各种非正常读
脏读
事务A读取到了事务B还未提交的数据,被称之为脏读。
不行重复读
在并发更新操作时,在同一次事务中,前后两次查询到的数据是不一样的。
幻读
在并发新增、修改时,在同一次事务中,前后两次查询到的数据量不一致。用户发生不行意料的问题
事务阻隔等级
能够处理脏读、幻读、不行重复读的问题。
阻隔等级 | 阻隔等级英文 | 脏读 | 幻读 | 不行重复读 | 加锁读 | 阐明 |
---|---|---|---|---|---|---|
读未提交 | Read UnCommitted (RU) | 是 | 是 | 是 | 否 | 能够读取到其它事物未提交的内容 |
读已提交 | Read Committed (RC) | 否 | 是 | 是 | 否 | 只能读取到其它事物提交成功的内容 |
可重复读 | Repeatable Read (RR) | 否 | 否 innoDB在外
|
是 | 否 | 读取某行后,不允许其它事物操作此行,直到事物结束 |
序列化 | Serializable | 否 | 否 | 否 | 是 | 等候其它事物执行完成后,依次执行,性能低,安全性高 |
MVCC并发版别操控
MVCC全称(Multiversion Concurrency Control)
在MySQL的InnoDB引擎下,RC、RR根据MVCC(多版别并发操控)进行并发事务操控,MVCC是根据数据版别来进行并发事务拜访的一种技能。
RR在MVCC下不能确保不发生幻读的问题。由于假如在两次快照读中心交叉了当时读,那么ReadView会被重新生成,因此或许会导致幻读的问题发生。既第一次读到了3条数据,第二次读到了2条数据。
UNDO_LOG
UNDO_LOG(回滚日志)版别链条
MySQL会在确定UNDO_LOG没有其它事务引用时才会删去。
ReadView
ReadView就是快照读SQL执行时,MVCC提取数据的依据。当时读不会运用MVCC。
- 快照读:就是最根底的查询句子。运用MVCC。
- 当时读:执行下列句子时读取数据的方法。运用行锁 间隙锁。
- INSERT、UPDATE、DELETE
- SELECT … FOR UPDATE
- SELECT … LOCL IN SHARE MODE
ReadView属性
- m_ids:当时活泼的事务id列表
- 活泼:没有commit、rollback的事务
- min_trx_id:最小活泼的事务id
- max_trx_id:预分配的事务id,最大事务编号 1
- cerator_trx_id:ReadView创建者的事务编号
ReadView生成机遇:
- 读已提交RC:每次读取都会生成新的ReadView
- 可重复读RR:会复用第一次生成的ReadView
- 由于所运用的ReadView是一模一样的,所以RR是可重复读的。
ReadView提取数据的逻辑
ReadView会根据自己的属性,去到UNDO_LOG中提取数据,提取的顺序由UNDO_LOG的事务号从大到小依次读取,假如当时不满足,就会往下接着找,最终找到符合条件的数据。规则如下。
- 判别当时事务id是否等于,ReadView创建者的事务id,假如是的话就阐明这个事务是自己的,能够拜访数据。
- 判别trx_id < min_trx_id,自己的事务id是否小于最小的活泼事务id,假如是的话阐明自己现已被提交了,能够拜访。
- 判别 trx_id > max_trx_id 假如自己的事务id大于ReadView生成时的最大事务ID,那么阐明自己还没有提交。不行以拜访。
- 判别 min_trx_id <= trx_id <= max_trx_id,假如当时事务id大于等于最小事务id,并且小于等于预分配事务id,建立的话就去活泼的事务id列表中查找,没找到,阐明自己被提交了,那就能够拜访,不然就不行以拜访。
参阅地址:IT老齐
Spring事务
三方操作怎么确保原子性
在开发事务的过程中,往往或许遇到这种场景,在数据库事务操作完毕后,给第三方组件、服务发送一条音讯、HTTP恳求。像这种操作假如直接写在事务内部,则有或许会影响主要事务代码的运转,假如写在外部,则无法确保事务操作与三方操作的原子性。
在Spring中供给了一个功用,事务回调接口