事务的隔离性及隔离级别
事务的四大特性(ACID)
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
MyISAM与InnoDB 的区别
InnoDB支持事务,MyISAM不支持事务
InnoDB支持外键
InnoDB是聚集索引,使用B+Tree作为索引结构
B+Tree和B-Tree
事务的隔离性
脏读
一个事务在处理过程中读取了另一个未提交的事务中的数据
不可重复读
对于数据中的某个数据,一个事务范围多次查询返回了不同的数据值,这是由于查询隔离期间,被另外一个事务修改并且提交了
不可重复读和脏读的区别是,脏读是某一个事务读取另一个事务未提交的脏数据,而不可重复读是读取了前一事务提交的数据
某些情况下,不可重复读不是问题,一般会以最后查询的结果为准
幻读
一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。如果事务都使用快照读,就不会产生幻读。
脏读”、“不可重复读”和“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。数据库实现事务隔离的方式,基本上可分为以下两种:
- 一种是在读取数据前,对其加锁,阻止其他事务对数据进行修改。
- 另一种是不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本,因此,这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC),也经常称为多版本数据库。
隔离级别
读未提交(read-uncommit):最低级别
读已提交(read-committed):可避免脏读情况发生
可重复读(repeatabler-read):确保事务可以多次从一个字段中读取相同的值,在此事务持续期间,禁止对其他事务对此字段的更新,可避免脏读和不可重复读
串行化(serializable):最严格的事务隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommit) | 是 | 是 | 是 |
读已提交(read-committed): | 否 | 是 | 是 |
可重复读(repeatabler-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
脏读和幻读区别
脏读:update/delete
幻读:insert
查看mysql当前事务隔离级别
select @@tx_isolation;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oh1GWmuv-1616629690518)(C:\Users\zyq zt\AppData\Roaming\Typora\typora-user-images\image-20210325071038454.png)]
在mysql设置隔离级别
set [glogal | session] transaction isolation level 隔离级别名称;
set tx_isolation=’隔离级别名称;’
MySQL可重复读隔离级别的实现原理
MySQL默认的隔离级别是可重复读,即:事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。 那么MySQL可重复读是如何实现的呢?
使用的的一种叫MVCC的控制方式 ,即Mutil-Version Concurrency Control,多版本并发控制,类似于乐观锁的一种实现方式
实现方式:
InnoDB在每行记录后面保存两个隐藏的列来,分别保存了这个行的创建时间和行的删除时间。这里存储的并不是实际的时间值,而是系统版本号,当数据被修改时,版本号加1
在读取事务开始时,系统会给当前读事务一个版本号,事务会读取版本号<=当前版本号的数据
此时如果其他写事务修改了这条数据,那么这条数据的版本号就会加1,从而比当前读事务的版本号高,读事务自然而然的就读不到更新后的数据了
幻读的解决方式:
很明显可重复读的隔离级别没有办法彻底的解决幻读的问题,如果我们的项目中需要解决幻读的话也有两个办法:
使用串行化读的隔离级别
MVCC+next-key locks:next-key locks由record locks(索引加锁/行锁) 和 gap locks(间隙锁,每次锁住的不光是需要使用的数据,还会锁住这些数据附近的数据)的结合,next-key lock 会锁定范围和自身行,比如select…where id<6,锁定的是小于6的行和等于6的行
s(索引加锁/行锁) 和 gap locks(间隙锁,每次锁住的不光是需要使用的数据,还会锁住这些数据附近的数据)的结合,next-key lock 会锁定范围和自身行,比如select…where id<6,锁定的是小于6的行和等于6的行