IT技术博客大学习 共学习 共进步

MySQL事务隔离级别的暗门

iMySQL 2016-02-29 23:57:29 浏览 1,963 次

0、导读

   我们知道,MySQL里可以动态修改事务隔离级别(TRANSACTIOIN ISOLATION LEVEL),既可以加 GLOBAL 关键字直接修改全局的设置,也可以加 SESSION 关键字只修改当前会话的设置。那么,如果两个关键字都不加,会出现什么情况呢?

1、调整事务隔离级别

   MySQL里,可以直接用 SET 指令调整事务隔离级别,既可以对全局调整,也可以只调整当前会话,其用法见下:

   SET [GLOBAL | SESSION] TRANSACTION

   [ REPEATABLE READ

   | READ COMMITTED

   | READ UNCOMMITTED

   | SERIALIZABLE ]

   我们都知道指定 GLOBAL 关键字是可以修改全局的设置,用这个方式修改完后,已经存在的连接还不会生效,只有对新建立的连接才会起作用。

   而指定 SESSION 关键字则是只修改当前连接会话的设置,修改完后立即生效,再次连接后会恢复成全局的设置,对其他连接/会话也不起作用。

   另外,如果都不指定 GLOBAL、SESSION 关键字,会发生什么情况呢?官方文档给出的解释是这样的:

   Without any SESSION or GLOBAL keyword, the statement applies to the next (not started) transaction performed within the current session. Subsequent transactions revert to using the SESSION isolation level.

   原文详见手册:13.3.6 SET TRANSACTION Syntax,出处链接:https://dev.mysql.com/doc/refman/5.6/en/set-transaction.html

   意思是说:采用这种方式设置后,本次连接当前事务还未起作用,要到下一个(尚未启动的)新事务才起作用,下一个事务结束后,又将恢复成本次 SESSION中原先的设置

2、实验演示

   为了证实上面的说法,我们可以做一个演示,详细过程见下:

T1T2
select @@tx_isolation;

   READ-COMMITTED

select @@tx_isolation;

   READ-COMMITTED

set transaction isolation level SERIALIZABLE;

   select @@tx_isolation;

   +—————-+

   | @@tx_isolation |

   +—————-+

   | READ-COMMITTED |

   这种方式调整完后,可以看到隔离级别还是RC



select @@tx_isolation;

   READ-COMMITTED

begin;

   select * from t;

   | a | b | c | d |

   +—+—+—+—+

   | 1 | 2 | 3 | 4 |



begin;

   select * from t;

   | a | b | c | d |

   +—+—+—+—+

   | 1 | 2 | 3 | 4 |

   update t set d = 5 where a = 1;

   被阻塞了,耐心等待中~

rollback;

Query OK, 1 row affected (13.13 sec)

   Rows matched: 1  Changed: 1  Warnings: 0

   等到T1执行rollback后才能继续,等了10多秒


rollback;
当前连接再次启动新事务测试
select @@tx_isolation;

   READ-COMMITTED

   可以看到隔离级别还是RC



select @@tx_isolation;

   READ-COMMITTED

begin;

   select * from t;

   | a | b | c | d |

   +—+—+—+—+

   | 1 | 2 | 3 | 4 |



begin;

   select * from t;

   | a | b | c | d |

   +—+—+—+—+

   | 1 | 2 | 3 | 4 |


update t set d = 20 where a = 1;

   Query OK, 1 row affected (0.00 sec)

   Rows matched: 1  Changed: 1  Warnings: 0

   立即完成,没有阻塞

rollback;

rollback;

   其中,测试表t的建表DDL:

   CREATE TABLE `t` (

   `a` int(11) NOT NULL,

   `b` int(11) NOT NULL,

   `c` int(11) NOT NULL,

   `d` int(11) NOT NULL,

   PRIMARY KEY (`a`,`b`),

   KEY `i_c` (`c`)

   ) ENGINE=InnoDB;

   该表中只有一条记录:

   SELECT * FROM t;

   +—+—+—+—+

   | a | b | c | d |

   +—+—+—+—+

   | 1 | 2 | 3 | 4 |

   +—+—+—+—+

3、建议

   如果需要全局调整事务隔离级别,最好是在 my.cnf 全局配置文件中直接设置好。

   而如果是要在当前会话中临时调整,可以不要加上 SESSION 关键字,这样的话,当前事务结束下一个新事务开始后,会自行恢复 SESSION 的设置,无需人为调整,更加方便。

建议继续学习

  1. 分布式系统的事务处理 (阅读 7,246)
  2. MySQL数据库分布式事务XA优缺点与改进方案 (阅读 4,645)
  3. 分布式事务性能分析 (阅读 4,623)
  4. MySQL数据库分布式事务XA的实现原理分析 (阅读 3,505)
  5. 关于sqlite的事务的使用 (阅读 3,443)
  6. Google Megastore系统事务机制 (阅读 3,245)
  7. Storm入门教程 第五章 一致性事务 (阅读 2,765)
  8. 深入剖析 redis 事务机制 (阅读 2,506)