PostgreSQL 行锁解读

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介:

    像其它数据库一样,PostgreSQL数据库不仅有表级别的锁,同时也有行级别的锁。行锁对于提高系统的并行度至关重要。那么PostgreSQL是如何实现行锁的呢?

PostgreSQL获取行锁的大致分为以下两个阶段:

1.获取buffer page级别的锁

   这是一个buffer content锁,不是单纯的buffer pin,当然buffer pin的次数肯定会增加。buffer content锁分为share和exclusive两种。”share”是共享锁,

一般的读操作,获取的就是share锁。”exclusive”是排它锁,对记录的修改,增加,删除等需要获取此类锁。

   另外Buffer page又分为两种,分别是local和shared。backend进程独有的buffer是不需要锁的,因为它只被本backend进程独享,是local的。如临时表等。

我们通常需要加锁处理都是针对shared类型的buffer,不同进程之间对buffer page的操作需要通过锁机制来保障。

   在对一个buffer page进行加锁前,需要进行可性性判断。即本条记录是否是“HeapTupleInvisible”。如果是invisible的,是不能加锁,这也是事务隔离的需要。

2.设置行锁标志位

  行锁的实现比较复杂,我们不可能把所有需要上锁的记录都放到内存的lock table中,因为有些情况下,涉及到的记录非常多。为了解决这个问题,通常只在

tuple的header中设置标记为来标识此行记录已经被锁。这两个关键的标记为xmax和infomask。”xmax”放置当前事务的xid,“infomask”放置flag信息。

设置infomask目的主要是为了区别与正常的deleted tuple分区开来,正常情况下xmax是用来标识被删除的记录。这样一来,就不必去维护全局级别的lock table了,

也可以实现任意记录数的行锁操作。另外如果是多个事务同时去上锁一行记录,那么multixact就会被使用。

下面举例说明:

image

上图第一个红色圈内容为一个事务,事务ID号为:15331854,所执行的语句为:

会话1:

postgres=# begin;
BEGIN
postgres=# update t1 set id=1 where id=2;
UPDATE 1

第二个红色圈内容为另一个事务,事务ID号为:15331855,所执行的语句为:

会话2:

postgres=# begin;
BEGIN
postgres=# update t1 set id=2 where id=2;

可以看到,第二个会话hang住了,因为他们更新的是同一个表的同一条记录。

我们再起会话3:

image

看到这条记录的xmax已经标记为第一个事务的xid,即:15331854。这也验证了上面的说法,当update时,PG会去标记每条记录的xmax,设置为当前xid。

另外一个标记位,从这里没有办法看到。需要dump出这条记录的header才能看到。

我们再在会话1中跑语句:select xmin,xmax,cmin,cmax ,t.* from t1 t;

image

细心的同学发现,情况不对,跟前面会话3查出的结果完全不同。那么是PG错了吗?

当然不是的,这就是MVCC实现的结果。会话3中看到的那条记录是old tuple,也就是老的记录,因为会话1还没有提交,而会话1看到的是新的记录。

根据read commit隔离级别,本事务中之前update掉的记录,是允许看到的。另外,我们发现xmin的xid已经是本事务的xid了。

总结:

PG对于update其实也生成了一个新版本的tuple,在老版本的tuple header中做了两个标记:一个是xmax,另外一个是infomask。

“xmax”放持有此记录lock的xid,infomask存放flag信息。

infomask的flag信息如下:

image

另外对于delete操作和update操作,PG做了不同处理。具体主要表现在索引上。

那么行锁与索引有什么关系? 大家知道PG索引是没有MVCC的,那么PG如何处理这些细节呢,下次再详细讲述。

本文转自ICT时空 dbasdk博客,原文链接:PostgreSQL 行锁解读 ,如需转载请自行联系原博主。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
SQL 缓存 运维
PostgreSQL 事务号回卷分析
## XID 定义 xid 是个啥东西?xid 就是 PostgreSQL 里面的事务号,每个事物都会分配一个 xid。PostgreSQL 数据中每个元组头部都会保存着 插入 或者 删除 这条元组的事务号,即 xid,然后内核通过这个 xid 进行元组的可见性判断。简单理解,比如有两个事务,xid1=200,xid2=201,那么 xid1 中只能看到 t_xmin 200 的元组。 ```c
|
2月前
|
Oracle 关系型数据库 MySQL
一文了解PostgreSQL MVCC机制
一文了解PostgreSQL MVCC机制
73 0
|
4月前
|
存储 SQL 关系型数据库
MYSQL--(1.存储引擎 *2.事务*)
MYSQL--(1.存储引擎 *2.事务*)
|
存储 关系型数据库 MySQL
Mysql锁和分库分表
MySQL锁和分库分表是两种常用的数据库性能优化和并发控制技术。
78 0
|
SQL 存储 关系型数据库
Mysql表锁与行锁
Mysql表锁与行锁
101 0
|
关系型数据库 MySQL 索引
MySQL - 无索引行锁升级为表锁
MySQL - 无索引行锁升级为表锁
99 0
|
SQL 存储 Oracle
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
快速学习 PostgreSQL 事务隔离级别的实现和多版本并发控制
552 0
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
|
关系型数据库 数据库 PostgreSQL
|
存储 关系型数据库 MySQL
MySQL 索引、事务与存储引擎(一)
1、索引 2、事务 3、存储引擎
MySQL 索引、事务与存储引擎(一)
|
存储 SQL 缓存
MySQL 索引、事务与存储引擎(二)
1、索引 2、事务 3、存储引擎
MySQL 索引、事务与存储引擎(二)
下一篇
无影云桌面