MySQL事务隔离级别以及各级别下的并发访问问题

事务隔离级别以及各级别下的并发访问问题

事务隔离级别
read uncommitted、read committed
事务并发访问引起的问题

更新丢失

MySQL事务隔离级别以及各级别下的并发访问问题这种情况,就会发现,出现一个更新丢失的问题。

脏读

我们设计一个场景,理解一下脏读

1.开启两个数据库sessions窗口,分别设置数据库事务隔离级别为read uncommitted
2. S1窗口,开启事务,更新id为1的余额1000-100,不提交事务
MySQL事务隔离级别以及各级别下的并发访问问题
3. S2窗口,开启事务,查询id为1的余额(900),已经产生脏读
MySQL事务隔离级别以及各级别下的并发访问问题
4. S1窗口,回滚事务,余额在S1看来是1000元了
MySQL事务隔离级别以及各级别下的并发访问问题
5. 此时S2窗口,更新900+200,提交事务
MySQL事务隔离级别以及各级别下的并发访问问题
6. 完蛋,用户莫名其妙丢100!

设置事务隔离级别为read committed(MySQL、Oracle默认级别)以上,防止读取未提交事务数据,设置后第二步S2会读取1000(S1未提交事务不被读取)

不可重复读

开启repeatable-read以上隔离级别解决,我们开启repeatable-read级别再试验

  1. S1开启事务,执行1000+500不提交
  2. 同时S2开启事务,查到1000(S2此时如果repeateble-read以下级别,S2多次读取会读取到1000突然变成1500)
  3. S1提交,此时S2查询仍然为1000(不重复读),拿到多少就是多少,不管别人改没改,我就是1000,这种模式下,我们要使用update set balance = balance+100这种就能避免使用旧数据进行更新

repeatable-read以上,会让事务读取到的信息,是开启事务时数据,不论别的事务是否 已经修改数据

幻读

幻读可以在serializable级别避免,查询操作都会加锁,更新更新操作会被blocking。(MySQL中repeatable-read下也会防止幻读)
幻读场景

  1. MySQL开启read-committed,S1开启事务,查询全表,共三条
  2. S2开启事务,执行插入,提交事务
  3. S1更新全表,发现更了四条,出现幻读

MySQL事务隔离级别以及各级别下的并发访问问题