PostgreSQL 事务与并发系列 · 第五期
Clyde Jin
04-24
DBA
28

PostgreSQL 事务与并发系列 · 第五期

实战调优:事务的常见陷阱与最佳实践

前四期我们深入了 MVCC、锁、隔离级别与序列化异常。本期将把这些知识落地到生产环境的日常运维与开发中,剖析长事务、空闲事务、表膨胀、死锁超时等真实痛点,并提供一套可立即上手的监控、报警与优化方案。

一、长事务:性能与运维的头号杀手

1.1 为什么长事务如此危险?

  • 阻止 VACUUM 清理:长事务持有的快照会让所有在它之后产生的死亡元组都无法被清理,导致表与索引持续膨胀。
  • 事务 ID 回卷风险:事务 ID 是 32 位环状空间,长事务可能导致 xid 无法冻结,最终数据库会强制关闭。
  • 锁持有时间过长:长事务可能持有表锁或行锁,阻塞其他正常业务。

1.2 如何定位长事务?

SELECT pid,
       now() - xact_start AS xact_duration,
       state,
       query,
       backend_xid,
       backend_xmin
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
  AND state NOT LIKE 'idle%'
ORDER BY xact_duration DESC;

重点关注:

  • xact_duration 超过 1 分钟的事务(视业务而定)
  • backend_xmin 非空且 age 很大的会话

1.3 治理策略

  • 应用层超时 + 重试:设置合理的语句超时(statement_timeout)和事务超时(idle_in_transaction_session_timeout)。
  • 拆分长事务:将长时间运行的事务拆分为多个短事务,或使用异步处理。
  • 定期监控与告警:当长事务超过阈值(如 5 分钟)时,通过脚本发送告警甚至自动终止。

自动终止示例(谨慎使用,建议先通知后终止):

-- 终止 xact_duration > 10 分钟的事务
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE xact_start < now() - interval '10 minutes'
  AND state != 'idle';

二、idle in transaction:被遗忘的会话

2.1 危害

会话处于 idle in transaction 状态,表示它已经 BEGIN 但既不提交也不回滚,也不执行任何语句。这种会话:

  • 持有可能的行锁或表锁,阻塞其他事务。
  • 持有快照,同样阻止 VACUUM 清理。
  • 占用连接资源,导致连接池枯竭。

2.2 发现与清理

SELECT pid, state, xact_start, now() - xact_start AS idle_duration, query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY idle_duration DESC;

根治方案:在 PostgreSQL 配置文件中设置:

idle_in_transaction_session_timeout = '60s'

一旦事务空闲超过 60 秒,自动被终止并回滚。生产环境建议设为 30~120 秒。

同时检查应用代码:确保每一次 BEGIN 后都有对应的 COMMITROLLBACK(尤其是异常处理路径)。


三、表膨胀:监控与回收

3.1 为什么会膨胀?

MVCC 的副作用:更新/删除会产生死元组(dead tuples)。如果 VACUUM 跟不上产生速度,表就会膨胀,占用更多磁盘,降低索引效率。

长事务和 idle in transaction 是 VACUUM 最大的敌人——它们强制保留旧版本。

3.2 如何检测膨胀?

使用 pg_stat_user_tables 观察死元组比例:

SELECT schemaname, relname,
       n_live_tup,
       n_dead_tup,
       round(100 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 2) AS dead_ratio,
       last_vacuum, last_autovacuum
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY dead_ratio DESC;

如果 dead_ratio 经常超过 10%,需要调整 autovacuum 参数或手动 VACUUM。

3.3 治理膨胀

  • 调优 autovacuum
    autovacuum_vacuum_scale_factor = 0.05   # 默认 0.2,降低触发阈值
    autovacuum_vacuum_threshold = 1000
    autovacuum_naptime = 30s
  • 对大表针对性设置 storage parameters
    ALTER TABLE large_table SET (autovacuum_vacuum_scale_factor = 0.05);
  • 手动 VACUUMVACUUM VERBOSE large_table; (不锁表)
  • 极端膨胀时使用 VACUUM FULL:会锁表并重写整个表,生产环境需谨慎(可使用 pg_repack 在线重建)。

四、超时设置的合理配置

PostgreSQL 提供了多个超时参数,合理设置可以防止事务失控:

参数 作用域 推荐值 说明
statement_timeout 会话/用户/数据库 30s ~ 300s 单条 SQL 语句执行超时
lock_timeout 会话 1s ~ 10s 等待锁的超时,建议小于 deadlock_timeout
idle_in_transaction_session_timeout 全局 60s 空闲事务超时,必须设置
deadlock_timeout 全局 1s 死锁检测周期,默认 1 秒通常合适

设置示例

-- 针对当前会话
SET statement_timeout = '30s';
SET lock_timeout = '5s';

-- 针对特定用户
ALTER ROLE app_user SET statement_timeout = '60s';

应用层也应配合超时与重试。


五、锁监控与实时告警

5.1 找出当前阻塞链

使用递归查询找出阻塞关系:

WITH RECURSIVE blocking AS (
    SELECT pid, array[pid] AS path, 1 AS level
    FROM pg_stat_activity
    WHERE pid NOT IN (SELECT unnest(pg_blocking_pids(pid)) FROM pg_stat_activity WHERE pg_blocking_pids(pid) <> ARRAY[]::int[])
    UNION ALL
    SELECT blocked.pid, blocking.path || blocked.pid, blocking.level + 1
    FROM pg_stat_activity blocked
    JOIN blocking ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
    WHERE NOT blocked.pid = ANY(blocking.path)
)
SELECT pid, path, level
FROM blocking
ORDER BY level DESC, pid;

5.2 持续监控与告警脚本(示例)

使用 Shell + psql 定期检查,并通过 Webhook 发送告警:

#!/bin/bash
THRESHOLD_SEC=300   # 长事务阈值 5 分钟
ALERT_WEBHOOK="https://hooks.slack.com/..."

psql -At -c "
SELECT json_agg(row_to_json(t))
FROM (
  SELECT pid, age(now(), xact_start) AS duration, query
  FROM pg_stat_activity
  WHERE xact_start IS NOT NULL
    AND age(now(), xact_start) > interval '$THRESHOLD_SEC seconds'
    AND state NOT LIKE 'idle%'
) t
" | jq . > /tmp/long_xacts.json

if [ $(jq length /tmp/long_xacts.json) -gt 0 ]; then
  curl -X POST -H 'Content-type: application/json' 
    --data "{"text": "Long transactions detected: $(cat /tmp/long_xacts.json)"}" 
    $ALERT_WEBHOOK
fi

(可将此脚本放入 crontab 每分钟执行)


六、连接池与事务的配合

连接池(如 pgbouncer、HikariCP)在提高性能的同时也会带来事务管理的陷阱。

6.1 常见问题

  • 事务悬挂:应用获取连接后忘了 COMMIT,归还连接时事务依然打开。连接池再次借出该连接时,新请求会继续在旧事务中运行,导致不可预测的结果。
  • 连接池模式选择pgbouncer 有三种模式 – session、transaction、statement。如果使用 transaction 模式,每个事务结束会自动回滚到空闲状态,可以避免事务悬挂,但不支持某些特性(如 PREPARE 跨事务)。

6.2 最佳实践

  • 检查事务状态:应用在从连接池获取连接后,建议执行 DISCARD ALL 或至少检查 SHOW transaction_isolation; 等,确保处于干净状态。
  • 使用事务级别的连接池:如果业务事务短小,transaction 模式是最安全的。
  • 设置连接池的超时:例如 pgbouncer 的 server_idle_timeout 及时回收异常空闲连接。

七、事务优化的检查清单

在日常开发与运维中,对照以下清单避免常见陷阱:

  • [ ] 是否显式控制了事务边界?BEGINCOMMIT/ROLLBACK 成对出现。
  • [ ] 事务中是否有远程 API 调用或用户交互(极易导致长事务)?
  • [ ] 是否设置了 idle_in_transaction_session_timeout
  • [ ] 是否监控了长事务与 idle in transaction
  • [ ] 是否配置了合理的 statement_timeoutlock_timeout
  • [ ] 是否定期检查膨胀并调优 autovacuum?
  • [ ] 是否在应用层处理了序列化失败(40001)的重试逻辑?
  • [ ] 连接池配置是否符合事务模式(推荐 transaction 或显式重置会话)?
  • [ ] 是否在需要强一致性的地方使用了 SELECT FOR UPDATESERIALIZABLE

八、总结与系列收官

本系列五期内容从 ACID 与 MVCC 原理出发,逐步深入到锁机制、隔离级别、序列化异常,最后以生产实战调优收尾。通过这个系列,你应该已经能够:

  • 解释 PostgreSQL 的 MVCC 如何实现高并发读写
  • 诊断并解决常见的锁等待、死锁、写偏斜问题
  • 为不同业务场景选择合适的隔离级别
  • 监控并治理长事务、膨胀、空闲事务等运维顽疾

事务与并发是数据库领域的核心深水区,但有了一套系统的理解和工具,你就能自信地应对生产环境的各种挑战。

感谢阅读整个系列! 希望这些内容能帮助你在实际工作中少踩坑,多产出。如果对任何一期有疑问或建议,欢迎留言讨论。

我们下个技术专题再见!

Star
Donate
PostgreSQL 事务与并发系列 · 第四期
Previous
PostgreSQL 存储与索引系列(一):数据在磁盘上如何安放——表、页、TOAST 与 VACUUM
Next

Leave a comment

Registration is not required

Clyde Jin
303 Articles
0 Comments
0 Like
Recent Posts

HiddenMerit Daily · Issue 60

📊 HiddenMerit Daily · Issue 60 Focus on Database Frontiers, Practical Insights for DBAs July 22, 2026 | 5 Selected Global Breaking News 01|Oracle Releases Largest Quarterly Patch in History: 1,449 Patches Fix 1,235 CVEs, 261 Critical On July 21, Oracle released its July 2026 Critical Patch Update (CPU), setting a record for the largest single patch release in the company’s history. This CPU contains 1,449 security patches fixing 1,235 independent CVEs across 32 Oracle product families, of which 261 patches are rated Critical. Patch Distribution by Product Family: Product Family Patches Remotely Exploitable Without Authentication Oracle E‑Business Suite 410 45 Oracle Fusion Middleware 355 219 Oracle Communications 168 122 Oracle MySQL 54 9 Oracle Database Server 15 6 Context for This Patch: Oracle had already issued an urgent “Prepare Now” warning a week earlier, emphasising that AI is fundamentally lowering the barrier to discovering and exploiting vulnerabilities – frontier AI models can analyse software changes, reverse‑engineer security patches, and develop attack paths at unprecedented speed. Oracle has collaborated with state‑of‑the‑art models from Anthropic and OpenAI to proactively identify and fix potential security vulnerabilities. Oracle strongly recommends that customers immediately test and deploy this update in their monthly patch cycles. […]

HiddenMerit Daily · Issue 59

📊 HiddenMerit Daily · Issue 59 Focus on Database Frontiers, Practical Insights for DBAs July 21, 2026 | 5 Selected Global Breaking News 01|Oracle Issues Urgent Warning: July 21 Release Update to Fix Large Number of High‑Risk Vulnerabilities, Immediate Deployment Recommended On July 13, Oracle issued an urgent security warning, strongly recommending that all customers running supported Oracle Database versions (including Oracle Database 19c and Oracle AI Database 26ai) immediately test and deploy the Release Update (RU) after its release on July 21. Background: New frontier AI models are significantly lowering the barrier to discovering and exploiting software vulnerabilities – these models can identify weaknesses, analyse software changes, reverse‑engineer security patches, and develop potential attack paths at unprecedented speed and scale. AI models are also becoming increasingly adept at combining multiple weaknesses across the application and data stack into complex attacks, even when individual weaknesses do not themselves pose a serious risk. As a result, protecting systems solely at the network or application layer is no longer sufficient; enterprises must protect the entire technology stack. Fixes Included in This RU: Oracle has collaborated with state‑of‑the‑art models from Anthropic and OpenAI to proactively identify and fix potential security vulnerabilities. The upcoming […]

HiddenMerit Daily · Issue 58

📊 HiddenMerit Daily · Issue 58 Focus on Database Frontiers, Practical Insights for DBAs July 20, 2026 | 5 Selected Global Breaking News 01|CAICT: Domestic Databases Enter Core System “Deep Water,” AI‑Native Leads New Industry Landscape On July 9, at the 2026 Trustworthy Database Development Conference, CAICT released the “Database Development Research Report (2026).” The report notes that domestic databases have basically completed peripheral system replacement and have officially entered the critical business system breakthrough phase. Key Data: The global database market reached $131.6 billion in 2025 (approximately RMB 894.09 billion). The Chinese database market reached $9.49 billion in 2025 (approximately RMB 64.48 billion), and is expected to reach RMB 97.974 billion by 2028, with a CAGR of 13.06%. The number of domestic database vendors has shrunk from a peak of 167 to 94, with a clear head‑concentration effect and an intensifying “Matthew effect.” AI‑Native Becomes the Main Theme: The report points out that database technology is accelerating its evolution toward the AI‑native direction, and the global database industry is entering a new phase of landscape restructuring. The role of databases is upgrading from “underlying support systems” to “core engines enabling intelligent decision‑making and business innovation.” AI agents are becoming […]

HiddenMerit Daily · Issue 56

📊 HiddenMerit Daily · Issue 56 Focus on Database Frontiers, Practical Insights for DBAs July 6, 2026 | 5 Selected Global Breaking News 01|Kingware Releases Manufacturing Scenario Database Evolution White Paper: SQL Server Replacement Enters “Deep Water” On July 5, CETC Kingware published a technical article titled “Database Evolution in Manufacturing Scenarios: How Kingware Replaces SQL Server,” pointing out that the data surge on industrial shop floors has exceeded the processing capacity of single‑node systems. Traditional database architectures that rely on vertical scaling are facing unprecedented performance challenges. Over the next 1‑3 years, manufacturing enterprises will no longer face only the “choice of replacement,” but must answer the strategic question: “How do we build an autonomous data foundation in the context of de‑IOE?” Three Paradigm Shifts: Hybrid Workloads Become the Norm: The IT architecture of modern factories is shifting from separated OLTP and OLAP to HTAP mode. The same data system must simultaneously handle tens of thousands of device instruction writes per second and minute‑level production report analysis. Distributed Architecture Becomes a Hard Requirement: When a single table exceeds 100 million rows with daily increments exceeding 1 million rows, the index maintenance cost of traditional single‑node databases rises exponentially. Autonomous […]
生成中...
扫描二维码
扫描二维码