一文彻底读懂PostgreSQL事务隔离级别

SQL标准定义了四种隔离级别。隔离级别从低到高分别是:Read uncommitted 、Read committed 、Repeatable read 、Serializable。在各个隔离级别上被禁止出现的现象是:

  • 脏读:一个事务读取了另一个并行未提交事务写入的数据。
  • 不可重复读:一个事务重新读取之前读取过的数据,发现该数据已经被另一个事务(在初始读之后提交)修改。
  • 幻读:一个事务重新执行一个返回符合一个搜索条件的行集合的查询, 发现满足条件的行集合因为另一个最近提交的事务而发生了改变。
  • 序列化异常:成功提交一组事务的结果与这些事务所有可能的串行执行结果都不一致。

看到这里估计你还是一脸懵逼,没弄明白事务的隔离级别到底是啥。下面我们结合例子来一一阐述它们的概念与联系。

  • Read uncommitted

读未提交,指的就是一个事务可以读取另一个未提交事务的数据。

打个比方:你打算在网上买一台新的电脑,看到一家店中原价6000的电脑,现价只要998,没错,只要998。但是当你开开心心去付款的时候,价格又变成了6000,为啥呢?原来店家老板在输入商品单价的时候(事务开始),不小心按错写成998了,但是事务还没有提交,这时被你看见了,可老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成6000再提交。

小结:商品价格还是原先的6000,但是你却看到了998。这是老板输错了还没提交的数据,这就是脏读。

那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。

  • Read committed

读提交,就是指一个事务要等另一个事务提交后才能读取数据。

打个比方:尽管你发现这台电脑不是998,而是6000,因为你很喜欢,所以咬咬牙还是决定用卡里最后的6000块买下这台电脑。当你开始支付订单时(事务开始),收费系统事先检测到你的卡里有6000块。但是当收费系统准备扣款时,再检测卡里的金额,发现钱不够了。你还在纳闷为啥的时候,你收到一条短信:恭喜您成功续费xxx视频的会员!原来你之前购买的xxx视频的会员在这个时候自动续费了,扣掉了20块,导致你没钱买电脑了(第二次检测金额就是等待会员续费转出金额事务提交完)。

说明:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。

那怎么解决可能的不可重复读问题?Repeatable read 。

  • Repeatable read

重复读,就是在开始读取数据(事务开启)时,不再允许修改操作。

扫描二维码关注公众号,回复: 10907760 查看本文章

举例:你终于等到发工资了,这时你卡里有钱去买电脑了。当你支付订单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统检测到你卡里有6000块,现在不允许其它事务从你的卡里扣钱了,你终于如愿买到新电脑了。

说明:利用重复读终于可以解决不可重复读问题了。但是要注意的是:不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

  • 幻读:

买完电脑之后,你想看看今天的账单,看看卡里还是多少钱。看到确实是花了6000元,还剩1000块,就在这个时候,你的视频会员又给你自动续费了,即新增INSERT了一条消费记录,并提交。当你打印出自己的账单时,发现卡里980了,怎么少了20块,似乎出现了幻觉,这就是幻读。

那怎么解决幻读问题?Serializable!

  • Serializable 序列化

Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

总结:
最后说明下,在PostgreSQL中你虽然可以请求四种标准事务隔离级别中的任意一种,但是内部只实现了三种不同的隔离级别,即 **PostgreSQL 的读未提交模式的行为和读已提交相同。**这是因为把标准隔离级别映射到 PostgreSQL 的多版本并发控制架构的唯一合理的方法。
在这里插入图片描述

参考链接:
https://www.postgresql.org/docs/12/transaction-iso.html

发布了155 篇原创文章 · 获赞 88 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/105198086