Home > Database > Mysql Tutorial > body text

关于MySQL变量innodb_rollback_on_timeout一些讨论_MySQL

WBOY
Release: 2016-06-01 13:38:30
Original
1067 people have browsed it

bitsCN.com

1innodb_rollback_on_timeout变量

下面是MySQL官方手册关开innodb_rollback_on_timeout变量的说明:

In MySQL 5.0.13 and up, InnoDB rolls back only the last statement on a transaction timeout by default. If --innodb_rollback_on_timeout is specified, a transaction timeout causes InnoDB to abort and roll back the entire transaction (the same behavior as before MySQL 5.0.13). This variable was added in MySQL 5.0.32.

该变量默认值为OFF,如果事务因为加锁超时,会回滚上一条语句执行的操作。如果设置ON,则整个事务都会回滚。

 

下面通过一个示例来验证上面这段话。

2、示例

(1) innodb_rollback_on_timeoutOFF

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)

session2因为加锁超时,事务回退到上一条语句。 

 

(2) innodb_rollback_on_timeoutON

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_timeoutOFF,事务会回滚到上一个保存点,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_timeoutON,整个事务都会回滚。这可以从row_mysql_handle_errors函数中得到验证。

ibool
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,回滚事务。 

bitsCN.com
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template