在mysql命令行的默认下,事务都是自动提交的,sql语句提交后立刻会执行commit操做。所以开启一个事务必须使用begin,start transaction,或者执行 set autocommit=0;
可使用的事务控制语句mysql
start transction | begin : 显示的开启一个事务
commit (commit work)
commit work与completion_type的关系,commit work是用来控制事务结束后的行为,是chain仍是release的,能够经过参数completion_type来控制,默认为0(或者NO_CHAIN),表示没有任何操做 与commit效果同样。当completion_type=1的时候sql
mysql>setnames utf8;
Query OK, 0 rowsaffected (0.00 sec)
mysql> createtablet(aint,primarykey(a))engine=innodb;
Query OK, 0 rowsaffected (0.29 sec)
mysql> select@@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row inset(0.00 sec)
mysql> set@@completion_type=1;
Query OK, 0 rowsaffected (0.00 sec)
mysql> begin;
Query OK, 0 rowsaffected (0.00 sec)
mysql> insertintotselect1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> commitwork;
Query OK, 0 rowsaffected (0.00 sec)
mysql> insertintotselect2;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insertintotselect2;
ERROR 1062 (23000): Duplicate entry '2'forkey'PRIMARY'
mysql> rollback;
Query OK, 0 rowsaffected (0.00 sec)
# 回滚以后只有1这个记录,而没有2这个记录
mysql> select*fromt;
+---+
| a |
+---+
| 1 |
+---+
1 row inset(0.00 sec)
测试中,将completion_type设置成1,第一次经过commit work来insert这条记录。以后insert 2的时候并无启用begin(start transaction)来开启一个事务,以后再插入一条重复的记录2,这时会抛出异常rollback后,最后发现只有1这样一条记录,2并无被insert进去。由于completion_type为1的时候,commit work会开启另一个事务,所以2个insert语句是在同一个事务里面的,因此回滚后就没有insert进去。
服务器
参数completion_type为2时,commit work等同于commit and release。当事务提交时候会自动断开与db的链接,以下:ide
mysql>set@@completion_type=2;
Query OK, 0 rowsaffected (0.00 sec)
mysql> begin
-> ;
Query OK, 0 rowsaffected (0.00 sec)
mysql> insertintotselect3;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> commitwork;
Query OK, 0 rowsaffected (0.00 sec)
mysql> select@@versison;
ERROR 2006 (HY000): MySQL server has gone away
Noconnection. Tryingtoreconnect...
Connectionid: 205656
Currentdatabase: test
ERROR 1193 (HY000): Unknown system variable 'versison'
mysql>
经过上面的测试发现,completion_type设置成2时,commit work以后,再经过select获取db服务器版本信息的时候出现2006的error,说明以及断开了与db的链接。测试
rollback,rollback work与commit,commit work的工做原理同样。url
rollback(rollback work)
savepoint identifier:在事务中建立一个保存点,一个事务容许有多个保存点
release savepoint identifier:删除事务中的保存点,当时一个保存点也没有时执行这个命令,会报错抛出一个异常,以下所示:spa
mysql>begin;
Query OK, 0 rowsaffected (0.00 sec)
mysql> rollbacktosavepoint t1;
ERROR 1305 (42000): SAVEPOINT t1 does notexist
mysql>
innodb存储引擎中的事务都是原子性的,说明如下2种状况:
构成事务的每条语句都会commit,不然事务的每条语句都会rollback,这种保护还会涉及到单调的语句。一条语句要不完成成功要么彻底回滚,
可是一条语句失败并不会致使前一条执行的语句自动回滚,他们的工做会保留,须要你手动commit或者rollback。以下:.net
mysql>createtablet(aint,primarykey(a))engine=innodb;
Query OK, 0 rowsaffected (0.24 sec)
mysql> begin
-> ;
Query OK, 0 rowsaffected (0.00 sec)
mysql> insertintotselect1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insertintotselect1;
ERROR 1062 (23000): Duplicate entry '1'forkey'PRIMARY'
mysql> select*fromt;
+---+
| a |
+---+
| 1 |
+---+
1 row inset(0.00 sec)
mysql>
能够看到,插入第二条记录的时候,db抛出了1062错误,可是并无自动回滚,能查出前一条insert的记录,这个时候须要咱们手动commit或者rollback
rollback to [savepoint] identifier:与savepoint一块儿使用,能够把事务回滚到标记点,而不回滚在此标记点以前的任何工做。
set transaction:设置事务的隔离级别,4种事务隔离级别:read uncommitted,read committed,repeatable read,serializable。
start transaction与begin均可以在mysql命令行下显示的开启一个事务,可是在存储过程当中MySQL会自动将begin识别成begin ... end。
所以在存储过程当中,只能用start transaction。命令行