PostgreSQL如何查看事务所占有的锁?

这篇具有很好参考价值的文章主要介绍了PostgreSQL如何查看事务所占有的锁?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

表级锁命令LOCK TABLE

在PG中,显式地在表上加锁的命令为“LOCK TABLE”,此命令的语法如下:

LOCK [TABLE] [ONLY] name [,...][IN lockmode MODE] [NOWAIT]

语法中各项参数说明如下:

  1. name:表名
  2. lockmode:表级锁模式,即SHARE、EXCLUSIVE、ACCESS SHARE、ACCESS EXCLUSIVE、ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE ROW EXCLUSIVE
  3. NOWAIT:如果没有NOWAIT这个关键字,当无法获得锁时会一直等待,而如果加了NOWAIT关键字,在无法立即获取该锁时,此命令会立即退出并且报错

在PG中,事务自己的锁是从不冲突的,因此一个事务可以在持有SHARE模式的锁时再请求ROW EXCLUSIVE锁,而不会出现自己的锁阻塞自己的情况

当事务要更新表中的数据时,应该申请ROW EXCLUSIVE锁,而不应该申请SHARE锁,因为在更新数据时,事务还是会对表加ROW EXCLUSIVE锁,想象一下,在两个并发的事务都请求SHARE锁后,开始更新数据前要对表加ROW EXCLUSIVE锁,但由于各自先前已加了SHARE锁,所以都要等待对方释放SHARE锁,因而出现死锁。从这个示例可以看出,如果涉及多种锁模式,那么事务应该总是最先请求最严格的锁模式,否则就容易出现死锁

行级锁命令

显式的行级锁命令是由SELECT命令后加如下子句来构成的:

SELECT ... FOR {UPDATE | SHARE} [OF table_name [,...]] [NOWAIT] [...]
  • NOWAIT关键字加上,如果无法获得锁则直接报错,而不会一直等待。
  • OF table_name明确指定表名字,那么只有被指定的表会被锁定,其他在SELECT中使用的表则不会
  • 不带OF table_name的FOR UPDATE或者FOR SHARE子句将锁定该命令中使用的所有表
  • 如果FOR UPDATE或者FOR SHARE应用于一个视图或者子查询,那么它将同样锁定该视图或者子查询中使用到的所有表
  • 主查询中引用了WITH查询时,WITH查询中的表并不会被锁定
  • 如果想要锁定WITH查询内的表行,需要在WITH查询内指定FOR UPDATE或者FOR SHARE关键字

锁的查看

我们经常需要查看一个事务产生了哪些锁,哪个事务被哪个事务阻塞了,若执行一条SQL语句时阻塞住了,需要查询为什么阻塞,是谁阻塞住的,这些信息可以通过查询系统视图“pg_locks”来得到。pg_locks视图中各列的描述如下:

列名称 列类型 引用 描述
locktype text 被锁定的对象类型:relation、extend、page、tuple、transactionid、virtualxid、object、userlock、advisory
database oid pg_database.oid 锁定对象的数据库OID,如果对象是一个共享对象,不属于任何数据库,此值为“0”,如果对象是“transaction ID”,此值为空
relation oid pg_class.oid 如果对象不是表或只是表的一部分,则此值为“NULL”,否则此值是表的OID
page integer 表中的页号,如果对象不是表行(tuple)或表页(relation page),则此值为“NULL”
tuple smallint 页内的行号(tuple)
virtualxid text 虚拟事务id
transactionid xid 事务id
classid oid pg_class.oid 包含该对象系统目录的id
objid oid any OID column 对象在系统目录的oid
objsubid smallint 如果对象是表列(table column),此列的值为列号,这时classid和objid指向表
virtualtransaction text 持有或等待这把锁的虚拟事务id
pid integer 持有或等待这把锁的服务进程的PID,如果此锁是被一个两阶段提交的事务持有,则此值为NULL
mode text 锁的模式名称,如“ACCESS SHARE”“SHARE”“EXCLUSIVE”等锁模式
granted boolean 如果锁已被持有,此值为True,如果等待获得此锁,则此值为False

上述中,描述事务id的字段有三个:

  • virtualxid
  • transactionid
  • virtualtransaction
  1. transactionid代表事务id,简写为“xid”
  2. virtualxid代表虚拟事务id,简写为“vxid”
  3. 每产生一个事务id,都会在pg_clog下的commit log文件中占用2bit
  4. 最早pg中本没有虚拟事务id,但是后来发现,有一些事务根本没有产生任何实质的变更,如一个只读事务或一个空事务,若在这种情况下也分配一个事务id会造成浪费,于是提出了虚拟事务id的概念
  5. 对于这类只读事务,值分配一个虚拟事务id,而不是实际分配一个真实的事务id,这样就不需要在commit log中占用2bit的空间了

pg_locks这张视图的字段分为以下两部分:

  • virtualtransaction之前的字段(不包括virtualtransaction字段),我们称其为“第一部分”,用于描述锁定对象(Locked Object)信息
  • virtualtransaction之后的字段(包括virtualtransaction字段),我们称其为“第二部分”,用于描述持有锁或等待锁的session信息

了解上述概念后,可以容易理解virtualxid和virtualtransaction两个字段的意思:

  • virtualxid在第一部分字段中,表示锁对象是一个virtualxid
  • virtualtransaction表示持有锁或等待锁session的虚拟事务id

表锁实操

1.先开一个psql窗口,命令如下
PostgreSQL如何查看事务所占有的锁?

第一个窗口,查询PID,并锁定一张表。

2.第二个窗口中查看数据库中的锁的情况
PostgreSQL如何查看事务所占有的锁?
sql命令:

select locktype,relation::regclass as rel,virtualxid as vxid,transactionid as xid,virtualtransaction as vxid2,pid,mode,granted from pg_locks where pid = 12264;

通过上述图片可以看出:

  • 第一行显示的是事务在自己的“virtualxid”上加的ExclusiveLock锁,这是必定会加上的
  • 第二行才是我们实际在表上加的锁“AccessExclusiveLock”

3.新增一个窗口,显示地对表加锁
PostgreSQL如何查看事务所占有的锁?

执行sql语句发现,该窗口的锁表语句会被阻塞住

4.查看两个进程的锁情况
PostgreSQL如何查看事务所占有的锁?

  • 发现两个进程都对表加了锁
  • 进程12264中的granted字段为t,说明它获得了这把锁
  • 进程21052中的granted字段为f,说明该进程没有获得这把锁,从而被阻塞

行锁实操

1.第一个窗口执行如下操作(在加表锁的基础上加行锁)
PostgreSQL如何查看事务所占有的锁?

2.第二个窗口中查看数据库中的锁的情况
PostgreSQL如何查看事务所占有的锁?

行锁不仅会在表上加意向锁,也会在相应的主键上加意向锁。其中“jxx_test_pkey”就是表的主键。

3.另一个窗口加行锁
PostgreSQL如何查看事务所占有的锁?
该窗口阻塞

4.第二个窗口中查看数据库中的锁的情况
PostgreSQL如何查看事务所占有的锁?

xid为739的锁被进程12264持有了,所以21052的进程获取锁标识为False

5.如何查看具体是哪一行数据被阻塞

-- 其中0和1分别代表pg_locks中的page和tuple字段
select * from jxx_test where ctid = '(0,1)'

pg_locks并不能显示出每个行锁的信息,因为行锁信息并不会被记录到共享内存中。如果记录到内存,意味着对表做全表更新时,表有多少行就需要在内存中记录多少条行锁信息,那么内存会吃不消,所以postgreSQL设计成不在内存中记录行锁信息。


思考:如何获取进程是在哪一行上被阻塞的?文章来源地址https://www.toymoban.com/news/detail-487451.html

到了这里,关于PostgreSQL如何查看事务所占有的锁?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 查看docker所占空间大小

    先df -h 看下docker目录。  检查此目录的大小并获取 Docker 使用的总磁盘空间,执行:

    2024年02月11日
    浏览(38)
  • Linux查看当前目录下各文件所占空间

    要查看当前目录下各文件所占空间,可以使用du命令(磁盘使用情况)配合sort命令来实现。以下是在Linux系统中执行的命令: 解释一下这个命令: du -sh * :计算当前目录下每个文件和目录的总大小,并以易读的方式显示(例如以KB、MB、GB为单位)。 sort -hr :将du命令的输出进

    2024年02月13日
    浏览(45)
  • mysql语句查看数据库表所占容量空间大小

         六. 查看所有产生碎片的表 查看某个表的碎片大小 SHOW TABLE STATUS LIKE \\\'表名\\\'; 查询结果中的\\\'Data_free\\\'字段的值就是碎片大小。 7. 清理表碎片

    2024年02月11日
    浏览(42)
  • Android 使用sqlcipher加密和解密数据库(包括加密和解密已有的数据库,还有如何查看数据库教程)

    前言 我们知道Android系统有一个内嵌的SQLite数据库,并且提供了一整套的API用于对数据库进行增删改查操作,SQLite是一个轻量级的、跨平台的、开源的嵌入式数据库引擎,也是一个关系型的的使用SQL语句的数据库引擎,读写效率高、资源消耗总量少、延迟时间少,使其成为移

    2024年02月06日
    浏览(54)
  • 查看现有的conda源

    (d2l-zh) C:Users36291conda config --show channels channels:   - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/   - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/   - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/   - https://mirrors.bfsu.edu.cn/anaconda/pkgs/main/   - https://mirrors.bfsu.edu.cn/anaconda/pkgs/fr

    2024年01月21日
    浏览(63)
  • PostgreSql 事务

      在日常操作中,对于一组相关操作,通常需要其全部成功或全部失败。在关系型数据库中,将这组相关操作称为事务。事务具有的四个特性简称为 ACID。 原子性(Atomicity) :保证事务中的操作要么全部成功,要么全部失败,不会只成功一部分。 一致性(Consistency) :数

    2024年02月15日
    浏览(39)
  • 【TensorFlow 】查看Tensorflow和python对应版本、将现有的TensorFlow更新到指定的版本

    1、查看Tensorflow和python对应版本 1.1这里我是在TensorFlow官方网址产看的 1、打开官方网址 https://pypi.org/project/tensorflow/1.1.0rc2/#files但是这个网址好像打不开,点击会出现这样 问题不大 输入Tensorflow然后点击搜索,就会跳转到https://pypi.org/search/?q=tensorflow,点击第一个即可: 即可看

    2023年04月26日
    浏览(56)
  • 《PostgreSQL事务管理深入解析》

    🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🐅🐾猫头虎建议程序员必备技术栈一览表📖: 🛠️ 全栈技术 Full Stack : 📚 MERN/MEAN/MEVN Stack | 🌐 Jamstack | 🌍 GraphQL | 🔁 RESTful API | ⚡ WebSockets | 🔄 CI/CD | 🌐 Git Version Control | 🔧 DevOps 🌐 前端技术 Frontend : 🖋️ HTML CSS |

    2024年02月09日
    浏览(51)
  • PostgreSQL-分布式事务之两阶段提交

    在日常操作中,对于一组相关操作,通常需要其全部成功或全部失败。 在关系型数据库中,将这组相关操作称为“ 事务 ”。 在一个事务中,多个插入、修改、删除操作要么全部成功,要么全部失败,这称为“ 原子性 ”,实际上一个事务还需要有其他三个特性,即“ 一致性

    2024年02月04日
    浏览(48)
  • POSTGRESQL PERPARE 事务提交方式,到底用还是不用

    开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群(共1100人左右 1 + 2 + 3)新人会进入3群 关于Prepare 提交事务的方式问题,有两

    2024年02月16日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包