在存取银行系统时,如果遇到同时存取一个账户,系统应该如何处理? 许多人可能考虑线程同步,但在APP应用层上使用同步会锁定对象,严重影响并发效率。 此时,通过利用数据库的事务隔离机制,可以很好地解决这个问题。 本文详细掌握了事务隔离的详细知识。
1 .数据库事务的隔离级别
事务隔离从低到高有四个级别,分别是读不建议、读建议、可复制读和序列化。 较低的隔离级别通常支持较高的并发处理,具有较低的开销。
通俗易懂,结合场景说明各级含义和问题。 首先,必须了解事务具有ACID特性,事务行为具有开始、提交和回滚进程。
1.1读取未确认的不同事务a、b; a的数据还没有提交,b可以查询已经a没有提交的数据。
问题:并发事务a,B:A试图将工资表中工资为5000的记录更改为8000,但在没有提交commit事务之前发现8000错误,因此ROLLBACK将终止此事务同时b正在调查工资表,表示工资是8000,不是5000。 也就是说,b读取了a还没有提交的数据,b读取了b不应该看到的脏数据。
MySQL示例settransactionisolationlevelreaduncommitted事务处理a更新表:
事务b并发查询:
事务a回滚和最终结果:
1.2在提交read committed事务处理a的数据之前,事务处理b无法看到事务处理a提交的数据。
问题:假设并行事务a,B:A从工资表上的8000个工资记录中减去5000,再减去commit。 事务b查询工资表为8000后仍需扣除5000,但此时a已扣除5000,正反只剩下3000,不能扣除5000。 也就是说,在事务b的单元格内,两次查询的结果一次为8000,一次为3000,前后不一致(不能重复读取)。
MySQL示例settransactionisolationlevelreadcommitted事务b查询:
更新并提交事务a表:
发送事务b的重发查询:
1.3在repeatable read这两个事务单元中,对同一记录的查询结果相同,而其他事务的干预不会导致结果不一致。 也就是说,当开始查询事务时,查询的记录将被锁定,直到事务结束。
问题:插入新记录被锁定,无法成为幻读。
MySQL示例settransactionisolationlevelrepeatableread事务a查询:
事务b更新:
事务a再次进行查询,发现b的更新未在表中更新,a读取的数据前后一致:
1.4序列化是最高的事务隔离级别。 在此级别,事务按顺序执行,因此不仅可以避免脏读、不可重复读,还可以避免幻像读,但成本最高,性能最低,一般不太使用。 这里不怎么说明。
1.5总结
2 .每个数据库的默认隔离级别
2.1 MySQL Oracle
MySQL :可重复读取
Oracle :读取推荐
2.2 DB2
DB2隔离级别分为以下四类:
1 .可重复读取(可重复读取,RR ) )。
2 .读取稳定性(读取稳定性,RS ) :与可重复读取的隔离级别相同
3 .游标稳定性(Cursor Stability,CS ) :使用游标稳定性隔离级别时,当事务通过游标从表中检索行时,其他事务无法更新或删除游标引用的行
4 .未读(未指定读取(UR ) ) ) ) ) ) ) ) ) ) ) ) ) )
DB2的缺省隔离级别是游标稳定性(CS )
参考资料