Mysql事务隔离机制
在介绍什么是事务隔离机制前,先了解一下什么是事务
什么是事务
事务是在程序运行中一系列的多个操作,这个系列中的操作必须全部完成或全部失败,若有一个操作出现错误,则整个系列的所有操作均不会生效。
当所有操作执行成功时,称为提交事务,只有提交完毕,对于数据的操作才会真正生效。
当有一个操作失败时,事务中的所有操作都不会生效,并回滚已经执行的操作,返回到初始状态,称为回滚事务。
当事务a修改了某条数据尚未提交,有事务b修改同一条数据并提交,此时回滚事务a会回滚到何种状态?
这个场景不会成立,在不同事务中若修改同一条数据时会阻塞等待,当先修改的事务提交后后面修改的事务的修改操作才会进行。
事务的四个特征 (ACID)
事务具有4个基本特征: 原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )、持续性( Durability )
- 原子性(Atomicity)
原子性的表现形式即为上述事务的描述中的表现。
事务中的所有操作是数据库的一个逻辑工作单位,它们要么全部完成,要么全部取消。
- 一致性(Consistency)
务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
- 隔离性(Isolation)
多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
事务隔离机制的实现也是主要为了满足事务的隔离性。
- 持续性(Durability)
已被提交的事务对数据库的修改应该永久保存在数据库中。
MySQL的事务隔离机制
注意: 需要与Spring事务传播机制区分开
事务隔离级别是指若干个并发的sql事务之间的隔离程度,以及并发事务之间的读写策略。
Mysql中的事务隔离机制一共有四种:
- Read uncommited (未提交可读)
事务可以读取其他事务尚未提交的修改。
例如:
现数据库有记录 x = 1
事务a首先查询x得到1,此时a未提交,再启动一个事务b对x进行修改,执行 upadte 语句,更新为2,b不进行提交,
然后再由a查询x,这时候就可以得到x = 2,这就是读取到了b尚未提交的修改
- Read commited (提交可读)
事务不能读取到其他事务未提交的修改,
例如:
现数据库有记录 x = 1
事务a启动,对x执行更新操作,将x的值更新为2,事务a执行完后不提交再启动一个事务b查询x的值,此时查询得到的值为 x = 1
然后提交事务a,此时事务a对x的值的更新操作就可以被其他的事务所读取到了。
- Repeatable read (可重复读)
在当前事务提交之前,其他事务对数据的修改不会在本事务中生效,只有当前事务提交之后会被访问到。运用了行锁
例如:
现数据库有记录 x = 1
事务a启动,对x执行更新操作,将x的值更新为2,事务a执行完进行提交再启动一个事务b查询x的值,此时查询得到的值仍为 x = 1,事务a提交的操作并未在事务b中生效
- Serializable (序列化)
串行执行,完全隔离,运用了全表锁,事务执行时会使用全表锁,若有不同事务需要操作同一表中的数据,需要等待上一事务提交后才能执行。
虽然这个级别最安全最可靠,但由于其使用全表锁,所以导致性能极差,一边拿不推荐使用。
MySql并发一致性问题
若干个并发的事务之间主要可能会产生的并发一致性问题有:
- 脏读
一个事务读取了被另一个事务修改、但未提交(进行了回滚)的数据,造成两个事务得到的数据不一致。
- 不可重复读
在同一个事务中,在未提交之前不同时间查询到的数据发生了变化
- 幻读
当同一查询多次执行时,由于其它事务在这个数据范围内执行了插入操作,会导致每次返回不同的结果集
和不可重复读的区别:针对的是一个数据整体/范围;并且需要是插入操作
不同的事务隔离机制可能产生的并发一致性问题如下表
事务隔离机制 | 并发一致性问题 |
---|---|
Read uncommited (未提交可读) | 脏读、不可重复读、幻读 |
Read commited (提交可读) | 不可重复读、幻读 |
Repeatable read (可重复读) | 幻读 |
Serializable (序列化) | / |