mysql存在四个事物级别,最常用的是两个,提交读,重复读。
提交读,简单的理解就是在事物当中,可以读取到其他事物提交的数据。
比如,
1, 在事物A中执行语句 select * from user ;。
2, 在事物B中执行语句更新user表。
3, 在事物A中再次执行 select * from user, 结果数据没有变化。
4, 提交事物B。
5, 在事物A中继续执行 select * from user ,此时,结果数据发生变化。
重复读,也就是保证在Mysql的事物中,执行相同的查询语句,返回相同的结果,即使在之间数据发生修改也仍然如此。
1, 在事物A中执行语句 select * from user ;。
2, 在事物B中执行语句更新user表。
3, 在事物A中再次执行 select * from user, 结果数据没有变化。
4, 提交事物B。
5, 在事物A中继续执行 select * from user ,此时,结果数据没有发生变化。
通过这个流程,可以发现,重复读之间,B事物已经修改了数据,并切提交,但是对A事物没有影响。
然而重复读需要注意一个地方,那就是读。也就是数据读取一直之后,其他事物修改数据并提交事物不会影响数据结果。 然而有一种场景会出现另一种情况,
如下
1, 开启事物A,不执行查询
2, 在事物B中执行语句更新user表。
3, 提交事物B。
4, 在事物A中继续执行 select * from user ,此时,结果数据为事物B更新后的数据。
以上情况会导致一个问题就是在扣除库存时,可能导致重复数据存在。看看如下场景
1, 在A事物中,查看 到存在2个可售库存,并查看到可售物品A,B。
2,在B事物中,查看 到存在2个可售库存,并查看到可售物品A,B。
3,A事物减少1个库存,.
4, B事物减少一个库存,应为行锁的关系,阻塞等待A事物提交。
5, A事物查看到到可售物品,A.B。 讲A物品分配给用户,并提交事物,A事物结束。
6,B事物的阻塞因为A事物提交成功,因此减少库存成功。
7,B事物查看可售物品, 因为在步骤2已执行查询语句,导致查看到物品A,B都可以出售。
8,B事物将A物品分配给用户,并提交事物。
以上流程执行的结果就是A物品被重复分配。原因就是重复读导致的幻读情况,实际上在步骤7中,B事物读取的数据已经不在是数据库的实际数据。
解决以上问题的办法很简单。1,在事物实际使用之前,不执行相关的查询语句。此方法局限太大。
2,在分配数据之时,严格判断数据分配状态。