mysql的隔离级别有四种:read uncommitted,read committed,repeatable read ,serializable
前面三种的区别 比较容易理解 。关键是第三种个第四种的区别 。
前段时间微信公众号上看到的一个例子,大致是这么说的:
- table credit上面记录了每个用户的消费记录,record1(小明,date1,消费5000元),record2(小明,data2,消费2000元)
- 有一条隐式约束,即小明的消费记录加载一期不能超过小明的信用额度1万元:5000+2000<10000
- 事务1,小明想消费了2000元,先去select sum(消费) from credit where user=小明;若sum(消费)< 10000,则允许小明此次消费2000元,向credit表中插入一条新的记录,否则交易失败;
- 事务2跟事务1相同,也是消费2000元;
- 如果事务1跟事务2完全串行,那么事务2不会交易成功
- 如果事务1未提交之前,事务2开始,那么
- 在read repeatable的隔离级别下,事务2也是可以执行的,因为事务2开始时,计算小明消费总额时,读取到的是credit表的快照,此时仍然是可以消费的;
- 如果级别是serializable的隔离级别,事务1在计算消费总额度时,会针对查询的范围都加上范围读锁,事务2执行的时候,发现事务1已经自己要读取的记录,加了范围锁,那么事务2会阻塞等待事务1提交或回滚。
- R两条记录A.count和B.count,if A.count+ B.count >1 然后W A=A-1。
- R两条记录A.count和B.count,if A.count+ B.count >1 然后W B=B-1。
https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html
http://www.evanjones.ca/db-isolation-semantics.html
补充,一些容易混淆的技术概念:
- 对于快照隔离,一般认为是一种隔离的级别,笔者更倾向于理解为隔离的技术,在此基础上可以实现不同的隔离级别,例如PG中对于serializable的实现,就是对SI隔离的升级为serializable snapshot isolation;
- SQL92事务隔离级别的定义是基于悲观锁的思想,例如教科书上的三级封锁协议的定义;商用数据库的实现过程中,多采用基于乐观锁的MVCC技术;商用DBMS事务隔离级别的定义,跟SQL92的标准是有所差别的。
- 不同的DBMS对于事务隔离级别的定义和实现相差非常大;例如DB2中最高隔离级别repeatable read,相当于mysql的serializable;DB2的cursor stability(锁住select查询游标指向的当前记录)在mysql并没有定义;
https://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.admin.perf.doc/doc/c0004121.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html
http://it.dataguru.cn/article-8406-1.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io