事务隔离级别(基于InnoDB引擎)
写锁
- 在进行增删改时,MySQL 会默认加上写锁 (排它锁)
- 在进行查询时,不会默认加锁。
- 读锁只排斥写锁,写锁排斥读锁和写锁
结论一:事务1执行更新语句(更新id=1的数据),其他任何事务执行更新语句(更新id=1的数据)都会等待。
结论二:事务1执行查询语句,不影响其他任何事务的更新、查询
结论三:事务1增加读锁(lock in share mode;对id=1的数据),其他任何事务都不能执行更新语句(对id=1的数据)
问题1: 有了结论一,是不是更改余额类的操作就不需要并发控制了?
- 结论:不是的。此结论只保证了原子类更新语句的并发;
- 比如:test表:id=1,value=1;
事务1:update test value SET value = value + 1 WHERE id = 1;
事务2:update test value SET value = value + 2 WHERE id = 1;
事务1:commit
事务2:commit
此时value = 4(正确)
原因:比如两个事务都要更改记录(id=1)的记录的value字段; - 反例:
比如:test表:id=1,value=100;
事务1:
select value FROM test WHERE id = 1
if value >= 100;
// 扣减30
update test value SET value = 70 WHERE id = 1;
事务2:
select value FROM test WHERE id = 1
if value >= 100;
// 扣减80
update test value SET value = 20 WHERE id = 1;
事务1commit;
事务2commit;
此时value = 20;但他应该被扣减了两次[30、80],值应该为-10 - 解决:
- 查询时就增加写锁
select value FROM test WHERE id = 1 for update - 使用乐观锁(cas)
update test value SET value = 20 WHERE id = 1 and value = 100
问题二:读锁有什么用?
待解答
可重复读
每一个语句在事务里在第一次读时,建立镜像,后续再读此语句都不会改变。
网友评论