PostgreSQL 事务并发锁

文章目录

  • PostgreSQL 事务
    • 大家都知道的 ACID
    • 事务的基本使用
    • 保存点
  • PostgreSQL 并发
    • 并发问题
    • MVCC
  • PostgreSQL 锁机制
    • 表锁
    • 行锁
  • 总结

PostgreSQL 事务

大家都知道的 ACID

在日常操作中,对于一组相关操作,通常要求要么都成功,要么都失败。在关系型数据库中,称这一组操作为事务。为了保证整体事务的安全性,有ACID这一说:

  • 原子性A:事务是一个最小的执行单位,一次事务中的操作要么都成功,要么都失败。
  • 一致性C:在事务完成时,所有数据必须保持在一致的状态。(事务完成后吗,最终结果和预期结果是一致的)
  • 隔离性I:一次事务操作,要么是其他事务操作前的状态,要么是其他事务操作后的状态,不存在中间状态。
  • 持久性D:事务提交后,数据会落到本地磁盘,修改是永久性的。

PostgreSQL相比于其他数据库,有一个比较大的优化,DDL也可以包含在一个事务中。比如集群中的操作,一个事务可以保证多个节点都构建出一个表,才算成功。

事务的基本使用

PostgreSQL跟MySQL一样,是自动提交事务的。

可以基于关闭PostgreSQL的自动提交事务来进行操作。

image.png

但是上述方式比较麻烦,传统的方式。

也可以根据命令处理一个事务:

  • begin:开始事务
  • commit:提交事务
  • rollback:回滚事务
-- 开启事务
begin;
-- 操作
insert into test values (7,'bbb',12,5);
-- 提交事务 
commit;

保存点

在PostgreSQL中,保存点(savepoint)用于在事务中创建中间状态,点允许在事务过程中设置临时的“检查点”,以便在必要时回滚事务的一部分。

比如项目中有一个大事务操作超时,回滚成本太高。针对大事务,可以拆分成几个部分,每个部分完成后,构建一个保存点,如果后面操作超时了,回滚到保存点,继续重试。

-- savepoint操作
-- 开启事务
begin;
-- 插入一条数据
insert into test values (8,'铃铛',55,11);
-- 添加一个保存点
savepoint ok1;
-- 再插入数据,比如出了一场
insert into test values (9,'大唐官府',66,22);
-- 回滚到之前的提交点
rollback to savepoint ok1;
-- 就可以开始重试操作,重试成功,commit,失败可以rollback;
commit;

PostgreSQL 并发

并发问题

在不考虑隔离性的前提下,事务的并发可能会出现的问题:

  • 脏读:读到了其他事务未提交的数据。(必须避免这种情况)
  • 不可重复读:同一事务中,多次查询同一数据,结果不一致,因为其他事务修改造成的。(一些业务中这种不可重复读不是问题)
  • 幻读:同一事务中,在修改某个数据后,再次查询还是之前的数据,因为其他事务对数据进行了更新,这种现象为幻读。

针对这些并发问题,关系型数据库有一些事务的隔离级别,一般用4种。

  • READ UNCOMMITTED:读未提交
  • READ COMMITTED:读已提交,可以解决脏读(PGSQL默认隔离级别)
  • REPEATABLE READ:可重复读,可以解决脏读和不可重复读(MySQL默认是这个隔离级别,PGSQL也提供了,但是设置为可重复读,效果还是串行化)
  • SERIALIZABLE:串行化

PGSQL在老版本中,只有两个隔离级别,读已提交和串行化,在PGSQL中不存在脏读问题。

MVCC

PostgreSQL中,在事务的并发问题里,也是基于MVCC多版本并发控制去维护数据的一致性。详细内容见多版本并发控制MVCC

首先要清楚,为啥要有MVCC?

如果一个数据库,频繁的进行读写操作,为了保证安全,采用锁的机制。但是如果采用锁机制,如果一些事务在写数据,另外一个事务就无法读数据,会造成读写之间相互阻塞。 所以大多数的数据库都会采用一个机制 多版本并发控制 MVCC 来解决这个问题。

MVCC是一种并发控制的方法,它通过保存数据的多个版本来实现并发访问。在MVCC中,每个事务在开始时获取一个唯一的版本号,然后读取和修改数据时都会带上这个版本号。这样,每个事务只能看到自己的版本号小于或等于自己的数据版本,从而实现了并发访问。

PGSQL中,每张表都会自带两个字段

  • xmin:给当前事务分配的数据版本。如果有其他事务做了写操作,并且提交事务了,就给xmin分配新的版本。
  • xmax:当前事务没有存在新版本,xmax就是0。如果有其他事务做了写操作,未提交事务,将写操作的版本放到xmax中。提交事务后,xmax会分配到xmin中,然后xmax归0。

image.png

基于上图的操作查看效果

事务A

-- 左,事务A
--1、开启事务
begin;
--2、查询某一行数据,  xmin = 630,xmax = 0
select xmin,xmax,* from test where id = 8;
--3、每次开启事务后,会分配一个事务ID 事务id=631
select txid_current();
--7、修改id为8的数据,然后在本事务中查询   xmin = 631, xmax = 0
update test set name = '铃铛' where id = 8;
select xmin,xmax,* from test where id = 8;
--9、提交事务
commit;

事务B

-- 右,事务B
--4、开启事务
begin;
--5、查询某一行数据,  xmin = 630,xmax = 0
select xmin,xmax,* from test where id = 8;
--6、每次开启事务后,会分配一个事务ID 事务id=632
select txid_current();
--8、事务A修改完,事务B再查询  xmin = 630  xmax = 631
select xmin,xmax,* from test where id = 8;
--10、事务A提交后,事务B再查询  xmin = 631  xmax = 0
select xmin,xmax,* from test where id = 8;

PostgreSQL 锁机制

当然,PostgreSQL也支持表锁和行锁,来控制并发访问。PostgreSQL中主要有两种锁,一个表锁一个行锁。

表锁

表锁就是锁住整张表,也分为很多中模式,其中最核心的两个:

  • ACCESS SHARE:共享锁(读锁),读读操作不阻塞,但是不允许出现写操作并行
  • ACCESS EXCLUSIVE:互斥锁(写锁),无论什么操作进来,都阻塞。

具体的可以查看官网文档。

PostgreSQL中表锁的实现:

image.png

基于LOCK开启表锁,指定表的名字name,其次在MODE中指定锁的模式,NOWAIT可以指定是否在没有拿到锁时,一致等待。

-- 事务1
-- 基于互斥锁,锁住test表
-- 先开启事务
begin;
-- 基于默认的ACCESS EXCLUSIVE锁住test表
lock test in ACCESS SHARE mode;
-- 操作
select * from test;
-- 提交事务,锁释放
commit;

当事务1开启锁住当前表之后,如果使用默认的ACCESS EXCLUSIVE,其他连接操作表时,会直接阻塞住。

如果事务1是基于ACCESS SHARE共享锁时,其他事务是可以查询当前表的。

行锁

PostgreSQL的行锁和MySQL的基本是一模一样的,基于select for update就可以指定行锁。

MySQL中有一个概念,for update时,如果select的查询没有命中索引,可能会锁表。

PostgerSQL有个特点,for update时,如果select的查询没有命中索引,不一定会锁表,依然会实现行锁。

-- 先开启事务
begin;
-- 基于for update 锁住id为3的数据
select * from test where id = 3 for update;
update test set name = 'v1' where id = 3;
-- 提交事务,锁释放
commit;

其他的事务要锁住当前行,会阻塞住。

总结

事务、MVCC和锁是三个相互关联的概念,它们共同保证了数据库的一致性和并发性。

  • 事务和MVCC是互相配合的,事务通过MVCC来实现并发控制,保证数据的一致性。
  • 锁是事务实现并发控制的一种手段,通过加锁来保证数据的一致性。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html实现邮件模版布局-flex布局table布局-demo

邮件模版布局 flex - 布局简单方便 兼容性差 table - 优点 就是兼容性好&#xff0c;其他没有优点 注&#xff1a;使用图片需要png最好&#xff0c;使用svg图google邮箱会出现不能使用的情况 效果图 flex布局 <!DOCTYPE html> <html lang"en" xmlns:th&qu…

Mojo 语言官网

Mojo面向 AI 开发者的新型编程语言&#xff0c;无缝支持CPU、GPU&#xff0c;兼容Python&#xff0c;跟Python类似的语法&#xff0c;但是比Python快68000倍。目前Mojo仅支持Ubuntu&#xff0c;暂不支持Windows和Mac&#xff0c;可以在Mojo Playground先体验一下。 Mojo 语言…

JVM类加载和双亲委派机制

当我们用java命令运行某个类的main函数启动程序时&#xff0c;首先需要通过类加载器把类加载到JVM&#xff0c;本文主要说明类加载机制和其具体实现双亲委派模式。 一、类加载机制 类加载过程&#xff1a; 类加载的过程是将类的字节码加载到内存中的过程&#xff0c;主要包括…

Outlook无需API开发连接钉钉群机器人,实现新增会议日程自动发送群消息通知

Outlook用户使用场景&#xff1a; 在企业中&#xff0c;会议和活动的顺利举行对于业务运转和团队协作至关重要。然而&#xff0c;计划的变动总是无法避免&#xff0c;这可能会导致其他人的计划受到影响&#xff0c;打乱原有的安排。为了解决这个问题&#xff0c;许多企业开始使…

前端面试要点

0914 JScript深拷贝和浅拷贝&#xff08;js解构赋值算哪个&#xff1f;&#xff09; 深拷贝和浅拷贝 回流和重绘 回流和重绘 webpack打包流程 Webpack打包 虚拟DOM 虚拟DOM git合并分支 git合并分支 CSS盒子模型 CSS盒子模型 0911 WebPack分包 webpack分包 ts泛型 ts泛型 优化…

基于Python计算PLS中的VIP值(变量投影重要性分析法)

sklearn中PLS回归模型并没有计算VIP值的方法,但VIP又是很重要的筛选变量方法。下附代码思路与完整代码。 计算公式: 其中: VIPj:对应于第j个特征的VIP值;p:预测变量的总数;A:PLS成分的总数;R矩阵:A个PLS成分中,每个成分a都对应一套系数wa将X转换为成分得分,系数矩…

spring boot 使用AOP+自定义注解+反射实现操作日志记录修改前数据和修改后对比数据,并保存至日志表

一、添加aop starter依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>二&#xff1a;自定义字段翻译注解。&#xff08;修改功能时&#xff0c;需要显示如…

亚马逊关于在澳大利亚销售儿童玩具和游戏的政策合规标准是什么?

亚马逊关于在澳大利亚销售儿童玩具和游戏的政策 在亚马逊澳大利亚商城中&#xff0c;设计用于或明确表示专供 14 岁及以下儿童玩耍用的所有商品或材料均视为儿童玩具。 商品根据以下标准确定为“儿童商品”&#xff1a; 预期用途&#xff1a; ASIN 是否可供儿童使用&#xff…

JAVA面向对象(OOP)总结----宏观的程序设计

类&#xff1a;使用关键字class&#xff0c;抽象的概念集合。例如人类&#xff0c;具有共性的产物。 对象&#xff1a;具有自己独立属性&#xff0c;具有个性的个体。 类中可以定义的内容&#xff1a; 成员变量&#xff08;属性&#xff09;&#xff1b;成员方法&#xff08;…

torch.where()两种用法

参考官方文档。 官方文档中只给了第一种用法。根据条件condition&#xff0c;从input,other中选择元素f返回。如果满足条件&#xff0c;则返回input元素。若不满足&#xff0c;返回other元素。 还有一种用法是通过where返回张量中满足条件condition的坐标&#xff0c;以二维张…

【自动化测试】如何在jenkins中搭建allure

相信大家在做自动化测试过程中&#xff0c;都会用到自动化测试环境&#xff0c;目前最常见的就是通过容器化方式部署自动化测试环境&#xff0c;但对于一些测试小白&#xff0c;不是很会搭建持续集成环境&#xff0c;特别是从0-1的过程&#xff0c;需要自行搭建很多依赖环境&am…

springboot项目制作docker镜像,如何动态传递变量值?

springboot项目制作成docker镜像后&#xff0c;如何给properties文件的变量动态传递值呢&#xff1f; 步骤1&#xff1a;将properties文件设置为如下形式 serverUrl${SERVER_URL} apiKey${API_KEY}步骤2&#xff1a;制作成docker镜像后&#xff0c;启动镜像时&#xff0c;通过…

【PCL-11】提取平面上层的目标物,剔除平面下层目标物

因项目需求&#xff0c;需提取平面上的物体&#xff0c;不提取平面下的物体&#xff0c;尝试采用超体聚类LCCP分割的方式&#xff0c;但由于上层点云模型一侧有空洞&#xff0c;导致分割效果不理想。 这里采用pcl::ExtractPolygonalPrismData类&#xff0c;实现平面上物体的提取…

代码混淆和加固,保障应用程序的安全性

摘要&#xff1a;本文将详细介绍iOS技术博主在保护应用程序代码安全方面的两种重要方式&#xff1a;代码混淆和代码加固。通过代码混淆和加固&#xff0c;博主可以有效防止他人对应用程序进行逆向工程和篡改&#xff0c;提高应用程序的安全性。 引言&#xff1a;作为iOS技术博…

实时云渲染应用之虚拟仿真项目的四大优势

虚拟仿真在教育领域的应用越来越广&#xff0c;尤其在科研和实验教学领域&#xff0c;这主要是因为虚拟仿真具有操作简单、场景逼真、更安全、易维护的优势。比如在实验教学过程中&#xff0c;一些实验对象相对于学生来说过于宏观或微观&#xff0c;学生不易理解&#xff0c;而…

北邮22级信通院数电:Verilog-FPGA(1)实验一“跑通第一个例程” 过程中遇到的常见问题与解决方案汇总(持续更新中)

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 问题一&#xff1a;Verilog代码没有跑通 报…

数据类型

目录 1.数值类型 整数类型 int 小数类型 double 2.字符类型 固定长度字符串 char 可变长度字符串 varchar 3.日期时间类型 日期类型&#xff1a;date 日期时间类型&#xff1a;datetime MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article…

DLL调试方法 VS2012 C++ 有代码时

把exe放到输出目录 并把调试 命令 设为 ( S o l u t i o n D i r ) (SolutionDir) (SolutionDir)(Platform)$(Configuration)\SmartPayDemo.exe 尽量用debug模式 反过来也行&#xff0c;把dll放在exe工程下也行。 解决方案exe工程中添加dll工程 dll本身是没法运行的&#…

Unreal Engine Loop 流程

引擎LOOP 虚幻引擎的启动是怎么一个过程。 之前在分析热更新和加载流程过程中&#xff0c;做了一个图。记录一下&#xff01;&#xff01; ![在这里插入图片描述](https://img-blog.csdnimg.cn/f11f7762f5dd42f9b4dd9b7455fa7a74.png#pic_center 只是记录&#xff0c;以备后用…

Linux下运行Jmeter压测

一、在Linux服务器先安装SDK 1、先从官网下载jdk1.8.0_131.tar.gz&#xff0c;再从本地上传到Linux服务器 2、解压&#xff1a;tar -xzf jdk1.8.0_131.tar.gz&#xff0c;生成文件夹 jdk1.8.0_131 3、在/usr/目录下创建java文件夹&#xff0c;再将 jdk1.8.0_131目录移动到/u…