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
|