MySQL的事务隔离级别一共有四个,分别是读未提交、读已提交、可重复读以及可串行化。
默认是什么?
它是可重复读。
在两个终端里,打开两个mysql客户端。数据初始时,id为1, age为11
| 终端1 | 终端2 | 结论 |
|---|---|---|
| start transaction; | ||
| start transaction; | ||
| update t_user set age=1 where id=1 | ||
| select age from t_user where id=1 (结果是11) | 读未提交?NO | |
| commit; | ||
| select age from t_user where id=1 (结果是11) | 读已提交?NO 重复读到的一样?YES | |
| commit; |
结论:
在终端1里,未提交事务的修改、已提交的事务中的修改,在另一个事务中不可见。在另一个事务中,读多少次,结果都是一样的(age 11)。
所以,MySQL默认情况下,不是【读未提交】;不是【读已提交】;是【可重复读】。
for update
在两个终端里,打开两个mysql客户端。数据初始时,id为1, age为11
| 终端1 | 终端2 | 结论 |
|---|---|---|
| start transaction; | ||
| update t_user set age=12 where id=1 | ||
| select age from t_user where id=1 (结果是11) | 因为当前不是【读未提交】 | |
| commit; | ||
| select age from t_user where id=1 (结果是12) |
同样的实验和初始值,加上for update:
| 终端1 | 终端2 | 结论 |
|---|---|---|
| start transaction; | ||
| start transaction; | ||
| select age from t_user where id=1 for update (结果是11) | ||
| select age from t_user where id=1 (结果是11) | 另一个事务可以读 | |
| update t_user set age=12 where id=1 | 不执行,仿佛卡住了 | |
| update t_user set age=13 where id=1 | ||
| select age from t_user where id=1(结果是13) | ||
| commit; | ||
| 上面的update执行了 | for update的事务执行了commit,其它事务执行update | |
| select age from t_user where id=1(结果是12) |
结论:for update让其它事务可以读要操作的行,但是对它们的写,执行要等当前事务(执行了for update事务)提交以后。如果for update事务迟迟不提交(执行commit),另一个事务的写操作可能因为超时而退出它所在的整个事务,这时会抛出:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
参考:
https://www.cnblogs.com/gao88/p/12502593.html
https://developer.aliyun.com/article/743691
本文详细解析MySQL的四种事务隔离级别,重点讨论默认的可重复读与forupdate锁机制,通过实例演示了其行为差异。理解forupdate如何影响并发读写,以及可能遇到的Lockwait超时问题。
91

被折叠的 条评论
为什么被折叠?



