PostgreSQL-锁机制详解

PG数据库中由两类锁:

  • 表级锁
  • 行级锁

当要查询、插入、更新、删除表中的数据时,首先会获得表上的锁,然后再获得行上的锁

表级锁模式

锁模式 解释 SQL操作
ACCESS SHARE 只与ACCESS EXCLUSIVE模式冲突。 通常情况下,任何只读取表而不修改表的查询都会请求这种锁模式
用于保护事务正在读取的表不被其他事务修改或删除
SELECT:当事务执行SELECT语句读取表中的数据时,会自动获取ACCESS SHARE锁模式
COPY:当事务执行COPY命令将表中的数据导出到文件或从文件导入到表中时,会自动获取ACCESS SHARE锁模式
ANALYZE:当事务执行ANALYZE命令对表进行统计分析时,会自动获取ACCESS SHARE锁模式
VACUUM:当事务执行VACUUM命令对表进行回收空间时,会自动获取ACCESS SHARE锁模式
需要注意的是,ACCESS SHARE锁模式只能防止其他事务对整张表进行写入操作,但不能防止其他事务对表中某些行进行写入操作。如果需要保护表中某些行不被其他事务修改或删除,可以考虑使用ROW SHARE或其他更严格的锁模式
ROW SHARE 与EXCLUSIVE和ACCESS EXCLUSIVE锁模式冲突。
SELECT FOR UPDATE和SELECT FOR SHARE命令会在目标表上加此类型的锁。
ROW SHARE并不是排他性锁,其他事务仍然可以读取这个表的数据。
ROW EXCLUSIVE 与SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE锁模式冲突。 UPDATE、DELETE、INSERT命令自动在所修改的表上请求加此类型的锁。通常情况下,修改表中数据的命令都是在表上加上此类型的锁。
SHARE UPDATE EXCLUSIVE 与SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE锁模式冲突。 模式改变和运行VACUUM并发的情况下,这种锁模式可以保护表。
VACUUM(不带FULL选项)、ANALYZE、CREATE INDEX CONCURRENTLY命令请求此类型的锁。
SHARE 与ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE锁模式冲突。 这种锁模式避免表的并发数据修改。
CREATE INDEX(不带CONCURRENTLY选项)语句要求这种锁模式
SHARE ROW EXCLUSIVE 与ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE锁模式冲突。 任何PG命令都不会自动请求这种锁模式。
EXCLUSIVE 与ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE锁模式冲突。这种锁模式只允许并发ACCESS SHARE锁,也就是说,只有对表的读操作可以和持有这个锁的事务并发执行。 任何PG命令都不会在用户表上自动请求这种锁模式。不过,在执行某些操作时,会在某些系统表上请求这种锁模式。
ACCESS EXCLUSIVE 与所有的锁模式冲突(包括ACCESS SHARE、ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE)。 这种锁模式保证只能有一个用户访问此表。
在LOCK TABLE命令中没有明确声明需要的锁模式时,它是默认锁模式。
ALTER TABLE、DROP TABLE、TRUNCATE、REINDEX、CLUSTER、VACUUM FULL命令要求此类型的锁。

表级锁冲突矩阵

水平代表已申请到的锁模式竖直代表请求的锁模式 ACCESS SHARE ROW SHARE ROW EXCLUSIVE SHARE UPDATE EXCLUSIVE SHARE SHARE ROW EXCLUSIVE EXCLUSIVE ACCESS EXCLUSIVE
ACCESS SHARE Y Y Y Y Y Y Y N
ROW SHARE Y Y Y Y Y Y N N
ROW EXCLUSIVE Y Y Y Y N N N N
SHARE UPDATE EXCLUSIVE Y Y Y N N N N N
SHARE Y Y N N Y N N N
SHARE ROW EXCLUSIVE Y Y N N N N N N
EXCLUSIVE Y N N N N N N N
ACCESS EXCLUSIVE N N N N N N N N
  1. “N”表示这两种锁冲突,也就是说,同一用户不能同时持有这两种锁,“Y”表示两种锁可以兼容。
  2. 表级锁只有SHARE和EXCLUSIVE这两种,这两种锁基本上就是读写锁的意思。
  3. 加上SHARE锁后相当于加了读锁,表中的内容就不能变化了。可以为多个事务加上此锁,只要任意一个用户不释放此读锁,其他用户就不能修改这个表。(注意这里的维度是表)。
  4. 多版本功能下,如果改某一行的数据,实际上并没有改变原先那行数据,而是另复制出一个新行,修改都在新行上进行,事务进行不提交,别人是看不到这条数据的;由于原先那行数据没有变化,在修改过程中,读数据的人仍然可以读到原有数据,这样就没有必要阻塞其他用户读数据了。
  5. 多版本功能下,除了SHARE和EXCLUSIVE两个锁,还需要增加两个锁,一个叫作“ACCESS SHARE”,表明加上这个锁,即使是正在修改数据的情况下也允许读数据;另一个锁是“ACCESS EXCLUSION”,意思是即使有多版本的功能,也不允许访问数据。

表级锁加锁的对象是表,由于加锁的范围太大而导致并发不高,于是人们提出了行级锁的概念,但是行级锁与表级锁之间会产生冲突,这时就需要有一种机制来描述行级锁与表级锁之间的关系。在MySQL中是使用“意向锁”的概念来解决这一问题的,方法就是当我们要修改表中的某一行数据时,需要先在表上加一种锁,表示即将在表的部分行上加共享锁或排它锁


PG中也是这样实现的,如ROW SHARE、ROW EXCLUSIVE这两个锁,这两个锁实际上就对应MySQL中的共享意向锁(IS)和排它意向锁(IX)。从“意向锁”的概念出发,我们可以得到意向锁如下两个特点:

  1. 意向锁之间是不会发生冲突的,即使是ROW EXCLUSIVE之间也不会发生冲突,因为它们都只是“有意”做什么但还没有真做,所以是可以兼容的。
  2. 意向锁与其他非意向锁之间的关系和普通锁与普通锁之间的关系是相同的。例如:
    • “X”与“X”锁是冲突的,所以“IX”锁与“X”是冲突的
    • “X”与“S”锁是冲突的,所以“IX”锁与“S”是冲突的
    • “S”与“S”锁是不冲突的,所以“IS”锁与“S”是不冲突的

如果把共享锁“SHARE”简写为“S”,把排它锁“EXCLUSIVE”简写为“X”;把“ROW SHARE”简写为“IS”;把“ROW EXCLUSIVE”锁简写为“IX”;这4种锁的关系(意向锁与非意向之间的冲突矩阵)如下表所示:

X S IX IS
X N N N N
S N Y N Y
IX N N Y Y
IS N Y Y Y

表级锁总计

  1. 共享锁“SHARE”
  2. 排它锁“EXCLUSIVE”
  3. ACCESS SHARE
  4. ACCESS EXCLUSIVE
  5. 意向共享锁“ROW SHARE”
  6. 意向排它锁“ROW EXCLUSIVE”
  7. SHARE UPDATE EXCLUSIVE
  8. SHARE ROW EXCLUSIVE

多版本原因,修改一条数据的同时允许读数据,所以为了处理这种情况,增加了“ACCESS”相关的两种锁;为了处理表锁和行锁之间的关系,于是有了意向锁的概念,增加了意向共享锁和意向排它锁;由于意向锁之间不会产生冲突,而且意向排它锁互相之间也不会产生冲突,于是又需要更严格一些的锁,这样就产生了SHARE UPDATE EXCLUSIVE和SHARE ROW EXCLUSIVE锁。

行级锁模式

行级锁模式比较简单,只有两种,即“共享锁”“排它锁”,或者可以说是“读锁”或“写锁”。

在PG中不称其为“读锁”的原因是,由于有多版本的实现,所以实际读取行数据时,并不会在行上执行任何锁(包括“读锁”)。

原文地址:https://blog.csdn.net/wozaibohaibian/article/details/131030606

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读601次。Oracle的数据导入导出是一项基本的技能,但是对于懂数据库却不熟悉Oracle的同学可能会有一定的障碍。正好在最近的一个项目中碰到了这样一个任务,于是研究了一下Oracle的数据导入导出,在这里跟大家分享一下。......_oracle 迁移方法 对比
文章浏览阅读553次。开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共700多人左右 1 + 2)。最近我们在使用MYSQL 8 的情况下(8.025)在数据库运行中出现一个问题 参数prefer_order_i..._mysql prefer_ordering_index
文章浏览阅读3.5k次,点赞3次,收藏7次。折腾了两个小时多才成功连上,在这分享一下我的经验,也仅仅是经验分享,有不足的地方欢迎大家在评论区补充交流。_navicat连接opengauss
文章浏览阅读2.7k次。JSON 代表 JavaScript Object Notation。它是一种开放标准格式,将数据组织成中详述的键/值对和数组。_postgresql json
文章浏览阅读2.9k次,点赞2次,收藏6次。navicat 连接postgresql 注:navicat老版本可能报错。1.在springboot中引入我们需要的依赖以及相应版本。用代码生成器生成代码后,即可进行增删改查(略)安装好postgresql 略。更改配置信息(注释中有)_mybatisplus postgresql
文章浏览阅读1.4k次。postgre进阶sql,包含分组排序、JSON解析、修改、删除、更新、强制踢出数据库所有使用用户、连表更新与删除、获取今年第一天、获取近12个月的年月、锁表处理、系统表使用(查询所有表和字段及注释、查询表占用空间)、指定数据库查找模式search_path、postgre备份及还原_pgsql分组取每组第一条
文章浏览阅读3.3k次。上一篇我们学习了日志清理,日志清理虽然解决了日志膨胀的问题,但就无法再恢复检查点之前的一致性状态。因此,我们还需要日志归档,pg的日志归档原理和Oracle类似,不过归档命令需要自己配置。以下代码在postmaster.c除了开启归档外,还需要保证wal_level不能是MINIMAL状态(因为该状态下有些操作不会记录日志)。在db启动时,会同时检查archive_mode和wal_level。以下代码也在postmaster.c(PostmasterMain函数)。......_postgresql archive_mode
文章浏览阅读3k次。系统:ubuntu22.04.3目的:利用向日葵实现windows远程控制ubuntu。_csdn局域网桌面控制ubuntu
文章浏览阅读1.6k次。表分区是解决一些因单表过大引用的性能问题的方式,比如某张表过大就会造成查询变慢,可能分区是一种解决方案。一般建议当单表大小超过内存就可以考虑表分区了。1,继承式分区,分为触发器(trigger)和规则(rule)两种方式触发器的方式1)创建表CREATE TABLE "public"."track_info_trigger_partition" ( "id" serial, "object_type" int2 NOT NULL DEFAULT 0, "object_name..._pg数据表分区的实现
文章浏览阅读3.3k次。物联网平台开源的有几个,就我晓得的有、、thingskit、JetLink、DG-iot(还有其他开源的,欢迎在评论区留言哦!),然后重点分析了下ThingsBoard、ThingsPanel和JetLink,ThingsBoard和Jetlinks是工程师思维产品,可以更多的通过配置去实现开发的目的,ThingsPanel是业务人员思路产品,或者开发或者用,避免了复杂的配置带来的较高学习门槛。ThingsBoard和Jetlinks是Java技术体系的,ThingsPanel是PHP开发的。_jetlinks和thingsboard
文章浏览阅读3.8k次。PostgreSQL 数据类型转换_pgsql数字转字符串
文章浏览阅读7k次,点赞3次,收藏14次。在做数据统计页面时,总会遇到统计某段时间内,每天、每月、每年的数据视图(柱状图、折线图等)。这些统计数据一眼看过去也简单呀,不就是按照时间周期(天、月、年)对统计数据进行分个组就完了嘛?但是会有一个问题,简单的写个sql对周期分组,获取到的统计数据是缺失的,即没有数据的那天,整条记录也都没有了。如下图需求:以当前月份(2023年2月)为起点,往后倒推一年,查询之前一年里每个月的统计数据。可见图中的数据其实是缺少的,这条sql只查询到了有数据的月份(23年的1月、2月,22年的12月)_如何用一条sql查出按年按月按天的汇总
文章浏览阅读3.8k次,点赞66次,收藏51次。PostgreSQL全球开发小组与2022年10月13日,宣布发布PostgreSQL15,这是世界上最先进的开源数据库的最新版本_mysql8 postgresql15
文章浏览阅读1.3k次。上文介绍了磁盘管理器中VFD的实现原理,本篇将从上层角度讲解磁盘管理器的工作细节。_smgrrelationdata
文章浏览阅读1.1k次。PostgreSQL设置中文语言界面和局域网访问_postgressql汉化
文章浏览阅读4.2k次。PostgreSQL 修改数据存储路径_如何设置postgresql 数据目录
文章浏览阅读4.7k次。在项目中用到了多数据源,在连接postgres数据库时,项目启动报错,说数据库连接错误,说dual不存在,网上好多教程都是说数据库查询的时候的大小写问题,而这个仅仅是连接,咋鞥却处理方法是修改application-dev.yml中的配置文件.项目中的druid参数是这样的:确实在配置文件中有个查询语句。_relation "dual" does not exist
文章浏览阅读4.9k次。PostgreSQL是一款强大的关系型数据库,但在实际使用过程中,许多用户经常会遇到慢SQL的问题。这些问题不仅会降低数据库性能,还会直接影响业务流程和用户体验。因此,本文将会深入分析PostgreSQL慢SQL的原因和优化方案,帮助用户更好地利用这个优秀的数据库系统。无论你是初学者还是专业开发者,本文都将为你提供实用的技巧和方法,让你的PostgreSQL数据库始终保持高效快速。_postgresql数据库优化
文章浏览阅读1.6k次。Linux配置postgresql开机自启_linux 启动pgsql
文章浏览阅读2k次。本篇介绍如何在centos7系统搭建一个postgresql主备集群实现最近的HA(高可用)架构。后续更高级的HA模式都是基于这个最基本的主备搭建。_postgresql主备