I would say that innodb_rollback_on_timeout is a very important parameter. In this blog, I am going to explain “innodb_rollback_on_timeout” and how it affects the transaction behavior at the MySQL level. I describe two scenarios with practical tests, as it would be helpful to understand this parameter better.
The parameter Innodb_rollback_on_timeout will control the behavior of the transaction when a failure occurs with timeout.
Let’s conduct the test with the below scenarios:
I have created this table for testing purposes.
|
1 |
mysql> select * from rollback_on;<br>+----+-----------------+---------------------+<br>| id | name | c_date |<br>+----+-----------------+---------------------+<br>| 1 | jc | 2020-07-23 00:44:09 |<br>| 2 | sri | 2020-07-23 00:44:09 |<br>| 3 | hercules7sakthi | 2020-07-23 00:44:09 |<br>+----+-----------------+---------------------+<br>3 rows in set (0.01 sec) |
Below I share the steps which are common for testing both scenarios.
|
1 |
#my.cnf<br>innodb_rollback_on_timeout = OFF<br>innodb_lock_wait_timeout = 10 |
At s1,
|
1 |
mysql> begin;<br>Query OK, 0 rows affected (0.03 sec)<br><br>mysql> update rollback_on set name='sakthi' where id=2;<br>Query OK, 1 row affected (0.10 sec)<br>Rows matched: 1 Changed: 1 Warnings: 0 |
At s2,
|
1 |
mysql> begin;<br>Query OK, 0 rows affected (0.00 sec)<br><br>mysql> update rollback_on set name='herc' where id=3;<br>Query OK, 1 row affected (0.07 sec)<br>Rows matched: 1 Changed: 1 Warnings: 0 |
At s1,
|
1 |
mysql> begin;<br>Query OK, 0 rows affected (0.03 sec)<br><br>mysql> update rollback_on set name='sakthi' where id=2;<br>Query OK, 1 row affected (0.10 sec)<br>Rows matched: 1 Changed: 1 Warnings: 0<br><br>mysql> update rollback_on set name='sakthi' where id=3;<br>ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction <br><br>mysql> commit;<br>Query OK, 0 rows affected (0.05 sec)<br><br>mysql> select * from rollback_on;<br>+----+-----------------+---------------------+<br>| id | name | c_date |<br>+----+-----------------+---------------------+<br>| 1 | jc | 2020-06-21 18:28:03 |<br>| 2 | sakthi | 2020-06-21 18:28:03 |<br>| 3 | hercules7sakthi | 2020-06-21 18:28:03 |<br>+----+-----------------+---------------------+<br>3 rows in set (0.00 sec) |
|
1 |
#my.cnf<br>innodb_rollback_on_timeout = ON<br>innodb_lock_wait_timeout = 10 |
At s1,
|
1 |
mysql> begin;<br>Query OK, 0 rows affected (0.03 sec)<br><br>mysql> update rollback_on set name='sakthi' where id=2;<br>Query OK, 1 row affected (0.10 sec)<br>Rows matched: 1 Changed: 1 Warnings: 0 |
At s2,
|
1 |
mysql> begin;<br>Query OK, 0 rows affected (0.00 sec)<br><br>mysql> update rollback_on set name='herc' where id=3;<br>Query OK, 1 row affected (0.07 sec)<br>Rows matched: 1 Changed: 1 Warnings: 0 |
At s1,
|
1 |
mysql> begin;<br>Query OK, 0 rows affected (0.03 sec)<br><br>mysql> update rollback_on set name='sakthi' where id=2;<br>Query OK, 1 row affected (0.10 sec)<br>Rows matched: 1 Changed: 1 Warnings: 0<br><br>mysql> update rollback_on set name='sakthi' where id=3;<br>ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction <br><br>mysql> commit;<br>Query OK, 0 rows affected (0.05 sec)<br><br>mysql> select * from rollback_on;<br>+----+-----------------+---------------------+<br>| id | name | c_date |<br>+----+-----------------+---------------------+<br>| 1 | jc | 2020-06-21 18:28:03 |<br>| 2 | sri | 2020-06-21 18:28:03 |<br>| 3 | hercules7sakthi | 2020-06-21 18:28:03 |<br>+----+-----------------+---------------------+<br>3 rows in set (0.00 sec) |
Here I explicitly committed the transaction to explain the behavior of the parameter “innodb_rollback_on_timeout”.
As a DBA, I would always suggest enabling the parameter “innodb_rollback_on_timeout”. Or, your application should be good enough to handle the failed transactions. Maybe retry the failed SQL or ROLLBACK the entire transaction when the driver gets the ERROR 1205 and retry the transaction, which is something that needs to be done regardless of the value of the innodb_rollback_on_timeout value to maintain the atomicity from MySQL level. Note, you need to restart your MySQL instance to change the threshold of this parameter.