PostgreSQL教程FG217-PG事务处理:原理与最佳实践
本文档风哥主要介绍PostgreSQL数据库的事务处理,包括事务的原理、生命周期、状态管理等内容,风哥教程参考PostgreSQL官方文档Transaction Processing内容,适合数据库管理员和开发者在学习和测试中使用。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 PostgreSQL事务处理概念
事务处理是数据库管理系统的核心功能,它确保了数据库操作的原子性、一致性、隔离性和持久性(ACID特性)。PostgreSQL的事务处理机制包括事务的开始、执行、提交或回滚等操作,确保数据的一致性和完整性。
- 支持ACID特性
- 支持嵌套事务(通过保存点)
- 支持多种隔离级别
- 支持事务的并发控制
- 支持事务的恢复机制
1.2 PostgreSQL事务生命周期
PostgreSQL事务的生命周期包括:
- 开始:使用BEGIN或START TRANSACTION语句开始事务
- 执行:执行各种SQL语句
- 提交:使用COMMIT语句提交事务,使所有修改永久生效
- 回滚:使用ROLLBACK语句回滚事务,撤销所有修改
- 保存点:使用SAVEPOINT创建保存点,使用ROLLBACK TO回滚到保存点
1.3 PostgreSQL事务状态
PostgreSQL事务的状态包括:
- 活跃(Active):事务正在执行中
- 空闲(Idle):事务已完成,连接处于空闲状态
- 空闲事务中(Idle in Transaction):事务已开始但未提交或回滚
- 空闲事务中(等待锁):事务等待锁释放
- 已提交(Committed):事务已成功提交
- 已回滚(Rolled Back):事务已回滚
Part02-生产环境规划与建议
2.1 PostgreSQL事务配置
PostgreSQL事务配置建议:
# 事务隔离级别
default_transaction_isolation = ‘read committed’ # 默认隔离级别
# 事务超时
idle_in_transaction_session_timeout = 60000 # 60秒
# 锁超时
lock_timeout = 0 # 无超时
# 死锁检测
deadlock_timeout = 1s # 死锁检测超时
# 事务同步
synchronous_commit = on # 同步提交
# 事务行为
default_transaction_read_only = off # 默认读写事务
default_transaction_deferrable = off # 默认非可延迟事务
# 示例:修改事务配置
ALTER SYSTEM SET default_transaction_isolation = ‘repeatable read’;
ALTER SYSTEM SET idle_in_transaction_session_timeout = ‘30000’; # 30秒
SELECT pg_reload_conf();
2.2 PostgreSQL事务性能优化
PostgreSQL事务性能优化建议:
# 事务管理优化
– 减少事务长度:避免长事务
– 批量操作:使用批量插入和更新
– 合理使用事务:避免不必要的事务
– 适当使用保存点:用于复杂事务
# 并发控制优化
– 选择合适的隔离级别
– 减少锁竞争:合理设计表结构和索引
– 使用乐观并发控制:适用于读多写少的场景
– 避免全表扫描:使用索引
# 事务参数优化
– 调整synchronous_commit:权衡一致性和性能
– 调整idle_in_transaction_session_timeout:避免长时间空闲事务
– 调整deadlock_timeout:合理设置死锁检测超时
# 示例:批量操作
BEGIN;
INSERT INTO fgedu_fgedus (fgeduname, email) VALUES
(‘fgedu1’, ‘fgedu1@fgedu.net.cn’),
(‘fgedu2’, ‘fgedu2@fgedu.net.cn’),
(‘fgedu3’, ‘fgedu3@fgedu.net.cn’);
COMMIT;
# 示例:使用保存点
BEGIN;
INSERT INTO fgedu_orders (customer_id, amount) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO fgedu_order_items (order_id, product_id, quantity) VALUES (1, 1, 2);
ROLLBACK TO sp1;
INSERT INTO fgedu_order_items (order_id, product_id, quantity) VALUES (1, 2, 1);
COMMIT;
2.3 PostgreSQL事务监控
PostgreSQL事务监控建议:
- 活跃事务:监控当前活跃的事务
- 长事务:监控运行时间过长的事务
- 锁定情况:监控锁的使用情况
- 死锁:监控死锁事件
- 事务统计:监控事务的执行统计
Part03-生产环境项目实施方案
3.1 PostgreSQL事务实施
3.1.1 事务控制语句
# 开始事务
BEGIN;
— 或
START TRANSACTION;
# 提交事务
COMMIT;
# 回滚事务
ROLLBACK;
# 保存点
SAVEPOINT savepoint_name;
ROLLBACK TO savepoint_name;
RELEASE SAVEPOINT savepoint_name;
# 设置事务属性
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRANSACTION READ WRITE;
BEGIN TRANSACTION DEFERRABLE;
# 示例:完整事务
BEGIN;
— 执行操作
UPDATE fgedu_fgedus SET fgeduname = ‘newfgedu’ WHERE id = 1;
INSERT INTO fgedu_audit (fgedu_id, action, timestamp) VALUES (1, ‘update’, NOW());
— 提交事务
COMMIT;
3.1.2 事务状态管理
# 查看当前事务状态
SELECT
txid_current(),
current_transaction_id();
# 查看活跃事务
SELECT
pid,
usename,
fgapplication_name,
client_addr,
state,
query_start,
now() – query_start AS duration,
query
FROM pg_stat_activity
WHERE state = ‘active’;
# 终止长事务
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE now() – query_start > interval ‘5 minutes’
AND state = ‘active’;
# 查看事务统计
SELECT
datname,
xact_commit,
xact_rollback,
blks_read,
blks_hit
FROM pg_stat_fgedudb
WHERE datname = ‘fgedudb’;
3.2 PostgreSQL事务隔离级别
3.2.1 隔离级别的类型
# 隔离级别类型
– READ UNCOMMITTED:读未提交
– READ COMMITTED:读已提交(默认)
– REPEATABLE READ:可重复读
– SERIALIZABLE:可串行化
# 隔离级别的设置
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED;
# 查看当前隔离级别
SHOW transaction_isolation;
# 不同隔离级别的特点
– READ UNCOMMITTED:可能读取到未提交的数据(脏读)
– READ COMMITTED:只能读取到已提交的数据,可能出现不可重复读
– REPEATABLE READ:确保同一事务中多次读取相同数据结果一致,可能出现幻读
– SERIALIZABLE:最高隔离级别,确保事务串行执行
# 示例:设置隔离级别
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM fgedu_fgedus WHERE id = 1;
— 其他操作
COMMIT;
3.2.2 隔离级别的选择
# 读已提交(默认)
– 适用场景:大多数应用
– 特点:并发性能好,避免脏读
– 缺点:可能出现不可重复读和幻读
# 可重复读
– 适用场景:需要一致性读取的应用
– 特点:确保同一事务中读取结果一致
– 缺点:并发性能略有下降
# 可串行化
– 适用场景:需要最高一致性的应用
– 特点:确保事务串行执行
– 缺点:并发性能较低
# 示例:根据场景选择隔离级别
— 普通业务操作
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
— 财务操作
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
3.3 PostgreSQL事务恢复
3.3.1 崩溃恢复
# 崩溃恢复过程
1. 数据库启动时,自动执行恢复
2. 重放未提交的WAL记录
3. 回滚未提交的事务
4. 确保数据一致性
# 查看恢复状态
SELECT
pg_is_in_recovery(),
pg_last_wal_replay_lsn(),
pg_last_wal_replay_time();
# 强制检查点
CHECKPOINT;
# 示例:模拟崩溃恢复
— 停止数据库
pg_ctl stop -D /postgresql/data -m immediate
— 启动数据库(自动执行恢复)
pg_ctl start -D /postgresql/data
3.3.2 时间点恢复(PITR)
# 准备工作
– 启用WAL归档
– 定期备份基础备份
# 恢复步骤
1. 停止数据库
2. 还原基础备份
3. 创建recovery.conf文件
4. 启动数据库,开始恢复
5. 恢复到指定时间点后停止
# recovery.conf示例
recovery_target = ‘2024-01-01 12:00:00’
recovery_target_timeline = ‘latest’
restore_command = ‘cp /archive/%f %p’
# 查看恢复进度
SELECT
pg_is_in_recovery(),
pg_last_wal_replay_lsn(),
pg_last_wal_replay_time();
Part04-生产案例与实战讲解
4.1 PostgreSQL事务实战案例
4.1.1 银行转账案例
# 创建表结构
CREATE TABLE fgedu_accounts (
id SERIAL PRIMARY KEY,
account_number VARCHAR(20) UNIQUE NOT NULL,
balance NUMERIC(10,2) NOT NULL
);
# 插入测试数据
INSERT INTO fgedu_accounts (account_number, balance) VALUES
(‘A001’, 10000.00),
(‘A002’, 5000.00);
# 转账事务
BEGIN;
— 检查余额
SELECT balance FROM fgedu_accounts WHERE account_number = ‘A001’;
— 执行转账
UPDATE fgedu_accounts SET balance = balance – 1000.00 WHERE account_number = ‘A001’;
UPDATE fgedu_accounts SET balance = balance + 1000.00 WHERE account_number = ‘A002’;
— 验证结果
SELECT * FROM fgedu_accounts;
— 提交事务
COMMIT;
# 执行结果
account_number | balance
—————+——–
A001 | 9000.00
A002 | 6000.00
# 错误处理案例
BEGIN;
— 检查余额
SELECT balance FROM fgedu_accounts WHERE account_number = ‘A001’;
— 执行转账(金额过大)
UPDATE fgedu_accounts SET balance = balance – 20000.00 WHERE account_number = ‘A001’;
— 检查余额是否为负
SELECT balance FROM fgedu_accounts WHERE account_number = ‘A001’;
— 发现余额为负,回滚事务
ROLLBACK;
# 执行结果
account_number | balance
—————+——–
A001 | 9000.00
A002 | 6000.00
4.2 PostgreSQL事务工具使用
4.2.1 使用pg_stat_activity监控事务
# 查看活跃事务
SELECT
pid,
usename,
fgapplication_name,
client_addr,
state,
query_start,
now() – query_start AS duration,
query
FROM pg_stat_activity
WHERE state = ‘active’;
# 查看长事务
SELECT
pid,
usename,
fgapplication_name,
client_addr,
state,
query_start,
now() – query_start AS duration,
query
FROM pg_stat_activity
WHERE now() – query_start > interval ‘5 minutes’
AND state = ‘active’;
# 终止长事务
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE now() – query_start > interval ’10 minutes’
AND state = ‘active’;
# 查看事务统计
SELECT
datname,
xact_commit,
xact_rollback,
blks_read,
blks_hit
FROM pg_stat_fgedudb
WHERE datname = ‘fgedudb’;
4.3 PostgreSQL事务常见问题
PostgreSQL事务常见问题及解决方法:
# 症状:事务运行时间过长
# 解决方法
– 优化事务逻辑,减少事务长度
– 拆分大事务为小事务
– 设置idle_in_transaction_session_timeout
– 定期监控和终止长事务
# 常见问题2:死锁
# 错误信息
ERROR: deadlock detected
DETAIL: Process 1234 waits for ShareLock on transaction 5678; blocked by process 5678.
Process 5678 waits for ShareLock on transaction 1234; blocked by process 1234.
# 解决方法
– 避免循环依赖
– 统一锁顺序
– 使用较短的事务
– 适当使用索引减少锁范围
– 设置deadlock_timeout
# 常见问题3:锁竞争
# 症状:事务等待锁时间过长
# 解决方法
– 优化查询,减少锁持有时间
– 使用合适的隔离级别
– 避免全表扫描
– 合理设计表结构和索引
– 考虑使用乐观并发控制
# 常见问题4:事务回滚
# 错误信息
ERROR: current transaction is aborted, commands ignored until end of transaction block
# 解决方法
– 检查事务中的错误
– 回滚事务
– 重新开始事务
– 修复错误后重新执行
Part05-风哥经验总结与分享
5.1 PostgreSQL事务最佳实践
PostgreSQL事务最佳实践:
- 保持事务简短:避免长事务,减少锁持有时间
- 合理使用批量操作:减少事务数量
- 选择合适的隔离级别:根据业务需求选择
- 避免不必要的事务:只在需要时使用事务
- 使用保存点:用于复杂事务的部分回滚
- 监控事务执行:及时发现和解决问题
- 优化锁使用:减少锁竞争
- 定期维护:执行VACUUM和ANALYZE
- 合理设置事务参数:根据硬件和负载调整
- 备份事务日志:确保数据可恢复
5.2 PostgreSQL事务检查清单
– [ ] 事务长度是否合理
– [ ] 隔离级别是否选择正确
– [ ] 锁竞争是否严重
– [ ] 死锁是否频繁发生
– [ ] 长事务是否存在
– [ ] 事务监控是否到位
– [ ] 事务性能是否优化
– [ ] 事务恢复是否测试
# 事务维护清单
– [ ] 定期监控活跃事务
– [ ] 定期清理长事务
– [ ] 定期分析事务执行情况
– [ ] 定期测试事务恢复
– [ ] 优化事务逻辑
– [ ] 调整事务配置参数
5.3 PostgreSQL事务工具推荐
PostgreSQL事务工具推荐:
- pg_stat_activity:查看活跃事务
- pg_locks:查看锁信息
- pg_stat_statements:查看SQL执行统计
- pg_terminate_backend:终止后台进程
- pg_cancel_backend:取消后台进程
- pg_waldump:查看WAL内容
- CHECKPOINT:执行检查点
- EXPLAIN ANALYZE:分析SQL执行计划
- pg_stat_fgedudb:查看数据库统计信息
- pg_xact_commit_stats:查看事务提交统计
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
