PostgreSQL rc,rr,ssi 隔离级别与性能对比 - 高隔离级别损耗性测试

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 标签 PostgreSQL , rc , rr , ssi , 隔离级别 , 性能 , 乐观锁 背景 https://www.postgresql.org/docs/11/mvcc.html PG支持到了最高级别的隔离级别SSI(serializable snapshot isolate)。 几种隔离级别的目标如下 1、读未提交,可以看到未提交的数据,脏读。 2、读已提交,只能看

标签

PostgreSQL , rc , rr , ssi , 隔离级别 , 性能 , 乐观锁


背景

https://www.postgresql.org/docs/11/mvcc.html

PG支持到了最高级别的隔离级别SSI(serializable snapshot isolate)。

几种隔离级别的目标如下

1、读未提交,可以看到未提交的数据,脏读。

2、读已提交,只能看到其他会话已提交的数据。

3、可重复度,只能看到事务开启前已提交的数据。更新(修改)事务开启后被其他会话修改过并提交的数据时,报错。

postgres=# create table abc(id int primary key, info text);  
CREATE TABLE  
postgres=# insert into abc values (1,'test');  
INSERT 0 1  

a

postgres=# begin transaction isolation level repeatable read ;  
BEGIN  
postgres=# select * from abc;  
 id | info   
----+------  
  1 | test  
(1 row)  

b

postgres=# update abc set info='hello digoal';  
UPDATE 1  
commit;  

a

postgres=# \set VERBOSITY verbose
postgres=# update abc set info ='new';  
ERROR:  40001: could not serialize access due to concurrent update
LOCATION:  ExecUpdate, nodeModifyTable.c:1257

4、严格串行,模拟串行执行,事务结束时,判断是否有会话之间的相互依赖,如果依赖的数据被已提交的事务修改,则报错,确保模拟严格串行的场景。

create table mytab (class int, value int);  
insert into mytab values (1,10),(1,20),(2,100),(2,200);  
  
 class | value  
-------+-------  
     1 |    10  
     1 |    20  
     2 |   100  
     2 |   200  

a

postgres=# begin transaction isolation level serializable ;  
BEGIN  
  
SELECT SUM(value) FROM mytab WHERE class = 1;  

b

postgres=# begin transaction isolation level serializable ;  
BEGIN  
postgres=# SELECT SUM(value) FROM mytab WHERE class = 2;  
 sum   
-----  
 300  
(1 row)  

a

insert into mytab values (2,30);  

b

insert into mytab values (1,30);  

a

postgres=# commit ;  
COMMIT  

b

postgres=# \set VERBOSITY verbose
postgres=# commit;
ERROR:  40001: could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.
LOCATION:  PreCommit_CheckForSerializationFailure, predicate.c:4685

《PostgreSQL 10.0 preview 功能增强 - 串行隔离级别 预加锁阈值可控》

《PostgreSQL SERIALIZABLE ISOLATION LEVEL introduce》

隔离级别越高,冲突可能性就越大,不同数据库的实现不一样,PG使用了巧妙的乐观锁实现。处理吞吐高。

对比rc, rr, ssi隔离级别的性能

为了方便测试,使用函数封装TPCB,测试rr和ssi

create or replace function tpcb (int,int,int,int) returns void as $$  
declare  
begin  
  UPDATE pgbench_accounts SET abalance = abalance + $4 WHERE aid = $1;  
  perform abalance FROM pgbench_accounts WHERE aid = $1;  
  UPDATE pgbench_tellers SET tbalance = tbalance + $4 WHERE tid = $3;  
  UPDATE pgbench_branches SET bbalance = bbalance + $4 WHERE bid = $2;  
  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($3, $2, $1, $4, CURRENT_TIMESTAMP);  
  exception when SQLSTATE '40001' then   -- skip 冲突 
    return;  
end;  
$$ language plpgsql strict;  

测试脚本

vi tpcb.sql  
\set aid random(1, 100000 * :scale)  
\set bid random(1, 1 * :scale)  
\set tid random(1, 10 * :scale)  
\set delta random(-5000, 5000)  
select tpcb(:aid, :bid, :tid, :delta);  

初始化数据,5亿条

pgbench -i -s 5000  

rc模式

alter role all set default_transaction_isolation ='read committed';  
pgbench -M prepared -v -r -P 1 -c 64 -j 64 -T 120  
  
transaction type: <builtin: TPC-B (sort of)>  
scaling factor: 5000  
query mode: prepared  
number of clients: 64  
number of threads: 64  
duration: 120 s  
number of transactions actually processed: 11343739  
latency average = 0.677 ms  
latency stddev = 0.747 ms  
tps = 94519.862919 (including connections establishing)  
tps = 94528.706372 (excluding connections establishing)  
statement latencies in milliseconds:  
         0.002  \set aid random(1, 100000 * :scale)  
         0.001  \set bid random(1, 1 * :scale)  
         0.001  \set tid random(1, 10 * :scale)  
         0.001  \set delta random(-5000, 5000)  
         0.046  BEGIN;  
         0.137  UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;  
         0.073  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;  
         0.082  UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;  
         0.079  UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;  
         0.067  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);  
         0.188  END;  
postgres=# select count(*) from pgbench_history ;  
  count     
----------  
 11343739  
(1 row)  

rr模式

alter role all set default_transaction_isolation ='repeatable read';  
pgbench -M prepared -v -r -P 1 -f ./tpcb.sql -c 64 -j 64 -T 120  
  
transaction type: ./tpcb.sql  
scaling factor: 1  
query mode: prepared  
number of clients: 64  
number of threads: 64  
duration: 120 s  
number of transactions actually processed: 10555148  
latency average = 0.728 ms  
latency stddev = 0.732 ms  
tps = 87949.593197 (including connections establishing)  
tps = 87957.185597 (excluding connections establishing)  
statement latencies in milliseconds:  
         0.001  \set aid random(1, 100000 * :scale)  
         0.000  \set bid random(1, 1 * :scale)  
         0.000  \set tid random(1, 10 * :scale)  
         0.000  \set delta random(-5000, 5000)  
         0.725  select tpcb(:aid, :bid, :tid, :delta);  

等待事件

select wait_event_type,wait_event,count(*) from pg_stat_activity  group by 1,2 order by 1,2;  
  
 wait_event_type |      wait_event      | count   
-----------------+----------------------+-------  
 Activity        | AutoVacuumMain       |     1  
 Activity        | BgWriterMain         |     1  
 Activity        | CheckpointerMain     |     1  
 Activity        | LogicalLauncherMain  |     1  
 Client          | ClientRead           |     4  
 IPC             | ProcArrayGroupUpdate |     1  
 LWLock          | buffer_content       |     5  
 Lock            | transactionid        |     6  
 Lock            | tuple                |    34  
                 |                      |    17  
(10 rows)  

正常事务:

postgres=# select count(*) from pgbench_history ;  
 count    
--------  
 638001  
(1 row)  

在冲突率这么高的情况下,可以保持87957的TPS,非常厉害。

ssi模式

alter role all set default_transaction_isolation ='serializable';  
pgbench -M prepared -v -r -P 1 -f ./tpcb.sql -c 64 -j 64 -T 120  
  
transaction type: ./tpcb.sql  
scaling factor: 1  
query mode: prepared  
number of clients: 64  
number of threads: 64  
duration: 120 s  
number of transactions actually processed: 5166549  
latency average = 1.486 ms  
latency stddev = 1.098 ms  
tps = 43050.086666 (including connections establishing)  
tps = 43058.594768 (excluding connections establishing)  
statement latencies in milliseconds:  
         0.002  \set aid random(1, 100000 * :scale)  
         0.000  \set bid random(1, 1 * :scale)  
         0.000  \set tid random(1, 10 * :scale)  
         0.000  \set delta random(-5000, 5000)  
         1.484  select tpcb(:aid, :bid, :tid, :delta);  

锁等待

select wait_event_type,wait_event,count(*) from pg_stat_activity  group by 1,2 order by 1,2;  
  
  
 wait_event_type |          wait_event          | count   
-----------------+------------------------------+-------  
 Activity        | AutoVacuumMain               |     1  
 Activity        | BgWriterHibernate            |     1  
 Activity        | CheckpointerMain             |     1  
 Activity        | LogicalLauncherMain          |     1  
 Activity        | WalWriterMain                |     1  
 Client          | ClientRead                   |     1  
 LWLock          | SerializableFinishedListLock |    58  
 LWLock          | SerializableXactHashLock     |     2  
 Lock            | transactionid                |     1  
 Lock            | tuple                        |     1  
                 |                              |     3  
(11 rows)  

正常事务:

postgres=# select count(*) from pgbench_history ;  
 count    
--------  
 411820  
(1 row)  

在冲突率这么高的情况下,可以保持43058的TPS,非常厉害。

性能对比

数据量 隔离级别 TPS(吞吐能力) QPS 正常事务 冲突比例
5亿 rc 94528 472640 11343739 0%
5亿 rr 87957 439785 638001 93.95%
5亿 ssi 43058 215290 411820 92.03%

小结

在冲突率高达90%以上的情况下,PG的RR模式可以保持87957的TPS,SSI模式可以保持43058的TPS,非常厉害,使用乐观锁带来的好处多多。

测试环境:32核虚拟机。(文章主要表明的是PG在高隔离级别下面的锁管理能力强悍,相对于RC这种低隔离级别,损耗做到了非常小。)

参考

https://www.postgresql.org/docs/11/mvcc.html

https://www.postgresql.org/docs/11/errcodes-appendix.html

《PostgreSQL 10.0 preview 功能增强 - 串行隔离级别 预加锁阈值可控》

《PostgreSQL SERIALIZABLE ISOLATION LEVEL introduce》

https://www.jianshu.com/p/c348f68fecde

https://zhuanlan.zhihu.com/p/37087894

src/backend/storage/lmgr/README-SSI

https://www.postgresql.org/docs/11/runtime-config-locks.html

postgres=# show max_pred_locks_per_page ;
 max_pred_locks_per_page 
-------------------------
 2
(1 row)

postgres=# show max_pred_locks_per_relation ;
 max_pred_locks_per_relation 
-----------------------------
 -2
(1 row)

postgres=# show max_pred_locks_per_transaction ;
 max_pred_locks_per_transaction 
--------------------------------
 64
(1 row)
References
----------

[1] http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
Search for serial execution to find the relevant section.

[2] A. Fekete et al. Making Snapshot Isolation Serializable. In ACM
Transactions on Database Systems 30:2, Jun. 2005.
http://dx.doi.org/10.1145/1071610.1071615

[3] Joseph M. Hellerstein, Michael Stonebraker and James Hamilton. 2007.
Architecture of a Database System. Foundations and Trends(R) in
Databases Vol. 1, No. 2 (2007) 141-259.
http://db.cs.berkeley.edu/papers/fntdb07-architecture.pdf
  Of particular interest:
    * 6.1 A Note on ACID
    * 6.2 A Brief Review of Serializability
    * 6.3 Locking and Latching
    * 6.3.1 Transaction Isolation Levels
    * 6.5.3 Next-Key Locking: Physical Surrogates for Logical Properties

 

免费领取阿里云RDS PostgreSQL实例、ECS虚拟机

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
2月前
|
机器学习/深度学习 人工智能 监控
提升软件质量的关键路径:高效测试策略与实践在软件开发的宇宙中,每一行代码都如同星辰般璀璨,而将这些星辰编织成星系的过程,则依赖于严谨而高效的测试策略。本文将引领读者探索软件测试的奥秘,揭示如何通过精心设计的测试方案,不仅提升软件的性能与稳定性,还能加速产品上市的步伐,最终实现质量与效率的双重飞跃。
在软件工程的浩瀚星海中,测试不仅是发现缺陷的放大镜,更是保障软件质量的坚固防线。本文旨在探讨一种高效且创新的软件测试策略框架,它融合了传统方法的精髓与现代技术的突破,旨在为软件开发团队提供一套系统化、可执行性强的测试指引。我们将从测试规划的起点出发,沿着测试设计、执行、反馈再到持续优化的轨迹,逐步展开论述。每一步都强调实用性与前瞻性相结合,确保测试活动能够紧跟软件开发的步伐,及时适应变化,有效应对各种挑战。
|
3月前
|
测试技术 数据库 UED
Python 性能测试进阶之路:JMeter 与 Locust 的强强联合,解锁性能极限
【9月更文挑战第9天】在数字化时代,确保软件系统在高并发场景下的稳定性至关重要。Python 为此提供了丰富的性能测试工具,如 JMeter 和 Locust。JMeter 可模拟复杂请求场景,而 Locust 则能更灵活地模拟真实用户行为。结合两者优势,可全面评估系统性能并优化瓶颈。例如,在电商网站促销期间,通过 JMeter 模拟大量登录请求并用 Locust 模拟用户浏览和购物行为,可有效识别并解决性能问题,从而提升系统稳定性和用户体验。这种组合为性能测试开辟了新道路,助力应对复杂挑战。
114 2
|
4月前
|
缓存 关系型数据库 数据库
PostgreSQL性能
【8月更文挑战第26天】PostgreSQL性能
72 1
|
2月前
|
监控 测试技术 PHP
性能和压力测试
【10月更文挑战第10天】性能和压力测试
114 60
|
3月前
|
缓存 Java 测试技术
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
使用JMeter对项目各个接口进行压力测试,并对前端进行动静分离优化,优化三级分类查询接口的性能
101 10
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
|
2月前
|
测试技术 PHP 开发工具
php性能监测模块XHProf安装与测试
【10月更文挑战第13天】php性能监测模块XHProf安装与测试
33 0
|
3月前
|
敏捷开发 安全 测试技术
软件测试的艺术:确保质量与性能的平衡之道
【9月更文挑战第24天】在软件开发的海洋中,测试是导航灯塔,指引着项目安全抵达质量的彼岸。本文将深入探讨软件测试的核心原则、方法论以及如何通过精心设计的测试策略来保障产品的可靠性和性能。我们将从测试的基础知识出发,逐步深入到高级测试技巧,最终展示如何通过实际案例来应用这些知识以确保软件的成功交付。
|
3月前
|
测试技术 Python
软件测试的艺术:确保质量与性能
【9月更文挑战第19天】在数字化时代,软件已成为我们生活的一部分。然而,随着软件复杂性的增加,如何确保其质量和性能成为了一个挑战。本文将探讨软件测试的重要性,介绍常见的测试类型和策略,并提供实用的代码示例来帮助读者更好地理解和应用这些测试方法。无论你是开发人员、测试工程师还是项目管理者,这篇文章都将为你提供有价值的见解和技巧。
|
3月前
|
缓存 关系型数据库 数据库
如何优化 PostgreSQL 数据库性能?
如何优化 PostgreSQL 数据库性能?
123 2
|
2月前
|
存储 关系型数据库 MySQL
四种数据库对比MySQL、PostgreSQL、ClickHouse、MongoDB——特点、性能、扩展性、安全性、适用场景
四种数据库对比 MySQL、PostgreSQL、ClickHouse、MongoDB——特点、性能、扩展性、安全性、适用场景