Skip to content

Commit d107dc8

Browse files
author
xiongcc
committed
添加第35章:How to use subtransactions in Postgres
1 parent 1382e3a commit d107dc8

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# How to use subtransactions in Postgres
2+
3+
> 我每天都会发布一篇新的 PostgreSQL "howto" 文章。加入我的旅程吧 — 订阅、提供反馈、分享!
4+
5+
## TL;DR
6+
7+
如无必要,否则不要使用子事务。
8+
9+
## 什么是子事务?
10+
11+
子事务,也称为"嵌套事务",是指在已启动的事务范围内通过指令启动的事务 (来源:[Wikipedia](https://en.wikipedia.org/wiki/Nested_transaction))。这一特性允许用户部分回滚事务,这在许多情况下很有帮助:如果发生错误,重新执行的步骤会减少。
12+
13+
SQL 标准定义了描述这种机制的两个基本指令:`SAVEPOINT` 和扩展的 `ROLLBACK` 语句 — `ROLLBACK TO SAVEPOINT`。PostgreSQL 实现了这些指令,但允许在语法上稍有不同,例如可以在 `RELEASE``ROLLBACK` 语句中省略 `SAVEPOINT` 关键字。
14+
15+
你可能已经在使用子事务,例如:
16+
17+
- 在 Django 中,使用嵌套的 ["atomic()" blocks](https://docs.djangoproject.com/en/5.0/topics/db/transactions/#savepoints)
18+
- 隐式使用:在 PL/pgSQL 函数中使用 `BEGIN / EXCEPTION WHEN ... / END` 块。
19+
20+
## 如何使用 (如果你真的想用)
21+
22+
语法:
23+
24+
- `SAVEPOINT savepoint_name` ([SAVEPOINT](https://postgresql.org/docs/current/sql-savepoint.html))
25+
- `ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] savepoint_name` ([ROLLBACK TO](https://postgresql.org/docs/current/sql-rollback-to.html))
26+
- `RELEASE [ SAVEPOINT ] savepoint_name` ([RELEASE SAVEPOINT](https://postgresql.org/docs/current/sql-release-savepoint.html))
27+
28+
一个示例:
29+
30+
![Rolled-back subtransaction example](https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos/-/raw/main/files/0035_rolled_back_subtransaction_example.jpg)
31+
32+
## 推荐
33+
34+
对于任何计划增长的 OLTP 类型负载 (如 Web 和移动应用),我唯一的实际建议是:
35+
36+
> 尽可能避免子事务
37+
38+
如果你不想有一天发生以下情况:
39+
40+
![Performance drop for more than 64 subtransactions in a transaction](https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos/-/raw/main/files/0035_performance_drop_too_many_subtx.jpg)
41+
42+
或者类似情况:
43+
44+
![Performance drop of standby server with primary running a long transaction and many subtransactions](https://gitlab.com/postgres-ai/postgresql-consulting/postgres-howtos/-/raw/main/files/0035_standby_server_killed.jpg)
45+
46+
你可以在这篇文章中找到对子事务四大危险的详细分析:[PostgreSQL Subtransactions Considered Harmful](https://postgres.ai/blog/20210831-postgresql-subtransactions-considered-harmful)
47+
48+
截至 2023 年 (PG16 版本),这些问题尚未解决,尽管一些优化工作正在进行中:
49+
50+
- [More scalable multixacts buffers and locking](https://commitfest.postgresql.org/45/2627/)
51+
- [suboverflowed subtransactions concurrency performance optimize](https://postgresql.org/message-id/flat/003201d79d7b%24189141f0%2449b3c5d0%[email protected]) (不幸的是,补丁已被撤回)
52+
53+
底线是
54+
55+
- 如果可以,不要使用子事务。
56+
- 关注与子事务相关的 pgsql-hackers 邮件讨论,并参与测试和改进。
57+
- 如果绝对需要使用子事务,请参考 [Problem 3: unexpected use of Multixact IDs](https://postgres.ai/blog/20210831-postgresql-subtransactions-considered-harmful#problem-3-unexpected-use-of-multixact-ids) 以及:
58+
- 仅在低 TPS 系统中使用它们
59+
- 避免深度嵌套
60+
- 在包含子事务的事务中谨慎使用 `SELECT ... FOR UPDATE`
61+
- 监控 `pg_stat_slru` 数值 (PG13+,[Monitoring stats](https://postgresql.org/docs/current/monitoring-stats.html)),以便迅速发现并解决 SLRU 溢出问题。
62+
63+
# 我见
64+
65+
在 17 版本中,已经针对 SLRU 的问题进行了极大优化,并且可以配置 SLRU 相关参数 — multixact_member_buffers、multixact_offset_buffers 和 subtransaction_buffers。
66+
67+
SLRU optimization
68+
69+
- Make the cache size configurable
70+
- Divide SLRU cache into small associative banks
71+
- Implement bankwise lock to remove the centralized control lock contention
72+
- Remove centralize LRU counter
73+
74+
Performance
75+
76+
- 2-3 x performance gain when there is huge load on SLRU

0 commit comments

Comments
 (0)