事物的四种隔离级别

说到事物,一般的文章会从ACID开始讲,一直讲到事物的传播特性。

今天这篇文章就讲事物的隔离级别,不讲ACID,也不讲事物的传播特性。

在讲事物的隔离级别之前先来了解一下事物并发情况下可能会出现的三个问题,了解了这三个问题后,那么事物的隔离级别就很好理解了。

事物并发可能会引起的问题

脏读
  • 脏读指的是一个事物可以读取到另一个未提交事物的数据。

举个例子:A向B转账1000元买包。A开启事物并转账1000元给B,但是A的事物还没提交,此时A让B查看余额,B一看1000元到账了,就把包给A了。然后B拿着包就跑了,并且造了一个异常导致事物回滚,此时B会发现自己账户里刚刚到手的1000元又没有了,但是包已经被A拿跑了,导致人财两空。

这就是脏读,在B的事物里能查看到A事物未提交的数据。

不可重复读
  • 不可重复读指的是一个事物可以读取到另一个事物提交了的数据。会导致在一个事物里的两次查询结果可能会不一致。

举个例子:这次是A向B借1000元。B开启了一个事物看了一下自己账户余额只有700元,告诉B自己钱不够,此时事物还没有关闭,A不相信,让B再查一次看看,结果B当着A的面又查了一次,显示卡里还有1200元(B老婆刚刚给B转了500元)。A当场就炸了,你这明明有钱还说没有,B马上回应刚刚还没有的,A又怼回去,你这事物还没关闭,同一个事物内两次查询结果怎么会不一样?你就是不想接给我,哼!友尽。

这就是不可重复读,一个在B的事物里能查到B的老婆后提交的数据。

幻读
  • 幻读又叫虚读指的是在一个事物的查询重出现了之前未出现的数据。
  • 幻读和不可重复读的区别在于幻读针对的是数据库重数据增删带来的变化,而不可重复读针对的是对数据库中某一条数据的修改带来的变化。

举个例子:由于最近开支越来越大,A决定打印一份银行卡消费记录出来反思一下,于是去银行帮忙开启一个事物开始打印消费记录,正打印着呢,突然想了想还是打两份好一点,给一份给老婆也反思反思,于是在事物还没关闭的情况下又打印了一份消费记录。此时A的老婆正拿着卡在买买买,于是等两份消费记录一起打印出来的时候A就很蒙圈了,我这是在同一个事物里面的两次查询呀,怎么第二份消费记录还多了个2000块钱的包包,这银行是在骗我吧,不行,赶紧打投诉电话。

事物的四种隔离级别

上面已经分析了事物并发可能会引起的三个问题,那么这里再讲一下事物的隔离级别。

事物的隔离级别一共有四个:
- 读未提交(read-uncommitted)
- 读已提交(read-committed)
- 可重复读(repeatable-read)
- 序列化(serializable)

对着上面脏读、不可重复读和幻读来理解这四种事物隔离级别就很容易了,下面看一个表格:

事物隔离级别脏读幻读不可重复读
读未提交
读已提交不会
可重复读不会不会
序列化不会不会不会

通过上面的表格可以很清楚的看出每个隔离级别是否会发生哪种事物并发问题。

事物隔离级别性能问题

通过上面的表格可以看出事物隔离级别越高越安全,这里再来聊一下不同事物隔离级别的性能问题。

首先先来看一下不同事物隔离级别对于数据库的锁的问题:
- 读未提交:不会对数据库产生锁
- 读已提交:写数据只会锁住相应的行
- 可重复读:如果有索引(包括主键索引)的时候,以索引列为条件更新数据,会存在间隙锁间隙锁、行锁、下一键锁的问题,从而锁住一些行;如果没有索引,更新数据时会锁住整张表
- 序列化:读写数据都会锁住整张表

所以事物的隔离级别越高越能保证数据的完整性和一致性,但是对并发情况下性能的影响也就越大。

Mysql的默认隔离级别是可重复读;Sql Server和Oracle默认的事务隔离级别是读已提交。当然了这些默认的事物隔离级别都是可以修改的。

由于性能原因,一般不会将事务隔离级别设置成序列化,而只会设置成读已提交和可重复读,至于可能发生数据不一致的问题,可以使用乐观锁、悲观锁等方式去解决。


喜欢这篇文章的朋友,欢迎扫描下图关注公众号lebronchen,第一时间收到更新内容。
这里写图片描述

数据库事务的隔离级别是用于控制事务之间的可见性和并发行为的关键机制。根据隔离程度从低到高,数据库事务的四种标准隔离级别包括: - **读未提交(Read Uncommitted)**:这是最低的隔离级别,允许一个事务读取另一个事务尚未提交的数据。这种级别可能会导致脏读问题,但并发性能最好。[^2] - **读已提交(Read Committed)**:此级别确保事务只能读取到已经提交的数据,从而避免了脏读。然而,它仍然可能引发不可重复读的问题。[^2] - **可重复读(Repeatable Read)**:在此级别,事务在执行期间多次读取同一数据集时,能够保证结果一致,避免了脏读和不可重复读的问题。然而,它可能无法防止幻读现象。 - **串行化(Serializable)**:这是最高的隔离级别,通过强制事务串行执行来完全隔离事务之间的操作,从而避免脏读、不可重复读和幻读等所有并发问题。尽管提供了最强的隔离性,但它的并发性能最差,通常不推荐在高并发环境中使用。[^1] 此外,某些数据库系统还提供了更细粒度的隔离级别或变种,例如 **快照隔离(Snapshot Isolation)**,它通过多版本并发控制(MVCC)机制提供了一种更高效的并发控制方式,同时避免了部分并发问题。 ### 数据库隔离级别与并发问题的关系 不同的隔离级别对并发问题的处理能力不同,下表总结了各隔离级别能够避免的并发问题: | 隔离级别 | 脏读 | 不可重复读 | 幻读 | |--------------------|------|-------------|------| | Read Uncommitted | 可能 | 可能 | 可能 | | Read Committed | 否 | 可能 | 可能 | | Repeatable Read | 否 | 否 | 可能 | | Serializable | 否 | 否 | 否 | 在实际应用中,选择合适的隔离级别需要权衡数据一致性和系统性能。 ### 查询 MySQL 的默认隔离级别 在 MySQL 中,可以通过以下 SQL 语句查询当前数据库实例的默认全局隔离级别: ```sql SELECT @@global.tx_isolation; ``` 同样,可以通过以下语句查看当前会话的隔离级别: ```sql SELECT @@session.tx_isolation; ``` 这些信息可以帮助开发者和数据库管理员了解当前数据库的事务行为,并根据实际需求调整隔离级别以优化性能和一致性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值