PostgreSQL 中如何处理数据的并发读写和事务隔离级别选择?

news2024/11/24 5:24:52
  • 🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
  • 📚领书:PostgreSQL 入门到精通.pdf

PostgreSQL

文章目录

  • PostgreSQL 中如何处理数据的并发读写和事务隔离级别选择
    • 一、并发读写的挑战
      • (一)数据一致性问题
      • (二)并发控制机制
    • 二、事务隔离级别
      • (一)读未提交
      • (二)读已提交
      • (三)可重复读
      • (四)串行化
    • 三、事务隔离级别的选择
      • (一)考虑因素
      • (二)实际案例
    • 四、并发读写和事务隔离级别的实际应用
      • (一)并发读写的处理
      • (二)事务隔离级别的选择

美丽的分割线


PostgreSQL 中如何处理数据的并发读写和事务隔离级别选择

在当今数据驱动的时代,数据库的并发读写和事务隔离级别选择是至关重要的。就好比在一个繁忙的交通路口,如何确保车辆(数据操作)能够安全、高效地通行(执行),同时避免碰撞(数据冲突)和混乱(不一致性),这是数据库管理系统需要解决的关键问题。PostgreSQL 作为一款强大的开源数据库,提供了丰富的功能来处理并发读写和事务隔离级别,以满足不同应用场景的需求。在本文中,我们将深入探讨 PostgreSQL 中如何处理数据的并发读写以及如何选择合适的事务隔离级别。

一、并发读写的挑战

在数据库中,并发读写是指多个事务同时对数据库进行读取和写入操作。这种并发操作带来了许多挑战,其中最主要的问题是数据一致性和并发控制。

(一)数据一致性问题

想象一下,有两个事务同时对一个账户余额进行操作。事务 T1 要从账户中取出 100 元,事务 T2 要向账户中存入 200 元。如果这两个事务并发执行,并且没有适当的控制机制,就可能会出现以下情况:

  • 丢失更新:事务 T1 读取了账户余额为 500 元,然后将其减去 100 元,准备将结果写回数据库。在 T1 还没有将结果写回之前,事务 T2 读取了账户余额为 500 元,然后将其加上 200 元,将结果 700 元写回数据库。此时,事务 T1 再将其计算的结果 400 元写回数据库,这样就覆盖了事务 T2 的操作,导致事务 T2 的更新丢失。
  • 脏读:事务 T1 将账户余额修改为 400 元,但还没有提交。此时,事务 T2 读取了账户余额为 400 元,然后根据这个值进行了一些操作。如果事务 T1 回滚,那么事务 T2 读取到的就是一个无效的值,这就是脏读。
  • 不可重复读:事务 T1 读取了账户余额为 500 元,然后进行了一些其他操作。在这个过程中,事务 T2 将账户余额修改为 700 元并提交。当事务 T1 再次读取账户余额时,得到的结果是 700 元,与第一次读取的结果不一致,这就是不可重复读。
  • 幻读:事务 T1 按照某个条件查询出了一些记录,然后进行了一些操作。在这个过程中,事务 T2 插入了一些符合事务 T1 查询条件的记录并提交。当事务 T1 再次按照相同的条件查询时,会发现多了一些记录,这就是幻读。

这些数据一致性问题会导致数据库中的数据出现错误,影响应用程序的正确性和可靠性。因此,数据库管理系统需要采取一些措施来避免这些问题的发生。

(二)并发控制机制

为了解决数据一致性问题,数据库管理系统采用了并发控制机制。并发控制机制的主要目的是确保多个事务能够并发执行,同时保持数据的一致性。常见的并发控制机制有两种:悲观并发控制和乐观并发控制。

1. 悲观并发控制

悲观并发控制认为在并发操作中数据冲突是很可能发生的,因此在事务执行过程中,会对数据进行加锁,以防止其他事务对数据进行修改。这种方式就好比在一个房间里,只有一个人能拿到钥匙进入房间进行操作,其他人必须等待这个人完成操作并交出钥匙后才能进入。悲观并发控制可以有效地避免数据冲突,但会降低并发度,因为在事务执行过程中,其他事务需要等待锁的释放。

在 PostgreSQL 中,悲观并发控制通过使用锁来实现。PostgreSQL 提供了多种锁模式,包括共享锁(Shared Lock)、排他锁(Exclusive Lock)、意向共享锁(Intention Shared Lock)、意向排他锁(Intention Exclusive Lock)等。不同的锁模式用于不同的场景,以满足不同的并发需求。

例如,当一个事务要读取数据时,它会申请共享锁。如果其他事务已经持有了排他锁,那么这个事务就需要等待排他锁的释放。当一个事务要修改数据时,它会申请排他锁。如果其他事务已经持有了共享锁或排他锁,那么这个事务就需要等待锁的释放。

2. 乐观并发控制

乐观并发控制认为在并发操作中数据冲突是不太可能发生的,因此在事务执行过程中,不会对数据进行加锁,而是在事务提交时检查是否存在数据冲突。如果存在数据冲突,那么事务就会回滚。这种方式就好比在一个操场上,大家可以自由地活动,只有在发生碰撞(数据冲突)时才会停下来解决问题。乐观并发控制可以提高并发度,但需要在事务提交时进行额外的检查,可能会增加一些开销。

在 PostgreSQL 中,乐观并发控制通过使用多版本并发控制(Multiversion Concurrency Control,MVCC)来实现。MVCC 是一种基于时间戳的并发控制机制,它为每个数据行保存多个版本,每个版本都有一个创建时间戳和一个删除时间戳。当一个事务读取数据时,它会读取符合其事务开始时间戳的版本。当一个事务修改数据时,它会创建一个新的版本,并将其标记为当前版本。这样,不同的事务可以看到不同版本的数据,从而避免了数据冲突。

例如,假设有一个表 accounts,其中包含一个字段 balance 表示账户余额。事务 T1 开始时,表中的数据如下:

idbalance
1500

事务 T1 读取了账户余额为 500 元,并将其减去 100 元,准备将结果写回数据库。此时,事务 T2 开始,并读取了账户余额为 500 元,然后将其加上 200 元,准备将结果写回数据库。在事务 T1 提交之前,事务 T2 提交了。此时,表中的数据如下:

idbalancexminxmax
170023

其中,xmin 表示创建该版本的事务 ID,xmax 表示删除该版本的事务 ID。当事务 T1 提交时,PostgreSQL 会检查是否存在数据冲突。由于事务 T1 读取的版本的 xmin 为 1,而事务 T2 提交后创建的新版本的 xmin 为 2,因此不存在数据冲突。事务 T1 可以成功提交,并创建一个新的版本,将账户余额修改为 400 元。此时,表中的数据如下:

idbalancexminxmax
140014
170023

通过使用 MVCC,PostgreSQL 可以有效地避免数据冲突,提高并发度。

二、事务隔离级别

事务隔离级别是指事务之间的隔离程度,它决定了一个事务在执行过程中能够看到其他事务的结果的程度。PostgreSQL 支持四种事务隔离级别:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。

(一)读未提交

读未提交是最低的事务隔离级别,在这个级别下,一个事务可以读取到其他事务未提交的数据,这可能会导致脏读、不可重复读和幻读等问题。读未提交的隔离级别就好比一个人在一个没有门的房间里工作,任何人都可以随时进入这个房间,看到他正在做的事情,这显然是不安全的。

在 PostgreSQL 中,读未提交的隔离级别可以通过以下语句设置:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

虽然读未提交的隔离级别可以提高并发度,但由于它存在严重的数据一致性问题,因此在实际应用中很少使用。

(二)读已提交

读已提交是大多数数据库系统的默认隔离级别,在这个级别下,一个事务只能读取到已经提交的数据,避免了脏读的问题,但仍然可能会出现不可重复读和幻读的问题。读已提交的隔离级别就好比一个人在一个有门但没有锁的房间里工作,只有当其他人完成工作并离开房间后,他才能进入房间,这样可以避免看到别人未完成的工作,但他可能会在不同的时间看到房间里的不同情况。

在 PostgreSQL 中,读已提交的隔离级别可以通过以下语句设置:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

读已提交的隔离级别在大多数情况下是足够的,它可以在保证数据一致性的前提下,提供一定的并发度。

(三)可重复读

可重复读是比读已提交更高的隔离级别,在这个级别下,一个事务在执行过程中,多次读取同一数据的结果是一致的,避免了不可重复读的问题,但仍然可能会出现幻读的问题。可重复读的隔离级别就好比一个人在一个有门有锁的房间里工作,只有他自己有钥匙,他可以在房间里自由地工作,不用担心别人会进来干扰他,但他可能会在房间外看到一些变化。

在 PostgreSQL 中,可重复读的隔离级别可以通过以下语句设置:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

可重复读的隔离级别适用于一些对数据一致性要求较高的场景,例如银行转账等。

(四)串行化

串行化是最高的事务隔离级别,在这个级别下,事务会按照串行的方式执行,避免了脏读、不可重复读和幻读等问题。串行化的隔离级别就好比一个人在一个独立的房间里工作,这个房间只有一个入口和一个出口,每次只能有一个人进入或离开,这样可以保证每个人的工作都是独立的,不会受到其他人的干扰。

在 PostgreSQL 中,串行化的隔离级别可以通过以下语句设置:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

串行化的隔离级别可以提供最高的数据一致性,但它的并发度最低,因此在实际应用中,只有在对数据一致性要求非常高,且并发度要求不高的场景下才会使用。

三、事务隔离级别的选择

选择合适的事务隔离级别是非常重要的,它需要根据具体的应用场景来决定。如果选择的隔离级别过高,会降低并发度,影响系统的性能;如果选择的隔离级别过低,会导致数据一致性问题,影响系统的正确性和可靠性。

(一)考虑因素

在选择事务隔离级别时,需要考虑以下几个因素:

  • 数据一致性要求:如果应用对数据一致性要求非常高,例如银行转账、财务报表等,那么应该选择较高的隔离级别,如可重复读或串行化。如果应用对数据一致性要求不高,例如一些查询统计类的应用,那么可以选择较低的隔离级别,如读已提交或读未提交。
  • 并发度要求:如果应用的并发度要求非常高,例如一些高并发的 Web 应用,那么应该选择较低的隔离级别,如读已提交或读未提交。如果应用的并发度要求不高,例如一些后台管理类的应用,那么可以选择较高的隔离级别,如可重复读或串行化。
  • 数据操作类型:如果应用中主要是读取操作,那么可以选择较低的隔离级别,如读已提交或读未提交。如果应用中主要是写入操作,那么应该选择较高的隔离级别,如可重复读或串行化。
  • 系统性能要求:如果系统对性能要求非常高,那么应该选择较低的隔离级别,以提高并发度。如果系统对性能要求不高,那么可以选择较高的隔离级别,以保证数据一致性。

(二)实际案例

为了更好地理解事务隔离级别的选择,我们来看一个实际的案例。假设有一个在线商城系统,其中包含一个订单表 orders 和一个库存表 inventory。当用户下单时,系统需要从库存表中扣除相应的库存数量,并将订单信息插入到订单表中。这个过程涉及到两个表的写入操作,因此需要保证数据的一致性。

在这个案例中,如果我们选择读未提交的隔离级别,那么可能会出现脏读的问题。例如,一个事务正在从库存表中扣除库存数量,但还没有提交,此时另一个事务读取了库存表中的数据,就会得到一个错误的结果。因此,读未提交的隔离级别不适合这个场景。

如果我们选择读已提交的隔离级别,那么可以避免脏读的问题,但仍然可能会出现不可重复读的问题。例如,一个事务读取了库存表中的库存数量,然后进行了一些其他操作。在这个过程中,另一个事务从库存表中扣除了一些库存数量并提交。当第一个事务再次读取库存表中的库存数量时,就会得到一个不同的结果。因此,读已提交的隔离级别也不太适合这个场景。

如果我们选择可重复读的隔离级别,那么可以避免不可重复读的问题。在这个隔离级别下,一个事务在执行过程中,多次读取同一数据的结果是一致的。因此,可重复读的隔离级别比较适合这个场景。

如果我们选择串行化的隔离级别,那么可以避免脏读、不可重复读和幻读的问题,但它的并发度最低,可能会影响系统的性能。在这个案例中,如果系统的并发度要求不高,那么可以选择串行化的隔离级别,以保证数据的一致性。如果系统的并发度要求较高,那么可以选择可重复读的隔离级别,在保证数据一致性的前提下,提高系统的性能。

四、并发读写和事务隔离级别的实际应用

为了更好地理解并发读写和事务隔离级别的实际应用,我们来看一个具体的示例。假设有一个论坛系统,其中包含一个帖子表 posts 和一个评论表 comments。当用户发表一个帖子时,系统会将帖子信息插入到 posts 表中,并为该帖子创建一个初始的评论数为 0。当用户发表评论时,系统会将评论信息插入到 comments 表中,并将该帖子的评论数加 1。

(一)并发读写的处理

在这个示例中,我们需要处理并发读写的问题,以避免数据一致性问题的发生。我们可以使用悲观并发控制或乐观并发控制来实现并发读写的处理。

1. 悲观并发控制

我们可以在插入帖子和更新评论数时使用排他锁,以避免其他事务对数据进行修改。例如,当用户发表一个帖子时,我们可以使用以下语句来插入帖子信息并获取排他锁:

BEGIN;
LOCK TABLE posts IN EXCLUSIVE MODE;
INSERT INTO posts (title, content) VALUES ('PostgreSQL 并发读写', '这是一个关于 PostgreSQL 并发读写的帖子');
UPDATE posts SET comment_count = 0 WHERE id = currval('posts_id_seq');
COMMIT;

在这个语句中,我们首先使用 BEGIN 语句开始一个事务,然后使用 LOCK TABLE 语句对 posts 表加排他锁,以避免其他事务对该表进行修改。然后,我们使用 INSERT INTO 语句插入帖子信息,并使用 UPDATE 语句将该帖子的评论数设置为 0。最后,我们使用 COMMIT 语句提交事务,释放锁。

当用户发表评论时,我们可以使用以下语句来插入评论信息并更新评论数:

BEGIN;
LOCK TABLE posts IN SHARED MODE;
LOCK TABLE comments IN EXCLUSIVE MODE;
INSERT INTO comments (post_id, content) VALUES (1, '这是一个很好的帖子');
UPDATE posts SET comment_count = comment_count + 1 WHERE id = 1;
COMMIT;

在这个语句中,我们首先使用 BEGIN 语句开始一个事务,然后使用 LOCK TABLE 语句对 posts 表加共享锁,以避免其他事务对该表进行修改,同时对 comments 表加排他锁,以避免其他事务对该表进行插入操作。然后,我们使用 INSERT INTO 语句插入评论信息,并使用 UPDATE 语句将该帖子的评论数加 1。最后,我们使用 COMMIT 语句提交事务,释放锁。

2. 乐观并发控制

我们可以使用 MVCC 来实现并发读写的处理。在 PostgreSQL 中,默认情况下就是使用 MVCC 来实现并发控制的。当用户发表一个帖子时,PostgreSQL 会为该帖子创建一个新的版本,并将其标记为当前版本。当用户发表评论时,PostgreSQL 会创建一个新的评论版本,并将该帖子的评论数加 1。由于 MVCC 是基于时间戳的,因此不同的事务可以看到不同版本的数据,从而避免了数据冲突。

(二)事务隔离级别的选择

在这个示例中,我们需要根据具体的需求来选择合适的事务隔离级别。如果我们希望在读取帖子和评论信息时,能够看到已经提交的数据,避免脏读的问题,那么我们可以选择读已提交的隔离级别。例如,我们可以使用以下语句来设置事务隔离级别:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

如果我们希望在读取帖子和评论信息时,能够保证多次读取的结果是一致的,避免不可重复读的问题,那么我们可以选择可重复读的隔离级别。例如,我们可以使用以下语句来设置事务隔离级别:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

美丽的分割线

🎉相关推荐

  • 🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!
  • 📚领书:PostgreSQL 入门到精通.pdf
  • 📙PostgreSQL 中文手册
  • 📘PostgreSQL 技术专栏
  • 🍅CSDN社区-墨松科技

PostgreSQL

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1928995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot之健康监控(Actuator)

1,基本介绍 Spring Actuator 是 Spring Boot 提供的一个扩展模块,用于监控和管理应用程序的生产环境。它通过 HTTP 端点暴露了大量的监控和管理功能,使得开发者可以在运行时查看应用程序的运行状况、配置信息、性能指标等。 主要功能&#…

重生奇迹mu游戏中的防御成功率

在重生奇迹游戏中,玩家通常除了追求高防御能力外,还会关注一种特殊属性——防御成功率。防御成功率的提高可以帮助玩家闪避攻击,并展现出无敌的效果,因此是防御技能的关键表现之一。 在游戏中,角色的防御成功率和敏捷属…

Zymo试剂盒产品目录,你了解过吗?

在加利福尼亚州奥兰治市的一个小车库里诞生,到今天的行业领导者,Zymo Research 的愿景是在生物医学领域产生积极影响,并为人类的更大福祉做出贡献。这一愿景涉及 Zymo Research的各个方面,并自 1994 年以来一直指导着公司的发展、…

Java | Leetcode Java题解之第231题2的幂

题目&#xff1a; 题解&#xff1a; class Solution {static final int BIG 1 << 30;public boolean isPowerOfTwo(int n) {return n > 0 && BIG % n 0;} }

高校节能环保建设

全球能源危机和环境保护问题日益严重。我国高等院校数量多&#xff0c;在校师生人数多。高等院校作为能耗消耗主体及其在校师生作为节能环保理念的重要传播群体&#xff0c;高校节能环保校园建设显得尤为重要。本文就节能环保校园建设中节能、节水和环保三个方面进行了思考&…

可视化作品集(13):智慧交通方向的这组大屏,绝对亮眼。

本期分享智慧交通方向的可视化化大屏&#xff0c;本期的视觉效果绝对亮眼。

ysoserial代码分析-反射

前言&#xff1a; ysoserial作为优秀的反序列化攻击工具&#xff0c;其提供的攻击调用链也是很简单好用&#xff0c;但是一直没有分析过其代码逻辑&#xff0c;最近有空正好分析了一下&#xff0c;对反序列化理解有更好的帮助 代码分析&#xff1a; 其代码中最重要的两个是反…

虚拟机 VMware Workstation- 安装详细步骤

目录 虚拟化概念VMware Workstation 简介一、安装准备1. 安装环境2. 软件下载 二、常见问题1. 虚拟机的【默认位置】会在C盘&#xff0c;盘符内存不够的建议改为D盘或别的盘符2. 验证许可证是否密钥是否成功。进入虚拟机点击【帮助】下的关于VMware Workstation(A)可以查看验证…

Android Stuido Gradle build编译报错原因排查

事情是这样的&#xff0c;在更新了支付宝sdk的aar文件后&#xff0c;运行项目&#xff0c;报错了。如下图&#xff1a; 但是没有给出更多错误信息。想尝试通过gradlew compileDebug --stacktrace来输出更多build时的信息&#xff0c;但没有得到更多有效信息。 接下来&#xff…

AI+ 资源数据分析运营助手

在数字化浪潮席卷全球的今天&#xff0c;资源管理&#xff0c;作为企业运营的中枢神经&#xff0c;正迎来一场由人工智能&#xff08;AI&#xff09;引领的智慧变革。从资源的智能分配到问题的瞬间解决&#xff0c;AI 正在重塑资源管理的每一个角落&#xff0c;让效率与精准成为…

13 IP层协议-网际控制报文协议ICMP

计算机网络资料下载&#xff1a;CSDNhttps://mp.csdn.net/mp_blog/creation/editor/140148186 为了更有效的转发IP数据报和提高交付成果的机会&#xff0c;在网际层使用了网际控制报文协议ICMP。ICMP允许主机或路由器报告差错情况和提供有关异常情况的报告。ICMP不是高层协议数…

十大护眼落地灯品牌哪个牌子好一点?十大落地灯品牌排行榜分享

十大护眼落地灯哪个牌子好一点&#xff1f;现在的孩子从早上睁开眼就开始学习&#xff0c;有时候还需要使用到电子产品辅助学习&#xff0c;长时间对着电子产品以及在不良的光线环境下&#xff0c;不仅会对孩子眼睛造成持续的刺激&#xff0c;损害我们的眼睛视力&#xff0c;加…

path+HTTP协议+IP+端口(nodejs)

一.path //导入 fs const fs require(fs); const path require(path); //写入文件 // fs.writeFileSync(__dirname /index.html, love); // console.log(__dirname /index.html);//resolve 解决 // console.log(path.resolve(__dirname, ./index.html)); // console.log(p…

Centos安装Nginx(手把手教学两种安装方式)

前言 在CentOS上安装Nginx&#xff0c;通常可以通过两种方式&#xff1a;使用YUM包管理器安装&#xff08;适用于官方仓库或EPEL仓库中包含的Nginx版本&#xff09;&#xff0c;或者从源代码编译安装&#xff08;适用于需要特定版本或自定义Nginx的情况&#xff09;。以下是两…

不要惊讶!就是这么6!最新发布,SD XL 虚幻引擎5光影高清模型

效果展示 提示词&#xff1a;1 sex girl,strapless,cleavage&#xff0c;glowing, solo, hood, red eyes, armor, looking at viewer, electricity, hood up, red background, gauntlets, glowing eyes, vambraces,(full_body:1.3)<lora:虚幻引擎5光影-XL_UE5-XL-V1【Unrea…

ChatGPT 深度解析:技术驱动的智能对话

在当今科技飞速发展的时代&#xff0c;ChatGPT 无疑成为了最耀眼的明星之一。它以其令人惊叹的智能对话能力&#xff0c;引发了全球范围内的广泛关注和热议。 ChatGPT 背后的技术堪称精妙绝伦。它基于深度学习算法&#xff0c;通过对海量数据的学习和分析&#xff0c;从而能够理…

[Vulnhub] Pinkys-PalaceV1 Squid http proxy+SQI+BOF

信息收集 IP AddressOpening Ports192.168.8.106TCP:8080,31337,64666 $ nmap -p- 192.168.8.106 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 8080/tcp open http nginx 1.10.3 |_http-title: 403 Forbidden |_http-server-header: nginx/1.10.3 …

基于java+springboot+vue实现的中药实验管理系统(文末源码+Lw)124

基于SpringBootVue的实现的中药实验管理系统&#xff08;源码数据库万字Lun文流程图ER图结构图开题报告演示视频软件包&#xff09; 系统功能&#xff1a; 本中药实验管理系统有管理员&#xff0c;教师&#xff0c;学生&#xff0c;实验员。 管理员功能有个人中心&#xff0c…

【Python爬虫教程】第5篇-使用BeautifulSoup查找html元素几种常用方法

文章目录 简介find()和find_all()字符串通过id查找通过属性查找通过.方式查找通过CSS选择器查找通过xpath查找正则表达自定义方法总结 简介 上一篇详细的介绍了如何使用Beautiful Soup的使用方法&#xff0c;但是最常用的还是如何解析html元素&#xff0c;这里再汇总介绍下查询…

识别 TON 生态系统中前10种加密资产,以bitget 钱包为例

元描述&#xff1a;想要找到下一个 100 倍加密货币投资&#xff1f;请密切关注这篇文章&#xff1b;它揭示了所有可能很快变得非常有价值的 TON 网络宝石。 由 Telegram 提供支持的 TON&#xff08;开放网络&#xff09;生态系统正在蓬勃发展&#xff01;这是一个充满激动人心的…