yashanb教程FG194-YashanDB长事务处理
本文档风哥主要介绍YashanDB长事务处理相关知识,包括YashanDB长事务的概念、影响、原因、处理规划、预防措施、实现、监控、故障排查、生产案例与实战讲解等内容,风哥教程参考YashanDB官方文档性能调优内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
Part01-基础概念与理论知识
1.1 YashanDB长事务的概念
YashanDB长事务是指执行时间较长的事务,通常是指执行时间超过一定阈值(如10秒、1分钟或更长)的事务。长事务可能会占用数据库资源,影响其他事务的执行,甚至导致数据库性能下降。更多视频教程www.fgedu.net.cn
- 长事务是指执行时间较长的事务
- 长事务的阈值通常根据业务需求和系统性能来定义
- 长事务可能会占用数据库资源,影响其他事务的执行
- 长事务可能导致锁等待、死锁等问题
1.2 YashanDB长事务的影响
YashanDB长事务的影响包括:
- 锁竞争:长事务会持有锁的时间较长,导致其他事务等待
- 资源占用:长事务会占用数据库连接、内存等资源
- 性能下降:长事务会导致数据库性能下降,影响整体系统性能
- 回滚开销:长事务的回滚会消耗大量资源和时间
- 日志增长:长事务会产生大量的 redo 日志,导致日志文件增长过快
- 备份影响:长事务会影响数据库备份的执行
1.3 YashanDB长事务的原因
YashanDB长事务的常见原因包括:
- 大数据量操作:处理大量数据的操作,如批量更新、删除或插入
- 复杂查询:执行复杂的查询,如多表关联、聚合操作等
- 锁等待:事务等待其他事务释放锁
- 外部资源:事务依赖外部资源,如网络I/O、文件I/O等
- 事务设计不合理:事务范围过大,包含了不必要的操作
- 系统资源不足:CPU、内存、磁盘I/O等系统资源不足
Part02-生产环境规划与建议
2.1 YashanDB长事务处理规划
YashanDB长事务处理规划建议:
– 预防为主:通过合理的设计和优化,预防长事务的发生
– 监控及时:建立长事务监控机制,及时发现长事务
– 处理高效:建立长事务处理流程,确保长事务能够被及时处理
– 影响最小化:采取措施,将长事务的影响降到最低
# 长事务处理流程
1. 监控:通过监控系统及时发现长事务
2. 分析:分析长事务的原因和影响
3. 处理:根据长事务的类型和影响,采取相应的处理措施
4. 优化:针对长事务的原因,进行优化,避免类似问题的发生
5. 记录:记录长事务的处理过程和结果,为后续优化提供参考
# 长事务处理策略
– 预防策略:合理设计事务范围,优化SQL语句,避免大数据量操作
– 监控策略:建立长事务监控机制,设置合理的告警阈值
– 处理策略:对长事务进行分析和处理,必要时终止长事务
– 优化策略:针对长事务的原因,进行系统优化和应用优化
2.2 YashanDB长事务预防措施
YashanDB长事务预防措施建议:
# 1. 事务设计优化
– 缩小事务范围:将大事务拆分为多个小事务
– 避免不必要的操作:只包含必要的操作在事务中
– 合理设置事务隔离级别:根据业务需求选择合适的隔离级别
– 及时提交或回滚:避免事务长时间处于未提交状态
# 2. SQL语句优化
– 优化查询语句:使用合适的索引,避免全表扫描
– 优化批量操作:使用批量处理,减少事务次数
– 避免复杂查询:将复杂查询拆分为多个简单查询
– 使用绑定变量:减少硬解析,提高执行效率
# 3. 系统配置优化
– 合理设置超时参数:设置事务超时时间,避免事务无限期执行
– 优化内存配置:增加共享池和PGA的大小
– 优化I/O配置:使用高性能存储,提高I/O速度
– 合理设置并行度:根据系统资源设置合适的并行度
# 4. 应用程序优化
– 异步处理:将耗时操作改为异步处理
– 批量处理:对大量数据的操作采用批量处理
– 连接池管理:合理使用连接池,避免连接泄漏
– 错误处理:及时处理异常,避免事务长时间挂起
# 5. 监控和告警
– 建立长事务监控机制:监控事务的执行时间
– 设置合理的告警阈值:当事务执行时间超过阈值时告警
– 定期分析:定期分析长事务,找出优化机会
– 性能基准:建立性能基准,及时发现性能异常
2.3 YashanDB长事务处理最佳实践
YashanDB长事务处理最佳实践:
# 1. 事务设计
– 保持事务简短:事务应尽可能简短,只包含必要的操作
– 避免在事务中进行非数据库操作:如网络I/O、文件I/O等
– 合理设置事务隔离级别:根据业务需求选择合适的隔离级别
– 及时提交或回滚:避免事务长时间处于未提交状态
# 2. SQL优化
– 使用绑定变量:减少硬解析,提高执行效率
– 优化索引:确保查询使用合适的索引
– 避免全表扫描:对大表进行操作时,使用索引或分区
– 优化批量操作:使用批量插入、更新和删除
# 3. 系统配置
– 设置合理的超时参数:如事务超时、语句超时
– 优化内存配置:增加共享池和PGA的大小
– 优化I/O配置:使用RAID、SSD等高性能存储
– 合理设置并行度:根据系统资源设置合适的并行度
# 4. 监控和管理
– 建立长事务监控机制:监控事务的执行时间和状态
– 设置合理的告警阈值:当事务执行时间超过阈值时告警
– 定期分析长事务:找出长事务的原因和优化机会
– 建立长事务处理流程:确保长事务能够被及时处理
# 5. 应急处理
– 准备应急方案:当长事务影响系统性能时,能够快速处理
– 建立回滚机制:当长事务无法正常完成时,能够安全回滚
– 定期演练:定期演练长事务的处理流程,确保应急方案的有效性
– 文档化:记录长事务的处理过程和结果,为后续优化提供参考
Part03-生产环境项目实施方案
3.1 YashanDB长事务处理实现
3.1.1 检测YashanDB长事务
# 1. 使用v$session视图检测长事务
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1 — 超过1分钟的事务
ORDER BY transaction_age_seconds DESC;
SID SERIAL# USERNAME STATUS SQL_ID SESSION_AGE_SECONDS TRANSACTION_AGE_SECONDS
——- ———- ———- ——– ————- ——————- ————————
123 456 FGEDU ACTIVE a1b2c3d4e5f6 3600 600
234 567 FGEDU ACTIVE f6e5d4c3b2a1 1800 300
# 2. 使用v$active_session_history视图检测长事务
SQL> SELECT session_id, sql_id,
MAX(elapsed_time) / 1000000 AS max_elapsed_seconds
FROM v$active_session_history
WHERE sample_time > SYSDATE – 1/24 — 最近1小时
GROUP BY session_id, sql_id
HAVING MAX(elapsed_time) / 1000000 > 60 — 超过60秒的SQL
ORDER BY max_elapsed_seconds DESC;
SESSION_ID SQL_ID MAX_ELAPSED_SECONDS
———- ————- ——————
123 a1b2c3d4e5f6 120
234 f6e5d4c3b2a1 90
# 3. 使用DBA_HIST_ACTIVE_SESS_HISTORY视图检测长事务
SQL> SELECT session_id, sql_id,
MAX(elapsed_time) / 1000000 AS max_elapsed_seconds
FROM dba_hist_active_sess_history
WHERE sample_time > SYSDATE – 7 — 最近7天
GROUP BY session_id, sql_id
HAVING MAX(elapsed_time) / 1000000 > 60 — 超过60秒的SQL
ORDER BY max_elapsed_seconds DESC;
SESSION_ID SQL_ID MAX_ELAPSED_SECONDS
———- ————- ——————
123 a1b2c3d4e5f6 180
234 f6e5d4c3b2a1 150
3.1.2 处理YashanDB长事务
# 1. 分析长事务
SQL> SELECT s.sid, s.serial#, s.username, s.machine, s.program,
t.start_time, t.used_ublk, t.used_urec,
q.sql_text
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
JOIN v$sql q ON s.sql_id = q.sql_id
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1 — 超过1分钟的事务
ORDER BY (SYSDATE – t.start_time) DESC;
SID SERIAL# USERNAME MACHINE PROGRAM START_TIME USED_UBLK USED_UREC SQL_TEXT
——- ———- ———- ———— —————- ————— ———- ———- —————————————-
123 456 FGEDU fgedu.net.cn sqlplus@fgedu.net 2026-04-01 10:00:00 100 1000 UPDATE fgedu.orders SET status = ‘COMPLETED’ WHERE order_date < SYSDATE - 30;
# 2. 终止长事务
SQL> ALTER SYSTEM KILL SESSION ‘123,456’ IMMEDIATE;
System altered.
# 3. 优化长事务
# 对于批量更新操作,使用批量处理
SQL> BEGIN
2 FOR i IN 1..10 LOOP
3 UPDATE fgedu.orders
4 SET status = ‘COMPLETED’
5 WHERE order_date < SYSDATE - 30
6 AND rownum <= 10000;
7 COMMIT;
8 EXIT WHEN SQL%ROWCOUNT = 0;
9 END LOOP;
10 END;
11 /
PL/SQL procedure successfully completed.
# 4. 设置事务超时
SQL> ALTER SYSTEM SET resource_limit = TRUE;
System altered.
SQL> CREATE PROFILE long_transaction_profile LIMIT
2 IDLE_TIME 30
3 CONNECT_TIME 120;
Profile created.
SQL> ALTER USER fgedu PROFILE long_transaction_profile;
User altered.
3.1.3 优化YashanDB长事务
# 1. 优化SQL语句
# 原SQL
UPDATE fgedu.orders SET status = ‘COMPLETED’ WHERE order_date < SYSDATE - 30;
# 优化后SQL
CREATE INDEX idx_orders_order_date ON fgedu.orders(order_date);
BEGIN
FOR i IN 1..10 LOOP
UPDATE fgedu.orders
SET status = 'COMPLETED'
WHERE order_date < SYSDATE - 30
AND rownum <= 10000;
COMMIT;
EXIT WHEN SQL%ROWCOUNT = 0;
END LOOP;
END;
/
# 2. 优化事务设计
# 原事务
BEGIN
-- 操作1
UPDATE fgedu.orders SET status = 'COMPLETED' WHERE order_date < SYSDATE - 30;
-- 操作2
INSERT INTO fgedu.order_history SELECT * FROM fgedu.orders WHERE status = 'COMPLETED';
-- 操作3
DELETE FROM fgedu.orders WHERE status = 'COMPLETED';
COMMIT;
END;
/
# 优化后事务
-- 操作1
BEGIN
FOR i IN 1..10 LOOP
UPDATE fgedu.orders
SET status = 'COMPLETED'
WHERE order_date < SYSDATE - 30
AND rownum <= 10000;
COMMIT;
EXIT WHEN SQL%ROWCOUNT = 0;
END LOOP;
END;
/
-- 操作2
BEGIN
FOR i IN 1..10 LOOP
INSERT INTO fgedu.order_history
SELECT * FROM fgedu.orders
WHERE status = 'COMPLETED'
AND rownum <= 10000;
COMMIT;
EXIT WHEN SQL%ROWCOUNT = 0;
END LOOP;
END;
/
-- 操作3
BEGIN
FOR i IN 1..10 LOOP
DELETE FROM fgedu.orders
WHERE status = 'COMPLETED'
AND rownum <= 10000;
COMMIT;
EXIT WHEN SQL%ROWCOUNT = 0;
END LOOP;
END;
/
# 3. 优化系统配置
# 增加共享池大小
SQL> ALTER SYSTEM SET shared_pool_size = 2G SCOPE=spfile;
# 增加PGA大小
SQL> ALTER SYSTEM SET pga_aggregate_target = 2G SCOPE=spfile;
# 设置事务超时
SQL> ALTER SYSTEM SET resource_limit = TRUE;
SQL> CREATE PROFILE long_transaction_profile LIMIT
2 IDLE_TIME 30
3 CONNECT_TIME 120;
SQL> ALTER USER fgedu PROFILE long_transaction_profile;
3.2 YashanDB长事务监控
3.2.1 YashanDB长事务监控命令
# 1. 监控当前活跃事务
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1 — 超过1分钟的事务
ORDER BY transaction_age_seconds DESC;
# 2. 监控SQL执行情况
SQL> SELECT sql_id, elapsed_time, buffer_gets, executions,
elapsed_time / executions / 1000000 AS avg_elapsed_seconds
FROM v$sql
WHERE executions > 0
AND elapsed_time / 1000000 > 60 — 超过60秒的SQL
ORDER BY elapsed_time DESC;
# 3. 监控锁等待
SQL> SELECT l.session_id, l.lock_type, l.mode_held, l.mode_requested,
s.username, s.sql_id, (SYSDATE – s.logon_time) * 24 * 60 AS minutes_active
FROM dba_locks l
JOIN v$session s ON l.session_id = s.sid
WHERE l.blocking_others = ‘Blocking’
ORDER BY minutes_active DESC;
# 4. 监控事务回滚
SQL> SELECT s.sid, s.serial#, s.username, r.used_ublk, r.used_urec,
r.start_time, (SYSDATE – r.start_time) * 24 * 60 AS minutes_rolling_back
FROM v$session s
JOIN v$rollstat r ON s.taddr = r.xid
WHERE r.status = ‘ACTIVE’
ORDER BY minutes_rolling_back DESC;
3.2.2 YashanDB长事务监控脚本
# long_transaction_monitor.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: `http://www.fgedu.net.cn`
# 长事务监控脚本
# 输出文件
output_file=”/tmp/long_transaction_monitor_$(date +%Y%m%d_%H%M%S).log”
echo “开始监控长事务” > ${output_file}
echo “监控时间: $(date)” >> ${output_file}
echo “” >> ${output_file}
# 监控当前活跃事务
echo “===== 当前活跃事务 ====” >> ${output_file}
sqlplus -s / as sysdba << EOF >> ${output_file}
SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v\$session s
JOIN v\$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1 — 超过1分钟的事务
ORDER BY transaction_age_seconds DESC;
EXIT;
EOF
echo “” >> ${output_file}
# 监控SQL执行情况
echo “===== SQL执行情况 ====” >> ${output_file}
sqlplus -s / as sysdba << EOF >> ${output_file}
SELECT sql_id, elapsed_time, buffer_gets, executions,
elapsed_time / executions / 1000000 AS avg_elapsed_seconds
FROM v\$sql
WHERE executions > 0
AND elapsed_time / 1000000 > 60 — 超过60秒的SQL
ORDER BY elapsed_time DESC
FETCH FIRST 10 ROWS ONLY;
EXIT;
EOF
echo “” >> ${output_file}
# 监控锁等待
echo “===== 锁等待 ====” >> ${output_file}
sqlplus -s / as sysdba << EOF >> ${output_file}
SELECT l.session_id, l.lock_type, l.mode_held, l.mode_requested,
s.username, s.sql_id, (SYSDATE – s.logon_time) * 24 * 60 AS minutes_active
FROM dba_locks l
JOIN v\$session s ON l.session_id = s.sid
WHERE l.blocking_others = ‘Blocking’
ORDER BY minutes_active DESC;
EXIT;
EOF
echo “” >> ${output_file}
echo “长事务监控完成,结果保存至:${output_file}” >> ${output_file}
echo “长事务监控完成,结果保存至:${output_file}”
# 检查是否有长事务
long_transaction_count=$(sqlplus -s / as sysdba << EOF
SET HEAD OFF
SET FEEDBACK OFF
SELECT COUNT(*) FROM v\$session s JOIN v\$transaction t ON s.taddr = t.addr WHERE (SYSDATE - t.start_time) * 24 * 60 > 5;
EXIT;
EOF
)
if [ $long_transaction_count -gt 0 ]; then
echo “发现长事务!数量: $long_transaction_count”
# 发送告警
echo “长事务告警:发现 $long_transaction_count 个长事务” | mail -s “YashanDB长事务告警” admin@fgedu.net.cn
fi
3.3 YashanDB长事务故障排查
3.3.1 YashanDB长事务故障排查步骤
# 1. 发现长事务
– 通过监控系统发现长事务
– 通过告警信息发现长事务
– 通过用户反馈发现长事务
# 2. 分析长事务
– 查看长事务的SQL语句
– 查看长事务的执行计划
– 查看长事务的资源使用情况
– 查看长事务的锁等待情况
# 3. 确定长事务的原因
– 大数据量操作
– 复杂查询
– 锁等待
– 外部资源依赖
– 系统资源不足
# 4. 采取处理措施
– 优化SQL语句
– 拆分长事务
– 终止长事务
– 增加系统资源
– 调整系统配置
# 5. 验证处理结果
– 检查长事务是否已结束
– 检查系统性能是否恢复
– 检查是否有其他影响
# 6. 预防措施
– 优化应用程序设计
– 加强监控和告警
– 定期性能分析
– 建立长事务处理流程
3.3.2 YashanDB长事务故障排查工具
# 1. 数据库视图
– v$session:查看会话信息
– v$transaction:查看事务信息
– v$sql:查看SQL语句信息
– v$active_session_history:查看活跃会话历史
– dba_locks:查看锁信息
– v$rollstat:查看回滚段信息
# 2. 诊断工具
– AWR (Automatic Workload Repository):自动工作负载仓库
– ASH (Active Session History):活跃会话历史
– ADDM (Automatic Database Diagnostic Monitor):自动数据库诊断监控器
– SQL Tuning Advisor:SQL调优顾问
– Enterprise Manager:企业管理器
# 3. 操作系统工具
– top:查看系统资源使用情况
– iostat:查看I/O使用情况
– vmstat:查看虚拟内存使用情况
– netstat:查看网络使用情况
# 4. 第三方工具
– Toad:数据库管理工具
– SQL Developer:SQL开发工具
– Navicat:数据库管理工具
– Prometheus + Grafana:监控和可视化工具
Part04-生产案例与实战讲解
4.1 YashanDB长事务处理案例一
案例背景:某企业数据库系统出现长事务,导致系统性能下降,需要及时处理。
# 1. 环境信息
– 数据库版本:YashanDB 19c
– 操作系统:Oracle Linux 9.3
– 硬件配置:8核CPU,32GB内存,1TB SSD
– 业务类型:OLTP
# 2. 问题描述
– 系统性能下降,用户反映操作缓慢
– 监控系统告警,发现长事务
– 数据库连接数增加,资源使用率高
# 3. 故障排查
# 查看长事务
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1 — 超过1分钟的事务
ORDER BY transaction_age_seconds DESC;
SID SERIAL# USERNAME STATUS SQL_ID SESSION_AGE_SECONDS TRANSACTION_AGE_SECONDS
——- ———- ———- ——– ————- ——————- ————————
123 456 FGEDU ACTIVE a1b2c3d4e5f6 3600 600
# 查看长事务的SQL语句
SQL> SELECT sql_text FROM v$sql WHERE sql_id = ‘a1b2c3d4e5f6’;
SQL_TEXT
—————————————-
UPDATE fgedu.orders SET status = ‘COMPLETED’ WHERE order_date < SYSDATE - 30;
# 查看执行计划
SQL> EXPLAIN PLAN FOR UPDATE fgedu.orders SET status = ‘COMPLETED’ WHERE order_date < SYSDATE - 30;
Explained.
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
—————————————-
Plan hash value: 1234567890
——————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
——————————————————————————-
| 0 | UPDATE STATEMENT | | 100K| 1000K| 1000 (5)| 00:00:01 |
| 1 | UPDATE | ORDERS | | | | |
| 2 | FULL TABLE SCAN| ORDERS | 100K| 1000K| 1000 (5)| 00:00:01 |
——————————————————————————-
# 4. 处理措施
# 优化SQL语句
SQL> CREATE INDEX idx_orders_order_date ON fgedu.orders(order_date);
Index created.
# 拆分长事务
SQL> BEGIN
2 FOR i IN 1..10 LOOP
3 UPDATE fgedu.orders
4 SET status = ‘COMPLETED’
5 WHERE order_date < SYSDATE - 30
6 AND rownum <= 10000;
7 COMMIT;
8 EXIT WHEN SQL%ROWCOUNT = 0;
9 END LOOP;
10 END;
11 /
PL/SQL procedure successfully completed.
# 终止长事务
SQL> ALTER SYSTEM KILL SESSION ‘123,456’ IMMEDIATE;
System altered.
# 5. 验证结果
# 检查长事务是否已结束
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1;
no rows selected
# 检查系统性能是否恢复
$ sar -u 1 5
Linux 5.4.0-80-generic (fgedu.net.cn) 04/01/2026 _x86_64_ (8 CPU)
10:00:00 AM CPU %user %nice %system %iowait %steal %idle
10:00:01 AM all 5.23 0.00 1.25 0.00 0.00 93.52
10:00:02 AM all 4.88 0.00 1.12 0.00 0.00 93.99
10:00:03 AM all 5.12 0.00 1.35 0.00 0.00 93.53
10:00:04 AM all 4.95 0.00 1.28 0.00 0.00 93.77
10:00:05 AM all 5.32 0.00 1.45 0.00 0.00 93.23
Average: all 5.10 0.00 1.31 0.00 0.00 93.59
# 6. 预防措施
# 优化应用程序设计
– 拆分大事务为小事务
– 使用批量处理处理大量数据
– 合理设置事务隔离级别
# 加强监控和告警
– 配置长事务监控
– 设置合理的告警阈值
– 定期分析长事务
# 系统配置优化
– 增加共享池和PGA大小
– 设置事务超时参数
– 优化I/O配置
4.2 YashanDB长事务处理案例二
案例背景:某电商系统在大促期间出现长事务,导致系统响应缓慢,需要及时处理。
# 1. 环境信息
– 数据库版本:YashanDB 19c
– 操作系统:Oracle Linux 9.3
– 硬件配置:16核CPU,64GB内存,2TB SSD
– 业务类型:OLTP,大促期间高并发
# 2. 问题描述
– 大促期间系统响应缓慢
– 监控系统告警,发现大量长事务
– 数据库连接数达到上限,资源使用率高
# 3. 故障排查
# 查看长事务
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1 — 超过1分钟的事务
ORDER BY transaction_age_seconds DESC;
SID SERIAL# USERNAME STATUS SQL_ID SESSION_AGE_SECONDS TRANSACTION_AGE_SECONDS
——- ———- ———- ——– ————- ——————- ————————
123 456 FGEDU ACTIVE a1b2c3d4e5f6 3600 600
234 567 FGEDU ACTIVE f6e5d4c3b2a1 1800 300
345 678 FGEDU ACTIVE g7h8i9j0k1l2 1200 200
# 查看长事务的SQL语句
SQL> SELECT sql_text FROM v$sql WHERE sql_id = ‘a1b2c3d4e5f6’;
SQL_TEXT
—————————————-
INSERT INTO fgedu.order_items SELECT * FROM fgedu.temp_order_items;
SQL> SELECT sql_text FROM v$sql WHERE sql_id = ‘f6e5d4c3b2a1’;
SQL_TEXT
—————————————-
UPDATE fgedu.orders SET total_amount = (SELECT SUM(price * quantity) FROM fgedu.order_items WHERE order_id = orders.order_id);
# 查看执行计划
SQL> EXPLAIN PLAN FOR INSERT INTO fgedu.order_items SELECT * FROM fgedu.temp_order_items;
Explained.
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
—————————————-
Plan hash value: 1234567890
——————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
——————————————————————————-
| 0 | INSERT STATEMENT | | 10M| 100M| 10000 (5)| 00:00:01 |
| 1 | LOAD TABLE CONVENTIONAL | ORDER_ITEMS | | | | |
| 2 | TABLE ACCESS FULL| TEMP_ORDER_ITEMS | 10M| 100M| 10000 (5)| 00:00:01 |
——————————————————————————-
# 4. 处理措施
# 优化SQL语句
# 对于批量插入,使用批量处理
SQL> BEGIN
2 FOR i IN 1..100 LOOP
3 INSERT INTO fgedu.order_items
4 SELECT * FROM fgedu.temp_order_items
5 WHERE rownum <= 100000;
6 COMMIT;
7 DELETE FROM fgedu.temp_order_items WHERE rownum <= 100000;
8 COMMIT;
9 EXIT WHEN SQL%ROWCOUNT = 0;
10 END LOOP;
11 END;
12 /
PL/SQL procedure successfully completed.
# 优化UPDATE语句,使用索引
SQL> CREATE INDEX idx_order_items_order_id ON fgedu.order_items(order_id);
Index created.
SQL> UPDATE /*+ PARALLEL(4) */ fgedu.orders
SET total_amount = (SELECT SUM(price * quantity)
FROM fgedu.order_items
WHERE order_id = orders.order_id);
# 终止长事务
SQL> ALTER SYSTEM KILL SESSION ‘123,456’ IMMEDIATE;
SQL> ALTER SYSTEM KILL SESSION ‘234,567’ IMMEDIATE;
SQL> ALTER SYSTEM KILL SESSION ‘345,678’ IMMEDIATE;
# 5. 验证结果
# 检查长事务是否已结束
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1;
no rows selected
# 检查系统性能是否恢复
$ sar -u 1 5
Linux 5.4.0-80-generic (fgedu.net.cn) 04/01/2026 _x86_64_ (16 CPU)
10:00:00 AM CPU %user %nice %system %iowait %steal %idle
10:00:01 AM all 15.23 0.00 3.25 0.00 0.00 81.52
10:00:02 AM all 14.88 0.00 3.12 0.00 0.00 81.99
10:00:03 AM all 15.12 0.00 3.35 0.00 0.00 81.53
10:00:04 AM all 14.95 0.00 3.28 0.00 0.00 81.77
10:00:05 AM all 15.32 0.00 3.45 0.00 0.00 81.23
Average: all 15.10 0.00 3.31 0.00 0.00 81.59
# 6. 预防措施
# 优化应用程序设计
– 使用批量处理处理大量数据
– 避免在事务中进行大量数据操作
– 合理设置事务隔离级别
# 加强监控和告警
– 配置长事务监控
– 设置合理的告警阈值
– 大促期间安排专人监控
# 系统配置优化
– 增加共享池和PGA大小
– 设置事务超时参数
– 优化I/O配置,使用RAID 10
4.3 YashanDB长事务处理案例三
案例背景:某金融系统出现长事务,导致数据库备份失败,需要及时处理。
# 1. 环境信息
– 数据库版本:YashanDB 19c
– 操作系统:Oracle Linux 9.3
– 硬件配置:12核CPU,48GB内存,1.5TB SSD
– 业务类型:OLTP,金融交易
# 2. 问题描述
– 数据库备份失败,报错”ORA-01555: snapshot too old”
– 监控系统告警,发现长事务
– 数据库性能下降,交易响应缓慢
# 3. 故障排查
# 查看长事务
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1 — 超过1分钟的事务
ORDER BY transaction_age_seconds DESC;
SID SERIAL# USERNAME STATUS SQL_ID SESSION_AGE_SECONDS TRANSACTION_AGE_SECONDS
——- ———- ———- ——– ————- ——————- ————————
123 456 FGEDU ACTIVE a1b2c3d4e5f6 7200 3600
# 查看长事务的SQL语句
SQL> SELECT sql_text FROM v$sql WHERE sql_id = ‘a1b2c3d4e5f6’;
SQL_TEXT
—————————————-
BEGIN
FOR i IN 1..1000 LOOP
UPDATE fgedu.transactions SET status = ‘COMPLETED’ WHERE transaction_id = i;
— 模拟外部调用
dbms_lock.sleep(1);
END LOOP;
COMMIT;
END;
# 4. 处理措施
# 终止长事务
SQL> ALTER SYSTEM KILL SESSION ‘123,456’ IMMEDIATE;
System altered.
# 优化事务设计
# 原事务
BEGIN
FOR i IN 1..1000 LOOP
UPDATE fgedu.transactions SET status = ‘COMPLETED’ WHERE transaction_id = i;
— 模拟外部调用
dbms_lock.sleep(1);
END LOOP;
COMMIT;
END;
/
# 优化后事务
BEGIN
FOR i IN 1..1000 LOOP
UPDATE fgedu.transactions SET status = ‘COMPLETED’ WHERE transaction_id = i;
— 每100条提交一次
IF MOD(i, 100) = 0 THEN
COMMIT;
END IF;
END LOOP;
COMMIT;
END;
/
# 优化外部调用
# 将外部调用移到事务外
BEGIN
FOR i IN 1..1000 LOOP
UPDATE fgedu.transactions SET status = ‘COMPLETED’ WHERE transaction_id = i;
— 每100条提交一次
IF MOD(i, 100) = 0 THEN
COMMIT;
— 模拟外部调用
dbms_lock.sleep(1);
END IF;
END LOOP;
COMMIT;
END;
/
# 5. 验证结果
# 检查长事务是否已结束
SQL> SELECT s.sid, s.serial#, s.username, s.status, s.sql_id,
(SYSDATE – s.logon_time) * 24 * 60 * 60 AS session_age_seconds,
(SYSDATE – t.start_time) * 24 * 60 * 60 AS transaction_age_seconds
FROM v$session s
JOIN v$transaction t ON s.taddr = t.addr
WHERE (SYSDATE – t.start_time) * 24 * 60 > 1;
no rows selected
# 重新执行备份
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;
Starting backup at 2026-04-01 10:00:00
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=123 device type=DISK
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00001 name=/yashanb/fgdata/fgedudb/system01.dbf
input datafile file number=00002 name=/yashanb/fgdata/fgedudb/sysaux01.dbf
input datafile file number=00003 name=/yashanb/fgdata/fgedudb/undotbs01.dbf
input datafile file number=00004 name=/yashanb/fgdata/fgedudb/users01.dbf
input datafile file number=00005 name=/yashanb/fgdata/fgedudb/fgedutbs01.dbf
channel ORA_DISK_1: starting piece 1 at 2026-04-01 10:00:00
channel ORA_DISK_1: finished piece 1 at 2026-04-01 10:05:00
piece handle=/yashanb/backup/fgedudb_full_20260401_12345.bkp tag=TAG20260401T100000 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:05:00
channel ORA_DISK_1: starting archived log backup set
channel ORA_DISK_1: specifying archived log(s) in backup set
input archived log thread=1 sequence=100
input archived log thread=1 sequence=101
input archived log thread=1 sequence=102
channel ORA_DISK_1: starting piece 1 at 2026-04-01 10:05:00
channel ORA_DISK_1: finished piece 1 at 2026-04-01 10:05:30
piece handle=/yashanb/backup/fgedudb_arch_20260401_12346.bkp tag=TAG20260401T100500 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:30
Finished backup at 2026-04-01 10:05:30
# 6. 预防措施
# 优化应用程序设计
– 避免在事务中进行外部调用
– 合理设置事务范围,及时提交或回滚
– 使用批量处理处理大量数据
# 加强监控和告警
– 配置长事务监控
– 设置合理的告警阈值
– 定期检查长事务
# 系统配置优化
– 增加undo表空间大小
– 设置合理的undo_retention参数
– 优化备份策略,避开业务高峰期
Part05-风哥经验总结与分享
5.1 YashanDB长事务处理经验总结
YashanDB长事务处理经验总结:
- 预防为主:通过合理的设计和优化,预防长事务的发生
- 监控及时:建立长事务监控机制,及时发现长事务
- 处理高效:建立长事务处理流程,确保长事务能够被及时处理
- 优化持续:针对长事务的原因,持续进行优化
- 文档完善:记录长事务的处理过程和结果,为后续优化提供参考
- 培训加强:加强开发人员和运维人员的培训,提高长事务处理能力
- 工具使用:合理使用数据库工具,提高长事务处理效率
- 应急演练:定期进行长事务处理的应急演练,确保应急方案的有效性
5.2 YashanDB长事务处理检查清单
– [ ] 长事务监控机制是否建立
– [ ] 长事务告警阈值是否合理
– [ ] 长事务处理流程是否完善
– [ ] 应用程序中是否存在长事务风险
– [ ] SQL语句是否优化
– [ ] 事务设计是否合理
– [ ] 系统配置是否优化
– [ ] 长事务处理工具是否准备
– [ ] 长事务处理应急方案是否制定
– [ ] 长事务处理演练是否定期进行
# 长事务预防检查清单
– [ ] 事务范围是否合理
– [ ] SQL语句是否优化
– [ ] 批量操作是否合理
– [ ] 外部调用是否移出事务
– [ ] 事务隔离级别是否合适
– [ ] 提交频率是否合理
– [ ] 系统资源是否充足
– [ ] 监控和告警是否到位
5.3 YashanDB长事务处理工具推荐
YashanDB长事务处理常用工具:
- 数据库视图:v$session、v$transaction、v$sql、v$active_session_history、dba_locks
- 诊断工具:AWR、ASH、ADDM、SQL Tuning Advisor、Enterprise Manager
- 操作系统工具:top、iostat、vmstat、netstat
- 第三方工具:Toad、SQL Developer、Navicat、Prometheus + Grafana
- 脚本工具:Shell脚本、Python脚本
- 监控工具:Zabbix、Nagios、Datadog
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
