1、事务是什么?
事务是数据库一个不可分的工作单元,可以将多个操作步骤表示为一个步骤。
2、事务的四大特性
Atomicity原子性, Consistency一致性,Isolation隔离性,Durability持久性
3、事务中出现的异常状况
脏读:一个事务读取到了另一个事务未提交的数据
时间 | 事务1 | 事务2 |
1 | 插入id=2数据 | |
2 | 可以查询到id=2数据 | |
3 | 回滚事务,此时事务A查询到的id=2的数据就是脏数据 |
不可重复读
时间 | 事务1 | 事务2 |
1 | 查询id=2的数据,name值为张三 | |
2 | update name=李四 where id=2 | |
3 | 提交事务 | |
4 | 查询id=2的数据,name值为李四 |
幻读
当事务隔离级别为读已提交
时间 | 事务1 | 事务2 |
1 | 查询id>=1的数据,得到id为1,2的两条数据 | |
2 | 插入id=3,name=王五的数据 | |
3 | 提交事务 | |
4 | 再次查询id>=1的数据,得到id为1,2,3的三条数据 |
当事务隔离级别为可重复读
时间 | 事务1 | 事务2 |
1 | 查询id>=1的数据,得到id为1,2的两条数据 | |
2 | 插入id=3,name=王五的数据 | |
3 | 提交事务 | |
4 | 执行 update tab set name = 王五1 where id = 3,此时update执行的是当前读,会更新id=3的快照数据 | |
5 | 再次查询id>=1的数据,得到id为1,2,3的三条数据 |
4、锁介绍
两阶段锁协议
在InnoDB事务中,行锁是在用到的时候才加上的,但并不是不再用了就立刻释放,而是要等到事务commit或rollback才会释放
锁的类型
共享锁(shared lock)允许事务读一行数据
排它锁(exclusive lock)允许事务删除或更新一行数据
共享锁 | 排他锁 | |
共享锁 | 兼容 | 不兼容 |
排它锁 | 不兼容 | 不兼容 |
锁的算法
行锁(record lock)针对单行记录的锁
间隙锁(gap lock)锁定一个范围但不包含记录本身,注:在可重复读级别下存在
间隙锁+行锁(Next-Key Lock)锁定一个范围并且包含记录本身,每个next-key lock都是前开后闭区间,假设数据库里有3条记录0,5,10 那么就有(-∞,0]、(0,5]、(5,10]、(10,+∞]4个可能的next-key lock,注:在可重复读、串行化级别下才存在
5、快照读与当前读
多版本并发控制(MVCC):一行数据有多个版本,根据事务ID获取一致性读视图,数据版本相关内容维护在undo log里,注:在读已提交、可重复读级别下才存在,MVCC避免了锁的争抢,通过空间换时间保证了数据读取的正确性。
快照读:读取的是快照数据,不保证是最新数据
在读未提交、读已提交、可重复读隔离级别下,最普通的查询就是快照读
select * from table
当前读:读到的数据是最新数据
-- 共享锁 select ... lock in share mode -- 排它锁 select ... for update insert ... update ... delete ...
6、事务隔离级别
SQL标准定义了四个隔离级别
- 读未提交(READ UNCOMMITED)
特点:读的时候未对数据加锁,修改数据的时候对数据添加行级共享锁
效果:因为修改数据时候添加的是共享锁,所以会被其他事务读到,产生脏读的问题
- 读已提交(READ COMMIED)
特点:(快照读)读的时候会通过MVCC的一致性视图读到最新的、已提交事务的数据版本
效果:(快照读)因为通过MVCC读取的是已提交事务的数据版本,所以不会存在脏读。通过MVCC读到的数据,没有进行加锁操作, 所以其他事务仍然可以对读到的数据进行修改并提交,这时候再次读取就发生了不可重复读。
(当前读)通过显示加锁,防止了其他事务对其行数据的修改,从而避免了不可重复读
- 可重复读(REPEATABLE READ)
特点:(快照读)读的时候会通过MVCC的一致性视图读到开启事务时刻、已提交事务的最新数据版本
效果:(快照读)因为通过MVCC读取的是开启事务时刻,已提交事务的数据版本,所以无论其他事务怎么修改,看到的数据都是雷打不动的固定的数据版本,这时候再次读取就避免了不可重复读。因为在修改数据的时候使用了next-key lock,所以即使进行插入操作也会被锁阻塞,这样也避免了幻读情况的产生。在实际情况中,锁的算法比较灵活 ,根据sql语句的不同,和命中索引的区别,即有next-key lock+gap lock锁住更大范围的情况,也有在唯一索引场景 next-key lock退化成 record lock以及gap lock的情况
- 串行化(SERIALIZABLE)
脏读 | 不可重复读 | 幻读 | |
读未提交 | 未解决 | 未解决 | 未解决 |
读已提交 | 已解决 | 快照读未解决,可通过加锁解决 | 未解决 |
可重复读 | 已解决 | 已解决 | MVCC能解决部分场景 |
串行化 | 已解决 | 已解决 | 已解决 |
标签:lock,事务,快照,隔离,级别,提交,mysql,数据,id From: https://www.cnblogs.com/yulongzhang/p/17105489.html