外观
OceanBase 事务超时与死锁
事务超时原理与配置
事务超时类型
- 语句执行超时:单个 SQL 语句的执行时间超过设定阈值
- 事务执行超时:整个事务的执行时间超过设定阈值
- 锁等待超时:事务等待锁的时间超过设定阈值
事务超时配置
sql
-- 设置语句执行超时时间(毫秒)
ALTER SYSTEM SET ob_query_timeout = 10000;
-- 设置事务执行超时时间(毫秒)
ALTER SYSTEM SET ob_trx_timeout = 300000;
-- 设置锁等待超时时间(毫秒)
ALTER SYSTEM SET ob_trx_lock_timeout = 5000;
-- 设置租户级别的超时时间
ALTER TENANT tenant_name SET ob_query_timeout = 15000;
ALTER TENANT tenant_name SET ob_trx_timeout = 600000;
ALTER TENANT tenant_name SET ob_trx_lock_timeout = 10000;事务超时参数说明
| 参数名 | 描述 | 默认值 | 建议值 |
|---|---|---|---|
| ob_query_timeout | 语句执行超时时间(毫秒) | 10000 | 10000-30000 |
| ob_trx_timeout | 事务执行超时时间(毫秒) | 300000 | 300000-600000 |
| ob_trx_lock_timeout | 锁等待超时时间(毫秒) | 5000 | 5000-10000 |
| ob_trx_idle_timeout | 事务空闲超时时间(毫秒) | 86400000 | 86400000 |
| ob_trx_retry_timeout | 事务重试超时时间(毫秒) | 120000 | 120000 |
死锁原理与检测
死锁产生条件
- 互斥条件:资源不能被共享,只能被一个进程使用
- 请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求
- 不剥夺条件:进程已获得的资源,在未使用完之前,不能被强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
死锁检测机制
OceanBase 采用主动检测和被动检测相结合的方式处理死锁:
- 主动检测:定期扫描事务等待图,检测是否存在环
- 被动检测:当事务等待锁超时,检查是否存在死锁
- 死锁解除:选择一个代价最小的事务进行回滚,解除死锁
死锁检测配置
sql
-- 启用死锁检测
ALTER SYSTEM SET enable_deadlock_detection = 'true';
-- 设置死锁检测间隔(毫秒)
ALTER SYSTEM SET deadlock_detection_interval = 1000;
-- 设置死锁检测超时时间(毫秒)
ALTER SYSTEM SET deadlock_detection_timeout = 5000;事务超时与死锁处理
查看事务超时与死锁信息
sql
-- 查看当前活跃事务
SELECT * FROM oceanbase.GV$OB_TRX WHERE state = 'RUNNING';
-- 查看事务锁等待情况
SELECT * FROM oceanbase.GV$OB_LOCK_WAITSTAT;
-- 查看死锁历史记录
SELECT * FROM oceanbase.DBA_OB_DEADLOCK_HISTORY ORDER BY gmt_create DESC;
-- 查看超时事件
SELECT * FROM oceanbase.DBA_OB_EVENT_HISTORY WHERE event_type = 'timeout' ORDER BY gmt_create DESC;手动处理事务超时与死锁
sql
-- 终止长时间运行的事务
KILL SESSION 'session_id';
-- 查看会话信息
SELECT * FROM oceanbase.GV$OB_SESSIONS WHERE sessid = 'session_id';
-- 强制提交或回滚事务
ALTER SYSTEM KILL TRANSACTION 'trx_id';优化事务超时与死锁的 SQL
- 优化长事务:将长事务拆分为多个短事务
- 优化锁竞争:减少锁持有时间,避免全表锁
- 优化索引:确保查询使用索引,减少扫描范围
- 调整事务隔离级别:根据业务需求选择合适的隔离级别
sql
-- 查看 SQL 执行计划
EXPLAIN SELECT * FROM table_name WHERE condition;
-- 优化索引
CREATE INDEX idx_column ON table_name(column);
-- 调整事务隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;事务超时与死锁最佳实践
配置建议
- 合理设置超时参数:根据业务需求和系统性能,设置合适的超时时间
- 启用死锁检测:确保死锁检测功能已启用
- 调整检测间隔:根据系统负载调整死锁检测间隔
- 设置合理的隔离级别:根据业务需求选择合适的事务隔离级别
开发建议
- 避免长事务:尽量将事务拆分为多个短事务
- 减少锁持有时间:在事务中尽量减少不必要的操作,尽快提交或回滚
- 避免热点数据竞争:合理设计表结构和索引,减少热点数据的竞争
- 使用批量操作:对于大量数据的操作,使用批量操作减少事务数量
- 合理使用锁粒度:尽量使用行级锁,避免表级锁
监控与告警
- 监控事务超时:设置事务超时告警,及时发现长时间运行的事务
- 监控死锁事件:设置死锁告警,及时处理死锁问题
- 监控锁等待:监控锁等待时间和数量,及时发现锁竞争问题
- 定期分析:定期分析事务超时和死锁记录,找出根本原因
常见问题(FAQ)
Q1: 事务超时会导致数据不一致吗?
A1: 不会。OceanBase 会自动回滚超时的事务,确保数据一致性。当事务超时发生时,系统会终止事务并释放所有已获得的资源和锁。
Q2: 如何查看导致死锁的 SQL 语句?
A2: 可以通过以下方式查看导致死锁的 SQL 语句:
sql
-- 查看死锁历史记录,包含导致死锁的 SQL
SELECT * FROM oceanbase.DBA_OB_DEADLOCK_HISTORY ORDER BY gmt_create DESC;
-- 查看当前活跃事务的 SQL
SELECT s.sessid, t.trx_id, s.sql_text
FROM oceanbase.GV$OB_SESSIONS s
JOIN oceanbase.GV$OB_TRX t ON s.sessid = t.sessid
WHERE t.state = 'RUNNING';Q3: 死锁发生时,OceanBase 会如何处理?
A3: OceanBase 会自动检测死锁,并选择一个代价最小的事务进行回滚,解除死锁。被回滚的事务会收到一个死锁错误,应用程序需要处理这个错误并决定是否重试。
Q4: 如何避免事务超时?
A4: 可以通过以下方式避免事务超时:
- 优化 SQL 语句,提高执行效率
- 减少事务中的操作数量,缩短事务执行时间
- 合理设置超时参数
- 避免在事务中执行耗时的外部操作
Q5: 如何处理频繁发生的死锁?
A5: 对于频繁发生的死锁,可以采取以下措施:
- 分析死锁日志,找出导致死锁的根本原因
- 优化表结构和索引,减少锁竞争
- 调整事务执行顺序,避免循环等待
- 降低事务隔离级别
- 增加锁等待超时时间
sql
-- 查看死锁详细信息
SELECT * FROM oceanbase.DBA_OB_DEADLOCK_HISTORY WHERE trx_id1 = 'trx_id' OR trx_id2 = 'trx_id';
-- 优化索引
CREATE INDEX idx_new ON table_name(column1, column2);