文章内容

2023/1/10 15:25:33,作 者: 黄兵

innodb_rollback_on_timeout 理解

参数 Innodb_rollback_on_timeout 将控制发生超时故障时事务的行为。

  • 如果指定了 –innodb-rollback-on-timeout=OFF(默认),则 InnoDB 仅回滚事务超时的最后一条语句。
  • 如果指定了 –innodb-rollback-on-timeout=ON,事务超时会导致 InnoDB 中止并回滚整个事务。

让我们用以下场景进行测试:

  • Innodb_rollback_on_timeout = OFF 事务 
  • Innodb_rollback_on_timeout = ON 的事务

测试环境

我出于测试目的创建了此表。

mysql> select * from rollback_on;
+----+-----------------+---------------------+
| id | name            | c_date              |
+----+-----------------+---------------------+
|  1 | jc              | 2020-07-23 00:44:09 |
|  2 | sri             | 2020-07-23 00:44:09 |
|  3 | hercules7sakthi | 2020-07-23 00:44:09 |
+----+-----------------+---------------------+
3 rows in set (0.01 sec)


下面我分享了测试这两种情况的常用步骤。 

常见步骤

  • 创建两个 MySQL 会话(s1 和 s2)
  • 在 s1,创建事务并执行更新“name = 'sakthi' where id=2”。不要提交事务。
  • 在 s2,创建另一个事务并执行更新“name = 'herc' where id=3”。不要提交事务。
  • 在 s1,再次执行另一个更新“name = 'sakthi' where id=3”。它将产生超时错误,因为行 (id=3) 已被 s2 持有并锁定。
  • 在 s1,一旦第二次更新出现超时错误,就提交事务。 
  • 验证结果并将其与实际数据进行比较。

场景 1 – Innodb_rollback_on_timeout = OFF 的事务

#my.cnf
innodb_rollback_on_timeout = OFF
innodb_lock_wait_timeout = 10

在 s1,

mysql> begin;
Query OK, 0 rows affected (0.03 sec)

mysql> update rollback_on set name='sakthi' where id=2;
Query OK, 1 row affected (0.10 sec)
Rows matched: 1  Changed: 1  Warnings: 0

在 s2,

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update rollback_on set name='herc' where id=3;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0

在 s1,

mysql> begin;
Query OK, 0 rows affected (0.03 sec)

mysql> update rollback_on set name='sakthi' where id=2;
Query OK, 1 row affected (0.10 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update rollback_on set name='sakthi' where id=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 

mysql> commit;
Query OK, 0 rows affected (0.05 sec)

mysql> select * from rollback_on;
+----+-----------------+---------------------+
| id | name            | c_date              |
+----+-----------------+---------------------+
|  1 | jc              | 2020-06-21 18:28:03 |
|  2 | sakthi          | 2020-06-21 18:28:03 |
|  3 | hercules7sakthi | 2020-06-21 18:28:03 |
+----+-----------------+---------------------+
3 rows in set (0.00 sec)

概括:

  • 在 s1,我们在事务中有两个更新。
  • 一个更新完成,另一个更新失败。
  • 提交事务后,可以在完成更新的实际表中看到修改后的数据。
  • 它说明,如果 innodb_rollback_on_timeout=OFF,则整个事务不会在超时失败的情况下回滚。它将对已完成的 SQL 应用更改。

场景 2 – Innodb_rollback_on_timeout = ON 的事务

#my.cnf
innodb_rollback_on_timeout = ON
innodb_lock_wait_timeout = 10

在 s1,

mysql> begin;
Query OK, 0 rows affected (0.03 sec)

mysql> update rollback_on set name='sakthi' where id=2;
Query OK, 1 row affected (0.10 sec)
Rows matched: 1  Changed: 1  Warnings: 0

在 s2,

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update rollback_on set name='herc' where id=3;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0

在 s1,

mysql> begin;
Query OK, 0 rows affected (0.03 sec)

mysql> update rollback_on set name='sakthi' where id=2;
Query OK, 1 row affected (0.10 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update rollback_on set name='sakthi' where id=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 

mysql> commit;
Query OK, 0 rows affected (0.05 sec)

mysql> select * from rollback_on;
+----+-----------------+---------------------+
| id | name            | c_date              |
+----+-----------------+---------------------+
|  1 | jc              | 2020-06-21 18:28:03 |
|  2 | sri             | 2020-06-21 18:28:03 |
|  3 | hercules7sakthi | 2020-06-21 18:28:03 |
+----+-----------------+---------------------+
3 rows in set (0.00 sec)

概括:

  • 在 s1,我们在事务中有两个更新。
  • 一次更新完成,一次更新失败
  • 提交事务后,您可以看到已完成的更新没有发生任何修改。
  • 它说明,如果 innodb_rollback_on_timeout=ON,则在发生故障时将回滚整个事务。

结论

这里我我们通过实验提交事务来解释参数“innodb_rollback_on_timeout”的行为。 

作为 DBA,我总是建议启用参数“innodb_rollback_on_timeout”。或者,您的应用程序应该足以处理失败的事务。当驱动程序收到错误 1205 并重试事务时,可能会重试失败的 SQL 或回滚整个事务,无论 innodb_rollback_on_timeout 值的值如何,这都是需要完成的事情,以保持 MySQL 级别的原子性。请注意,您需要重启 MySQL 实例才能更改此参数的阈值。


文章来源于:The Transaction Behavior Impact of innodb_rollback_on_timeout in MySQL

分享到:

发表评论

评论列表