When using the MySQL database, sometimes ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction such error. In a transaction, if one occurs when a sql execute this error, other scripts of the transaction would affect it, later if the commit operation results statement before being given the success of it? This result is isolation level and innodb_rollback_on_timeout parameter settings.
Note: MySQL default isolation level is REPEATABLE-READ, innodb_rollback_on_timeout is OFF, Based innodb table (support services) to be tested.
1. Preparations
1.1 Test Environment
MySQL 8.0
1.2 Create a test table and prepare data
Create a test table and insert a record
mysql> use testdb; Database changed mysql> create table test1(id int primary key,name varchar(20)); Query OK, 0 rows affected (0.01 sec) mysql> insert into test1 values(1,'1wdrt5'); Query OK, 1 row affected (0.00 sec) mysql> select * from test1; +----+--------+ | id | name | +----+--------+ | 1 | 1wdrt5 | +----+--------+ 1 row in set (0.00 sec)
The following will be tested according to the different levels of isolation and start-stop situation innodb_rollback_on_timeout.
2. test procedure
2.1 isolation level REPEATABLE-READ & innodb_rollback_on_timeout = OFF
a) the testing process:
session A | session B |
mysql> begin;
mysql> select * from test1; |
mysql> begin; mysql> select * from test1;
|
b) Test results:
隔离级别REPEATABLE-READ & innodb_rollback_on_timeout =OFF (2个参数均为默认值)的情况下,即使事务中有超时回滚报错,超时前的sql不会回滚,依旧执行成功。
2.2 隔离级别为READ-COMMITTED & innodb_rollback_on_timeout =OFF
a) 测试过程
session A | session B |
mysql> show global variables like 'transaction_isolation';
mysql> commit; mysql> select * from test1; |
mysql> begin;
|
b)测试结果:
隔离级别为READ-COMMITTED & innodb_rollback_on_timeout =OFF 情况下,即使事务中有超时回滚报错,超时前的sql不会回滚,依旧执行成功,同2者均为默认值的情况。
2.3 隔离级别REPEATABLE-READ & innodb_rollback_on_timeout =ON
注: innodb_rollback_on_timeout不能在线修改,需要修改配置文件后重启生效
测试过程:
a) 修改配置文件,重启数据库
在my.cnf文件里添加innodb_rollback_on_timeout=on 再重启数据库即可生效
mysql> show global variables like 'transaction_isolation'; +-----------------------+-----------------+ | Variable_name | Value | +-----------------------+-----------------+ | transaction_isolation | REPEATABLE-READ | +-----------------------+-----------------+ 1 row in set (0.00 sec) mysql> show global variables like 'innodb_rollback_on_timeout'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | innodb_rollback_on_timeout | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
b) 事务测试过程
session A | session B |
mysql> select * from test1;
mysql> commit; |
mysql> use testdb; |
c) 测试结果:
隔离级别REPEATABLE-READ & innodb_rollback_on_timeout =ON 的情况下,事务中有超时回滚报错时,超时前sql也会回滚。
2.4 隔离级别为READ-COMMITTED & innodb_rollback_on_timeout =ON
a) 参数调整
mysql> set global transaction_isolation='READ-COMMITTED'; mysql> exit # 重新登录 mysql> show global variables like 'transaction_isolation'; +-----------------------+----------------+ | Variable_name | Value | +-----------------------+----------------+ | transaction_isolation | READ-COMMITTED | +-----------------------+----------------+ 1 row in set (0.00 sec) mysql> show global variables like 'innodb_rollback_on_timeout'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | innodb_rollback_on_timeout | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
b) 测试过程
session A | session B |
mysql> use testdb;
mysql> commit; |
mysql> use testdb; |
c) 测试结果
隔离级别为READ-COMMITTED & innodb_rollback_on_timeout =ON的情况下,即使事务中有超时回滚报错,超时前的sql不会回滚,依旧执行成功,同2者均为默认值的情况。
3. 小结
在MySQL8.0 中,仅有在隔离级别为READ-COMMITTED & innodb_rollback_on_timeout =ON情况下,事务中有超时回滚报错时,超时前sql也会回滚。
隔离级别 | innodb_rollback_on_timeout | 结果 |
REPEATABLE-READ | OFF | 超时回滚前的SQL不会自动回滚 |
READ-COMMITTED | OFF | 超时回滚前的SQL不会自动回滚 |
REPEATABLE-READ | ON | 超时回滚前的SQL会自动回滚 |
READ-COMMITTED | ON | 超时回滚前的SQL不会自动回滚 |
TIPS:
1) 测试过程中可以查看information_schema.innodb_trx表观察事务情况,在不同的版本中事务情况不一样.例如,隔离级别REPEATABLE-READ & innodb_rollback_on_timeout=on的情况下,MySQL5.6 中整个事务回滚后会自动创建一个事务,而MySQL5.7则不会再自动创建事务。
2) 在生产环境使用中,建议将innodb_rollback_on_timeout 设置为ON。应用程序一定要做好事务控制,在一个事务出现异常时必须进行显式rollback