事务一致性的测试
框架:spring
数据库:innodb
spring事务的串行化
isolation=Isolation.SERIALIZABLE
多个串行化事务发生冲突会抛出死锁异常
串行化和不可重复读发生冲突的情况
事务1:串行化
事务2:不可重复读(默认隔离级别)
| 执行顺序 | 结果 |
|---|---|
| 1开启 - 2开启 - 2结束 - 1结束 | 事务1正常,事务2发生死锁异常 |
| 1开启 - 2开启 - 1结束 - 2结束 | 事务2的操作覆盖了事务1的操作 |
| 2开启 - 1开启 - 1结束 - 2结束 | 事务2的操作覆盖了事务1的操作 |
| 2开启 - 1开启 - 2结束 - 1结束 | 事务1正常,事务2发生死锁异常 |
总结:
- 事务1开启时给数据上锁,具体哪种锁没有研究
- 如果事务2先结束,提交事务时由于事务1没有释放锁,所以会发生死锁异常,这种结果可以保证一致性
- 如果事务2后结束,提交事务时事务1已经释放了锁,事务2使用旧数据更新数据库导致数据不一致
排他锁(悲观锁)
前提:需要保证一致的逻辑在一个事务中
先申请排他锁
加锁:select … for update
例如:
SELECT id, value
FROM t_pessimistic
WHERE id = 1
FOR UPDATE
会对查询结果的每行加排他锁
如果没有其他事务对查询结果中的任一行使用排他锁时可以成功获得锁,否则会阻塞直到获得锁
如果发生冲突的几率较低,每次都加锁会产生额外开销
适合发生冲突几率高的情况
乐观锁
代码中实现的乐观锁好像不太稳定
给需要保证一致性的表增加版本号字段
每次执行update或delete时,验证版本号,如果不一致就重试
如果发生冲突的几率较高,可能会重试多次,反而影响效率
适合发生冲突几率低的情况
总结
要保证数据的一致性,同一个表应该使用同一种锁
欢迎补充
版权声明:本文为qq_35433926原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。