为什么用 PostgreSQL 绑定变量 没有 Oracle pin S 等待问题

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
简介: 早上看到盖国强老师在朋友圈里分享了一篇关于软解析带来的Pin S等待的问题。有感而发,跟大家聊一聊为什么PostgreSQL不存在这个问题。 Oracle 在Oracle中多个会话高并发的执行同一条SQL,如果使用了绑定变量的话,会产生pin s的等待事件。原因如下(取自互联网http://

早上看到盖国强老师在朋友圈里分享了一篇关于软解析带来的Pin S等待的问题。
有感而发,跟大家聊一聊为什么PostgreSQL不存在这个问题。

Oracle

在Oracle中多个会话高并发的执行同一条SQL,如果使用了绑定变量的话,会产生pin s的等待事件。
原因如下(取自互联网http://www.dbafree.net/?p=778

每个child cursor(你可以认为是一条SQL的plan tree)下面都有一个mutexes这样的简单内存结构,当有session要执行该SQL而需要pin cursor操作的时候,session只需要以shared模式set这个内存位+1,表示session获得该mutex的shared mode lock.可以有很多session同时具有这个mutex的shared mode lock;
但在同一时间,只能有一个session在操作这个mutext +1或者-1。+1 -1的操作是排它性的原子操作。
如果因为session并行太多,而导致某个session在等待其他session的mutext +1/-1操作,则该session要等待cursor: pin S等待事件。

当看到系统有很多session等待cursor: pin S事件的时候,要么是CPU不够快,要么是某个SQL的并行执行次数太多了而导致在child cursor上的mutex操作争用。如果是硬件的问题,则可以升级硬件。

如果是SQL执行频率太高。最简单的做法是,将一条SQL拆分成多条SQL。增加SQL的版本数来降低并发。如一个SQL:

select name from acct where acctno=:1

可以改为如下4个SQL,则并发的争用可以下降4倍。

     select /*A*/ name from acct where acctno=:1
     select /*B*/ name from acct where acctno=:1
     select /*C*/ name from acct where acctno=:1
     select /*D*/ name from acct where acctno=:1

另外,我们还会经常碰到另外一个等待事件“cursor: pin S wait on X”,这个等待事件主要是由硬解析引起的,解释如下:

“cursor: pin S wait on X” wait event is mostly related to mutex and hard parse.
- When a process hard parses the SQL statement, it should acquire exclusive
library cache pin for the corresponding LCO.
- This means that the process acquires the mutex in exclusive mode.
- Another process which also executes the same query needs to acquire the mutex
but it’s being blocked by preceding process. The wait event is “cursor: pin S wait on X”.

cursor: pin S,
cursor: pin X,
cursor: pin S wait on X
这三个等待事件,实际上就是替代了cursor的library cache pin,
pin S代表执行(share pin),
pin X代表解析(exclusive pin),
pin S wait on X代表执行正在等待解析操作。
这里需要强调一下,它们只是替换了访问cursor的library cache pin,而对于访问procedure这种实体对象,依然是传统的library cache pin。
参考:
https://supporthtml.oracle.com/epmos/faces/ui/km/DocumentDisplay.jspx?_afrLoop=5051110464464000&id=1310764.1&_afrWindowMode=0&_adf.ctrl-state=fu77hl3v2_4
http://www.hellodb.net/2010/07/oracle-library-cache.html 这篇文章不错,每次看都能有所收获。

很显然,产生这个锁的客观原因是Oracle的plan tree结构是共享的,并且加锁是串行的,所以高并发的情况下就出问题了。
如果你的业务形态确实如此,就只能改客户端程序来避免类似的问题。

PostgreSQL

下面给大家分析一下为什么PostgreSQL不存在这个问题
原因也很简单,PostgreSQL的plan cache是会话级别的,会话之间不共享plan cache.
因此不存在Oracle pin S的问题。
例子:

postgres=# create table t(id int primary key);
CREATE TABLE
postgres=# insert into t select generate_series(1,100);
INSERT 0 100

.1. 使用绑定变量(pgbench -M prepared), 并发执行同一SQL

vi t.sql
\setrandom id 1 100
select * from t where id=:id;

pgbench -M prepared -n -r -f ./t.sql -c 64 -j 64 -T 120
tps = 1110129.983665 (including connections establishing)
tps = 1110693.523542 (excluding connections establishing)

23283.00  3.1% GetSnapshotData              /home/dege.zzz/pgsql9.6/bin/postgres
18074.00  2.4% AllocSetAlloc                /home/dege.zzz/pgsql9.6/bin/postgres
15403.00  2.1% LWLockAcquire                /home/dege.zzz/pgsql9.6/bin/postgres

Cpu(s): 72.2%us, 18.9%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  8.8%si,  0.0%st

.2. 使用绑定变量(pgbench -M prepared), 并发执行不同SQL

for ((i=1;i<=64;i++)); do sed  "s/select/select\ \/*\ $i\ *\//" t.sql >./t$i.sql ; done
生成
select /* 1 */ * from t where id=:id;
... ...
select /* 64 */ * from t where id=:id;

RUN
for ((i=1;i<=64;i++)); do pgbench -M prepared -n -r -f ./t$i.sql -c 1 -j 1 -T 120 | grep "^tps" & done

tps = 1089230.887 (including connections establishing)
tps = 1090257.658 (excluding connections establishing)

23272.00  3.0% GetSnapshotData              /home/dege.zzz/pgsql9.6/bin/postgres
17798.00  2.3% AllocSetAlloc                /home/dege.zzz/pgsql9.6/bin/postgres
15030.00  2.0% LWLockAcquire                /home/dege.zzz/pgsql9.6/bin/postgres

Cpu(s): 70.5%us, 18.0%sy,  0.0%ni,  2.9%id,  0.0%wa,  0.0%hi,  8.6%si,  0.0%st

可以看到他们的profile, 性能指标, CPU的分配,几乎都没有差异。
如果你原来是Oracle的用户,开发人员再也不用为pin S的问题妥协,放心大胆的用同一条SQL,随便绑。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
6月前
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
6月前
|
关系型数据库 分布式数据库 数据库
PolarDB PostgreSQL版:Oracle兼容的高性能数据库
PolarDB PostgreSQL版是一款高性能的数据库,具有与Oracle兼容的特性。它采用了分布式架构,可以轻松处理大量的数据,同时还支持多种数据类型和函数,具有高可用性和可扩展性。它还提供了丰富的管理工具和性能优化功能,为企业提供了可靠的数据存储和处理解决方案。PolarDB PostgreSQL版在数据库领域具有很高的竞争力,可以满足各种企业的需求。
|
2月前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
334 2
|
6月前
|
人工智能 Oracle 关系型数据库
一篇文章弄懂Oracle和PostgreSQL的Database Link
一篇文章弄懂Oracle和PostgreSQL的Database Link
|
SQL Oracle 关系型数据库
PostgreSQL技术大讲堂 - 第27讲:Oracle-FDW部署
从零开始学PostgreSQL,PG技术大讲堂 - 第27讲:Oracle-FDW部署
220 2
|
6月前
|
SQL Oracle 关系型数据库
常用数据库的分页语句(mySQL、oracle、PostgreSQL、SQL Server)
常用数据库的分页语句(mySQL、oracle、PostgreSQL、SQL Server)
|
Oracle 关系型数据库 数据库
PostgreSQL和Oracle两种数据库有啥区别?如何选择?
PostgreSQL和Oracle两种数据库有啥区别?如何选择?
510 0
|
SQL Oracle 关系型数据库
物化视图(Oracle与PostgreSQL对比)
物化视图(Oracle与PostgreSQL对比)
|
6月前
|
Oracle 关系型数据库 数据库
Flink Sink to Oracle 存在字段CLOB类型,如何处理错误”ORA-01461: 仅能绑定要插入LONG的LONG值“
做Flink CDC同步数据过程中,目标是Oracle数据库,其中某个字段较大被设置为CLOB类型,其中会遇到异常,”ORA-01461: 仅能绑定要插入LONG的LONG值“
|
SQL 关系型数据库 MySQL
MySQL - 锁等待及死锁初探
MySQL - 锁等待及死锁初探
209 0

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多