数据库开发者社区 > 正文

PostgreSQL Oracle 兼容性之 - select for update of column_name (change to table_name or table_alias)

简介:
+关注继续查看

标签

PostgreSQL , Oracle , select for update of column


背景

当一个SELECT中包含多张表时(比如JOIN),FOR UPDATE可以指定要LOCK哪张表的匹配到的ROWS。

例如

https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#SQLRF01702

The following statement locks only those rows in the employees table with purchasing clerks located in Oxford. No rows are locked in the departments table:

SELECT e.employee_id, e.salary, e.commission_pct  
   FROM employees e JOIN departments d  
   USING (department_id)  
   WHERE job_id = 'SA_REP'  
   AND location_id = 2500  
   FOR UPDATE OF e.salary  
   ORDER BY e.employee_id;  

PostgreSQL 对应语法

create table employees(department_id int, job_id text, employee_id int, salary float, commission_pct float);  
create table departments(department_id int, location_id int);  
  
insert into employees values (1, 'SA_REP', 1, 100, 1);  
insert into employees values (1, 'SA_REP123', 1, 100, 1);  
insert into departments values (1, 2500);  

语法如下,只是将列名改成表名或ALIAS,另外,order by需要放到前面。

postgres=# explain SELECT e.employee_id, e.salary, e.commission_pct  
   FROM employees e JOIN departments d  
   USING (department_id)  
   WHERE job_id = 'SA_REP'  
   AND location_id = 2500  
   ORDER BY e.employee_id   
   FOR UPDATE OF e;  -- order by 放前面  
  
                                      QUERY PLAN                                        
--------------------------------------------------------------------------------------  
 LockRows  (cost=182.79..182.84 rows=4 width=32)  
   ->  Sort  (cost=182.79..182.80 rows=4 width=32)  
         Sort Key: e.employee_id  
         ->  Hash Join  (cost=58.86..182.75 rows=4 width=32)  
               Hash Cond: (d.department_id = e.department_id)  
               ->  Seq Scan on departments d  (cost=0.00..123.62 rows=45 width=10)  
                     Filter: (location_id = 2500)  
               ->  Hash  (cost=58.62..58.62 rows=19 width=30)  
                     ->  Seq Scan on employees e  (cost=0.00..58.62 rows=19 width=30)  
                           Filter: (job_id = 'SA_REP'::text)  
(10 rows)  

我们还可以观察被LOCK的行

1、创建行锁观测插件

https://www.postgresql.org/docs/10/static/pgrowlocks.html

postgres=# create extension pgrowlocks ;  
CREATE EXTENSION  

2、在事务中执行以上LOCK的SQL,在其他会话中观测被锁的行

可以看到只有employees被LOCK

postgres=# select * from pgrowlocks('employees');  
 locked_row | locker  | multi |   xids    |     modes      |  pids     
------------+---------+-------+-----------+----------------+---------  
 (0,1)      | 1001814 | f     | {1001814} | {"For Update"} | {26460}  
(1 row)  

departments没有被锁

postgres=# select * from pgrowlocks('departments');  
 locked_row | locker | multi | xids | modes | pids   
------------+--------+-------+------+-------+------  
(0 rows)  

使用关联查询,可以看到被锁的行的记录

postgres=# SELECT * FROM employees AS a, pgrowlocks('employees') AS p  
  WHERE p.locked_row = a.ctid;  
 department_id | job_id | employee_id | salary | commission_pct | locked_row | locker  | multi |   xids    |     modes      |  pids     
---------------+--------+-------------+--------+----------------+------------+---------+-------+-----------+----------------+---------  
             1 | SA_REP |           1 |    100 |              1 | (0,1)      | 1001814 | f     | {1001814} | {"For Update"} | {26460}  
(1 row)  

3、如果不使用for update of ,则会锁住所有JOIN表的行。

postgres=# begin;  
BEGIN  
postgres=# SELECT e.employee_id, e.salary, e.commission_pct  
postgres-#    FROM employees e JOIN departments d  
postgres-#    USING (department_id)  
postgres-#    WHERE job_id = 'SA_REP'  
postgres-#    AND location_id = 2500  
postgres-#    ORDER BY e.employee_id   
postgres-#    FOR UPDATE  
postgres-# ;  
 employee_id | salary | commission_pct   
-------------+--------+----------------  
           1 |    100 |              1  
(1 row)  

观测

postgres=# select * from pgrowlocks('employees');  
 locked_row | locker  | multi |   xids    |     modes      |  pids     
------------+---------+-------+-----------+----------------+---------  
 (0,1)      | 1001826 | f     | {1001826} | {"For Update"} | {26460}  
(1 row)  
  
postgres=# select * from pgrowlocks('departments');  
 locked_row | locker  | multi |   xids    |     modes      |  pids     
------------+---------+-------+-----------+----------------+---------  
 (0,1)      | 1001826 | f     | {1001826} | {"For Update"} | {26460}  
(1 row)  
  

PostgreSQL for update更细致的用法

在对主外键表的主表加LOCK时,可以指定是否需要LOCK referenced的COLUMN。

FOR UPDATE, FOR NO KEY UPDATE, FOR SHARE and FOR KEY SHARE are locking clauses;   
  
they affect how SELECT locks rows as they are obtained from the table.  
  
The locking clause has the general form  
  
FOR lock_strength [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ]  
where lock_strength can be one of  
  
UPDATE  -- 当前事务可以改所有字段  
NO KEY UPDATE  -- 当前事务可以改除referenced KEY以外的字段  
SHARE    -- 其他事务不能改所有字段  
KEY SHARE  -- 其他事务不能改referenced KEY字段  

参考

https://www.postgresql.org/docs/10/static/pgrowlocks.html

《并发事务, 共享行锁管理 - pg_multixact manager for shared-row-lock implementation》

《PostgreSQL add 2 DML LOCK TUPLE MODE to 4》

《PostgreSQL How to deal TUPLE LOCK : 2 - "one|more transactions waiting one|more transactions release tuple lock"》

《PostgreSQL How to deal TUPLE LOCK : 1 - "One transaction lock single or multiple tuples | rows"》

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【.NET 6】使用EF Core 访问Oracle+Mysql+PostgreSQL并进行简单增改操作与性能比较
唠嗑一下。都在说去O或者开源,但是对于数据库选型来说,很多人却存在着误区。例如,去O,狭义上讲,是去Oracle数据库。但是从广义上来说,是去Oracle公司产品或者具有漂亮国垄断地位和需要商业授权的数据库产品。
106 0
10 PostgreSQL 表级复制-物化视图篇, 支持异地,异构如 Oracle 到 pg 的物化视图|学习笔记
快速学习10 PostgreSQL 表级复制-物化视图篇,支持异地,异构如 Oracle 到 pg 的物化视图
190 0
关于PostgreSQL数据库兼容Oracle数据库闪回查询的实现方案
注:关于在PostgreSQL上面实现Oracle数据库的闪回功能(闪回查询 闪回表 闪回删除…)的这个想法已经有很长时间了,但是鉴于本人的能力 精力和身体条件 迟迟没有完成。期间也有很多的小伙伴跟我一起研究过这个功能,但是最终都因为各种各样的问题 没有做下去。Oracle数据库闪回功能跨越版本较大,功能也比较强大 在PostgreSQL数据库上实现,需要对数据库内核有很深入的理解 两大数据库不同的底层原理也终将影响各自的实现策略,PostgreSQL标记删除就地插入的特点和基于事务快照行可见性的特性是我们可以开发PostgreSQL闪回查询的大前提。本文主要介绍 实现闪回查询的 一种实现方案
223 0
【学习资料】第10期数据库选型思考(PostgreSQL,MySQL,Oracle)
大家好 ,这里是数据库选型思考(PostgreSQL,MySQL,Oracle)
211 0
【学习资料】第1期Oracle DBA 增值 PostgreSQL,Greenplum 学习计划 - 珍藏级
大家好,这里是Oracle DBA 增值 PostgreSQL,Greenplum 学习计划 - 珍藏级
166 0
【学习视频】第6期2019-Oracle迁移到PostgreSQL - 适合DBA与业务开发者
大家好,这里是《PG干O,仁心所象 - 去O实战培训》 公益活动纪录 - 《PG开发者指南、去O、管理与优化实践》
201 0
PostgreSQL Oracle 兼容性 - Oracle 19c 新特性在PostgreSQL中的使用
PostgreSQL Oracle 兼容性 - Oracle 19c 新特性在PostgreSQL中的使用
2400 0
PostgreSQL Oracle 兼容性之 - performance insight - AWS performance insight 理念与实现解读 - 珍藏级
PostgreSQL , perf insight , 等待事件 , 采样 , 发现问题 , Oracle 兼容性
660 0
数据库领域前沿技术分享与交流
热门文章
热门讨论
+关注
德哥
公益是一辈子的事, I am digoal, just do it.
文章
问答
视频
相关电子书
更多
迁移 ORACLE 最佳实践
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
相关镜像