1、innodb_rollback_on_timeout變量
下面是MySQL官方手冊關開innodb_rollback_on_timeout變量的說明:
In MySQL
|
該變量默認值為OFF,如果事務因為加鎖超時,會回滾上一條語句執行的操作。如果設置ON,則整個事務都會回滾。
下面通過一個示例來驗證上面這段話。
2、示例
(1) innodb_rollback_on_timeout為OFF
Session 1
|
Session 2
|
mysql> create table tt(c1 int primary key, c2 int)engine=innodb;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into tt values(1, 1);
Query OK, 1 row affected (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from tt where c1=1 lock in share mode;
+----+------+
| c1 | c2 |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.00 sec)
|
|
|
mysql> begin; Query OK, 0 rows affected (0.00 sec)
mysql> insert into tt values(10,10); Query OK, 1 row affected (0.00 sec)
mysql> delete from tt where c1=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec)
mysql> rollback; Query OK, 0 rows affected (0.01 sec)
mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | +----+------+ 1 row in set (0.00 sec) |
mysql> select * from tt;
+----+------+
| c1 | c2 |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.00 sec)
|
|
|
mysql> begin; Query OK, 0 rows affected (0.00 sec)
mysql> insert into tt values(10,10); Query OK, 1 row affected (0.00 sec)
mysql> delete from tt where c1=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> commit; Query OK, 0 rows affected (0.02 sec)
mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec) |
(2) innodb_rollback_on_timeout為ON
Session 1
|
Session 2
|
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from tt where c1=1 lock in share mode;
+----+------+
| c1 | c2 |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.00 sec)
|
|
|
mysql> begin; Query OK, 0 rows affected (0.00 sec)
mysql> insert into tt values(11,11); Query OK, 1 row affected (0.00 sec)
mysql> delete from tt where c1=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec)
mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec) |
session2加鎖超時,整個事務回滾。
3、總結
innodb_rollback_on_timeout為OFF,事務會回滾到上一個保存點,InnoDB在執行每條SQL語句之前,都會創建一個保存點,參見代碼:
int
row_insert_for_mysql(
/* out: error code or DB_SUCCESS */
byte* mysql_rec, /* in: row in the MySQL format */
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
handle */
{
。。。
savept = trx_savept_take(trx);
。。。
|
如果事務因為加鎖超時,相當於回滾到上一條語句。但是報錯后,事務還沒有完成,用戶可以選擇是繼續提交,或者回滾之前的操作,由用戶選擇是否進一步提交或者回滾事務。
innodb_rollback_on_timeout為ON,整個事務都會回滾。這可以從row_mysql_handle_errors函數中得到驗證。
row_mysql_handle_errors(
/* ==================== */
/* out: TRUE if it was a lock wait and
we should continue running the query thread */
ulint* new_err, /* out: possible new error encountered in
lock wait, or if no new error, the value
of trx->error_state at the entry of this
function */
trx_t* trx, /* in: transaction */
que_thr_t* thr, /* in: query thread */
trx_savept_t* savept) /* in: savepoint or NULL */
{
...
else if (err == DB_DEADLOCK // 發生死鎖
|| err == DB_LOCK_TABLE_FULL
|| (err == DB_LOCK_WAIT_TIMEOUT
&& row_rollback_on_timeout)) {
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
trx_general_rollback_for_mysql(trx, FALSE, NULL); // 事務全部回滾
} else if (err == DB_OUT_OF_FILE_SPACE
|| err == DB_LOCK_WAIT_TIMEOUT) {
ut_ad(!(err == DB_LOCK_WAIT_TIMEOUT
&& row_rollback_on_timeout));
if (savept) { // 回滾到上一個保存點
/* Roll back the latest, possibly incomplete
insertion or update */
trx_general_rollback_for_mysql(trx, TRUE, savept);
}
/* MySQL will roll back the latest SQL statement */
...
問題:innodb_rollback_on_timeout為OFF,事務的原子性被破壞了嗎?
答:NO,從示例中可以看到,事務只是回退上一條語句的狀態,而整個事務實際上沒有完成(提交或者回滾),而作為應用程序在檢測這個錯誤時,應該選擇是提交或者回滾事務。如果嚴格要求事務的原子性,當然是執行ROLLBACK,回滾事務。
作者:MrDB
出處:http://www.cnblogs.com/hustcat/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。