外观
OceanBase 事务锁指标
核心概念
事务锁指标是指用于衡量和监控OceanBase数据库中事务锁行为的各种指标,包括锁等待、锁持有、死锁等方面的指标。事务锁是数据库并发控制的核心机制,用于保证数据的一致性和完整性。通过监控事务锁指标,可以了解数据库的并发情况,发现锁竞争和死锁问题,评估事务设计的合理性,以及优化数据库性能。事务锁指标的监控对于保障数据库的高并发性能和稳定性具有重要意义。
事务锁基础
1. 锁类型
功能:不同类型的锁用于控制不同级别的并发访问 适用场景:
- 不同粒度的数据访问控制
- 不同隔离级别下的并发控制
- 读写并发场景
核心锁类型:
| 锁类型 | 功能 | 适用场景 |
|---|---|---|
| 共享锁(S锁) | 允许并发读取,阻止写入 | 读操作 |
| 排他锁(X锁) | 阻止其他事务的读写操作 | 写操作 |
| 意向共享锁(IS锁) | 表级共享锁,用于表明事务计划在表中的行上设置共享锁 | 行级共享锁的表级意向 |
| 意向排他锁(IX锁) | 表级排他锁,用于表明事务计划在表中的行上设置排他锁 | 行级排他锁的表级意向 |
| 共享意向排他锁(SIX锁) | 表级锁,表明事务持有表的共享锁并计划在表中的行上设置排他锁 | 混合操作 |
2. 锁粒度
功能:锁粒度决定了锁的作用范围 适用场景:
- 不同数据量的并发访问
- 不同业务场景的并发需求
- 性能和并发度的平衡
核心锁粒度:
| 锁粒度 | 功能 | 适用场景 |
|---|---|---|
| 表级锁 | 锁定整个表 | 大量数据操作,如DDL |
| 分区级锁 | 锁定表的一个分区 | 分区表的批量操作 |
| 行级锁 | 锁定表中的一行或多行 | 单行或少量行的操作 |
| 页级锁 | 锁定数据页 | 批量行操作 |
3. 锁等待和死锁
功能:锁等待和死锁是锁竞争的两种表现形式 适用场景:
- 并发事务冲突
- 事务设计不合理
- 长事务导致的锁竞争
锁等待:当一个事务请求的锁被其他事务持有时,该事务会进入等待状态
死锁:两个或多个事务互相等待对方持有的锁,导致所有事务无法继续执行
核心锁指标
1. 锁等待指标
功能:衡量事务等待锁的情况 适用场景:
- 锁竞争检测
- 并发性能评估
- 长事务识别
核心指标:
| 指标名 | 含义 | 单位 | 建议阈值 |
|---|---|---|---|
lock_wait_time_total | 锁等待总时间 | 微秒 | < 1000000/秒 |
lock_wait_count | 锁等待次数 | 次 | < 100/秒 |
avg_lock_wait_time | 平均锁等待时间 | 微秒 | < 10000 |
max_lock_wait_time | 最大锁等待时间 | 微秒 | < 100000 |
lock_wait_ratio | 锁等待比率 | % | < 5% |
监控方法:
sql
-- 查询锁等待指标
SELECT
svr_ip,
svr_port,
tenant_id,
sum(lock_wait_time) AS lock_wait_time_total,
sum(lock_wait_count) AS lock_wait_count,
avg(lock_wait_time) AS avg_lock_wait_time,
max(lock_wait_time) AS max_lock_wait_time,
sum(lock_wait_count) / sum(total_count) * 100 AS lock_wait_ratio
FROM oceanbase.GV$OB_LOCK_WAIT_STAT
GROUP BY svr_ip, svr_port, tenant_id;2. 锁持有指标
功能:衡量事务持有锁的情况 适用场景:
- 长事务检测
- 锁资源占用评估
- 锁持有合理性分析
核心指标:
| 指标名 | 含义 | 单位 | 建议阈值 |
|---|---|---|---|
lock_hold_time_total | 锁持有总时间 | 微秒 | < 5000000/秒 |
avg_lock_hold_time | 平均锁持有时间 | 微秒 | < 50000 |
max_lock_hold_time | 最大锁持有时间 | 微秒 | < 500000 |
long_hold_lock_count | 长持有锁数量 | 个 | < 10 |
监控方法:
sql
-- 查询锁持有情况
SELECT
tx_id,
lock_type,
lock_mode,
table_name,
row_key,
hold_time,
waiter_count
FROM oceanbase.GV$OB_LOCKS
WHERE hold_time > 1000000; -- 持有时间超过1秒3. 死锁指标
功能:衡量死锁发生的情况 适用场景:
- 死锁检测
- 死锁原因分析
- 死锁预防
核心指标:
| 指标名 | 含义 | 单位 | 建议阈值 |
|---|---|---|---|
deadlock_count | 死锁发生次数 | 次 | 0 |
deadlock_resolve_time | 死锁解决时间 | 微秒 | < 100000 |
deadlock_involve_transactions | 死锁涉及事务数 | 个 | < 5 |
监控方法:
sql
-- 查询死锁信息
SELECT
deadlock_id,
deadlock_time,
tx_id1,
tx_id2,
victim_tx_id,
resolve_time
FROM oceanbase.GV$OB_DEADLOCKS
ORDER BY deadlock_time DESC;4. 锁竞争指标
功能:衡量锁竞争的激烈程度 适用场景:
- 锁竞争检测
- 高并发场景优化
- 资源争用分析
核心指标:
| 指标名 | 含义 | 单位 | 建议阈值 |
|---|---|---|---|
lock_contention_ratio | 锁竞争比率 | % | < 10% |
lock_waiters_per_lock | 每个锁的平均等待者数 | 个 | < 2 |
hot_lock_count | 热点锁数量 | 个 | < 5 |
lock_conflict_count | 锁冲突次数 | 次 | < 100/秒 |
监控方法:
sql
-- 查询锁竞争情况
SELECT
table_name,
lock_type,
count(*) AS lock_count,
sum(waiter_count) AS total_waiters,
avg(waiter_count) AS avg_waiters_per_lock,
max(waiter_count) AS max_waiters
FROM oceanbase.GV$OB_LOCKS
GROUP BY table_name, lock_type
HAVING sum(waiter_count) > 0
ORDER BY total_waiters DESC;锁指标监控方法
1. 内置视图监控
功能:使用OceanBase内置视图监控锁指标 适用场景:
- 实时锁监控
- 锁问题定位
- 历史锁分析
核心视图:
| 视图名 | 功能 |
|---|---|
GV$OB_LOCKS | 查看当前持有和等待的锁信息 |
GV$OB_LOCK_WAIT_STAT | 锁等待统计信息 |
GV$OB_DEADLOCKS | 死锁历史记录 |
GV$OB_TRANS_LOCK_STAT | 事务锁统计信息 |
GV$OB_LOCK_STAT | 锁统计信息 |
监控示例:
sql
-- 查看当前锁等待情况
SELECT
t1.svr_ip,
t1.svr_port,
t1.tenant_id,
t1.tx_id AS waiting_tx_id,
t2.tx_id AS holding_tx_id,
t1.lock_type,
t1.lock_mode,
t1.table_name,
t1.row_key,
t1.wait_time
FROM oceanbase.GV$OB_LOCK_WAITING t1
JOIN oceanbase.GV$OB_LOCKS t2
ON t1.svr_ip = t2.svr_ip
AND t1.svr_port = t2.svr_port
AND t1.tenant_id = t2.tenant_id
AND t1.table_id = t2.table_id
AND t1.row_key = t2.row_key
ORDER BY t1.wait_time DESC;2. 性能_schema监控
功能:使用performance_schema监控锁指标 适用场景:
- 细粒度锁监控
- 锁事件跟踪
- 性能分析
核心表:
| 表名 | 功能 |
|---|---|
performance_schema.events_waits_current | 当前等待事件 |
performance_schema.events_waits_history | 历史等待事件 |
performance_schema.events_waits_summary_global_by_event_name | 等待事件汇总 |
监控示例:
sql
-- 查看锁等待事件
SELECT
event_name,
count_star AS total_waits,
sum_timer_wait AS total_wait_time,
avg_timer_wait AS avg_wait_time,
max_timer_wait AS max_wait_time
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE event_name LIKE '%lock%'
ORDER BY sum_timer_wait DESC;3. 外部监控系统集成
功能:将锁指标集成到外部监控系统 适用场景:
- 集中监控
- 可视化展示
- 告警和通知
集成方法:
3.1 Prometheus集成
yaml
# Prometheus配置示例
scrape_configs:
- job_name: 'oceanbase-lock-metrics'
static_configs:
- targets: ['oceanbase-exporter:9184']
metrics_path: '/metrics'
scrape_interval: 15s
scrape_timeout: 10s3.2 Grafana可视化
bash
# Grafana仪表盘配置
# 1. 添加Prometheus数据源
# 2. 创建仪表盘
# 3. 添加锁指标面板:
# - lock_wait_time_total
# - lock_wait_count
# - deadlock_count
# - lock_contention_ratio
# 4. 设置告警规则
# 5. 保存并分享仪表盘4. 日志监控
功能:通过日志监控锁相关事件 适用场景:
- 死锁事件记录
- 锁等待日志
- 历史事件分析
配置示例:
sql
-- 启用锁日志
ALTER SYSTEM SET enable_lock_log = TRUE GLOBAL;
-- 设置锁等待日志阈值
ALTER SYSTEM SET lock_wait_log_threshold = 1000000 GLOBAL; -- 1秒
-- 查看锁日志
SELECT * FROM oceanbase.GV$OB_LOCK_LOGS
ORDER BY log_time DESC;锁指标分析方法
1. 锁等待分析
功能:分析锁等待的原因和影响 适用场景:
- 高锁等待时间
- 频繁的锁等待
- 长事务导致的锁问题
分析步骤:
- 定位锁等待的事务和资源
- 分析持有锁的事务情况
- 评估锁等待对系统的影响
- 制定优化方案
分析示例:
sql
-- 定位长时间锁等待
SELECT
waiting_tx.tx_id AS waiting_transaction,
waiting_tx.tenant_id,
waiting_tx.svr_ip,
waiting_tx.svr_port,
waiting_tx.wait_time,
waiting_lock.lock_type,
waiting_lock.lock_mode,
waiting_lock.table_name,
waiting_lock.row_key,
holding_tx.tx_id AS holding_transaction,
holding_tx.start_time,
holding_tx.elapsed_time AS holding_transaction_elapsed
FROM oceanbase.GV$OB_LOCK_WAITING waiting_lock
JOIN oceanbase.GV$OB_TRANSACTIONS waiting_tx
ON waiting_lock.svr_ip = waiting_tx.svr_ip
AND waiting_lock.svr_port = waiting_tx.svr_port
AND waiting_lock.tenant_id = waiting_tx.tenant_id
AND waiting_lock.tx_id = waiting_tx.tx_id
JOIN oceanbase.GV$OB_LOCKS holding_lock
ON waiting_lock.svr_ip = holding_lock.svr_ip
AND waiting_lock.svr_port = holding_lock.svr_port
AND waiting_lock.tenant_id = holding_lock.tenant_id
AND waiting_lock.table_id = holding_lock.table_id
AND waiting_lock.row_key = holding_lock.row_key
JOIN oceanbase.GV$OB_TRANSACTIONS holding_tx
ON holding_lock.svr_ip = holding_tx.svr_ip
AND holding_lock.svr_port = holding_tx.svr_port
AND holding_lock.tenant_id = holding_tx.tenant_id
AND holding_lock.tx_id = holding_tx.tx_id
WHERE waiting_lock.wait_time > 5000000; -- 等待时间超过5秒2. 死锁分析
功能:分析死锁的原因和解决方法 适用场景:
- 死锁事件发生
- 频繁的死锁
- 复杂事务设计
分析步骤:
- 查看死锁记录
- 分析死锁涉及的事务和资源
- 识别死锁产生的原因
- 制定预防和解决方案
分析示例:
sql
-- 查看最近的死锁记录
SELECT
d.deadlock_id,
d.deadlock_time,
d.tx_id1,
d.tx_id2,
d.victim_tx_id,
d.resolve_time,
t1.sql_text AS tx1_sql,
t2.sql_text AS tx2_sql
FROM oceanbase.GV$OB_DEADLOCKS d
JOIN oceanbase.GV$OB_TRANSACTIONS t1
ON d.svr_ip = t1.svr_ip
AND d.svr_port = t1.svr_port
AND d.tenant_id = t1.tenant_id
AND d.tx_id1 = t1.tx_id
JOIN oceanbase.GV$OB_TRANSACTIONS t2
ON d.svr_ip = t2.svr_ip
AND d.svr_port = t2.svr_port
AND d.tenant_id = t2.tenant_id
AND d.tx_id2 = t2.tx_id
ORDER BY d.deadlock_time DESC
LIMIT 10;3. 热点锁分析
功能:分析频繁被锁定的资源 适用场景:
- 高并发热点数据
- 频繁的锁竞争
- 性能瓶颈定位
分析步骤:
- 识别热点锁资源
- 分析热点形成的原因
- 评估热点锁对系统的影响
- 制定优化方案
分析示例:
sql
-- 识别热点锁资源
SELECT
table_name,
row_key,
count(*) AS lock_count,
sum(waiter_count) AS total_waiters,
avg(waiter_count) AS avg_waiters_per_lock
FROM oceanbase.GV$OB_LOCKS
GROUP BY table_name, row_key
HAVING count(*) > 10
ORDER BY total_waiters DESC;锁指标优化策略
1. 事务设计优化
功能:优化事务设计,减少锁竞争 适用场景:
- 长事务导致的锁问题
- 不合理的事务隔离级别
- 大量行锁定
优化方法:
1.1 缩短事务长度
sql
-- 优化前:长事务
START TRANSACTION;
-- 操作1:查询数据
SELECT * FROM orders WHERE id = 1;
-- 操作2:业务处理(耗时较长)
-- 操作3:更新数据
UPDATE orders SET status = 'processed' WHERE id = 1;
COMMIT;
-- 优化后:短事务
-- 操作1:业务处理(耗时较长)
-- 操作2:短事务处理
START TRANSACTION;
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
UPDATE orders SET status = 'processed' WHERE id = 1;
COMMIT;1.2 优化事务隔离级别
sql
-- 根据业务需求选择合适的隔离级别
-- 读未提交:READ UNCOMMITTED
-- 读提交:READ COMMITTED
-- 可重复读:REPEATABLE READ
-- 串行化:SERIALIZABLE
-- 设置事务隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;1.3 合理使用锁提示
sql
-- 优化前:默认锁行为
SELECT * FROM users WHERE id = 1;
UPDATE users SET balance = balance - 100 WHERE id = 1;
-- 优化后:使用锁提示
SELECT * FROM users WHERE id = 1 FOR UPDATE NOWAIT; -- 立即返回,不等待锁
UPDATE users SET balance = balance - 100 WHERE id = 1;2. 索引优化
功能:通过索引优化减少锁范围 适用场景:
- 全表扫描导致的锁问题
- 大范围的行锁定
- 索引缺失导致的锁竞争
优化方法:
2.1 添加合适的索引
sql
-- 优化前:无索引,全表扫描,锁定整个表
SELECT * FROM orders WHERE user_id = 123 FOR UPDATE;
-- 优化后:添加索引,只锁定匹配的行
CREATE INDEX idx_user_id ON orders(user_id);
SELECT * FROM orders WHERE user_id = 123 FOR UPDATE;2.2 优化索引设计
sql
-- 优化前:单列索引,锁范围较大
SELECT * FROM orders WHERE user_id = 123 AND status = 'pending' FOR UPDATE;
-- 优化后:联合索引,锁范围更小
CREATE INDEX idx_user_id_status ON orders(user_id, status);
SELECT * FROM orders WHERE user_id = 123 AND status = 'pending' FOR UPDATE;3. 并发控制优化
功能:优化并发控制机制,提高并发能力 适用场景:
- 高并发场景
- 锁竞争激烈
- 死锁频繁
优化方法:
3.1 启用乐观锁
sql
-- 乐观锁实现
UPDATE products
SET stock = stock - 1, version = version + 1
WHERE id = 1 AND version = 1;3.2 分区表设计
sql
-- 分区表设计,减少锁冲突
CREATE TABLE orders (
id BIGINT NOT NULL,
order_time DATETIME NOT NULL,
user_id BIGINT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
PRIMARY KEY (id, order_time)
) PARTITION BY RANGE COLUMNS(order_time) (
PARTITION p202301 VALUES LESS THAN ('2023-02-01'),
PARTITION p202302 VALUES LESS THAN ('2023-03-01'),
PARTITION p202303 VALUES LESS THAN ('2023-04-01')
);3.3 读写分离
sql
-- 读写分离,减少读写锁冲突
-- 主库:处理写操作
-- 从库:处理读操作
-- 读操作路由到从库
SELECT * FROM users WHERE id = 123;
-- 写操作路由到主库
UPDATE users SET name = 'new_name' WHERE id = 123;4. 系统配置优化
功能:通过系统配置优化锁行为 适用场景:
- 锁等待超时设置不合理
- 死锁检测间隔过长
- 并发参数配置不当
核心参数:
| 参数名 | 功能 | 建议值 |
|---|---|---|
lock_wait_timeout | 锁等待超时时间 | 30000000(30秒) |
deadlock_detection_interval | 死锁检测间隔 | 100000(100毫秒) |
max_trx_idle_time | 事务最大空闲时间 | 600000000(10分钟) |
txn_batch_report_interval | 事务批量报告间隔 | 1000000(1秒) |
配置示例:
sql
-- 设置锁等待超时时间为30秒
ALTER SYSTEM SET lock_wait_timeout = 30000000 GLOBAL;
-- 设置死锁检测间隔为100毫秒
ALTER SYSTEM SET deadlock_detection_interval = 100000 GLOBAL;
-- 设置事务最大空闲时间为10分钟
ALTER SYSTEM SET max_trx_idle_time = 600000000 GLOBAL;锁指标告警配置
1. 告警指标选择
功能:选择合适的锁指标进行告警 适用场景:
- 及时发现锁问题
- 防止锁问题扩散
- 主动运维
核心告警指标:
| 指标名 | 告警阈值 | 告警级别 |
|---|---|---|
lock_wait_time_total | > 5000000微秒/秒 | 警告 |
lock_wait_count | > 50次/秒 | 警告 |
deadlock_count | > 0次/分钟 | 错误 |
avg_lock_wait_time | > 50000微秒 | 警告 |
lock_contention_ratio | > 20% | 错误 |
2. 告警配置示例
功能:配置锁指标告警 适用场景:
- Prometheus Alertmanager配置
- Zabbix告警配置
- 其他监控系统
2.1 Prometheus Alertmanager配置
yaml
# 锁等待告警规则
groups:
- name: oceanbase-lock-alerts
rules:
- alert: HighLockWaitTime
expr: sum(rate(lock_wait_time_total[5m])) by (cluster, tenant) > 5000000
for: 2m
labels:
severity: warning
annotations:
summary: "High lock wait time in OceanBase cluster {{ $labels.cluster }}"
description: "Tenant {{ $labels.tenant }} has {{ $value }} microseconds of lock wait time in the last 5 minutes"
- alert: DeadlockDetected
expr: sum(rate(deadlock_count[5m])) by (cluster, tenant) > 0
for: 1m
labels:
severity: error
annotations:
summary: "Deadlock detected in OceanBase cluster {{ $labels.cluster }}"
description: "Tenant {{ $labels.tenant }} has {{ $value }} deadlocks in the last 5 minutes"最佳实践
1. 建立锁监控体系
- 全面监控:监控所有关键锁指标
- 实时告警:设置合理的告警阈值
- 可视化展示:使用Grafana等工具进行可视化
- 历史分析:保留历史锁指标数据,用于趋势分析
2. 定期锁分析
- 定期审计:定期分析锁指标,识别潜在问题
- 根因分析:深入分析锁问题的根本原因
- 优化改进:根据分析结果进行优化改进
- 效果验证:验证优化效果,持续改进
3. 事务设计规范
- 短事务原则:尽量缩短事务长度
- 合理隔离级别:根据业务需求选择合适的隔离级别
- 最小锁范围:只锁定必要的数据
- 避免长事务:避免在事务中执行耗时操作
4. 性能测试
- 并发测试:进行充分的并发测试
- 压力测试:在高压力下测试锁行为
- 边界测试:测试边界条件下的锁表现
- 回归测试:定期进行回归测试,确保锁问题不复发
常见问题(FAQ)
Q1: 如何快速定位锁等待的原因?
A1: 快速定位锁等待原因的方法:
- 使用GV$OB_LOCK_WAITING视图查看当前锁等待情况
- 关联GV$OB_LOCKS和GV$OB_TRANSACTIONS视图,查看持有锁的事务
- 分析持有锁事务的SQL语句和执行计划
- 检查事务的持有时间和状态
Q2: 如何处理频繁的死锁问题?
A2: 处理频繁死锁问题的方法:
- 分析死锁日志,找出死锁产生的原因
- 优化事务设计,避免循环等待
- 统一事务访问资源的顺序
- 减少事务持有锁的时间
- 考虑使用乐观锁替代悲观锁
Q3: 如何区分锁等待和死锁?
A3: 锁等待和死锁的区别:
- 锁等待是单向的,一个事务等待另一个事务的锁
- 死锁是双向的,两个或多个事务互相等待
- 锁等待最终会超时或获取到锁
- 死锁需要数据库自动检测和解决
- 锁等待影响单个或少量事务
- 死锁影响多个事务,可能导致系统性能下降
Q4: 如何优化热点锁问题?
A4: 优化热点锁问题的方法:
- 识别热点数据,分析访问模式
- 考虑数据分片,分散热点
- 使用缓存减少数据库访问
- 采用异步处理方式
- 考虑业务逻辑优化,减少对热点数据的并发访问
Q5: 锁指标监控对性能有影响吗?
A5: 锁指标监控对性能的影响:
- 合理的监控配置对性能影响很小
- 过于频繁的采样会增加系统开销
- 建议根据实际情况调整监控频率
- 生产环境建议使用15-60秒的采样间隔
- 可以根据业务需求调整监控粒度
Q6: 如何设置合理的锁等待超时时间?
A6: 设置合理的锁等待超时时间的方法:
- 考虑业务需求,确保正常事务能够完成
- 避免过长的超时时间导致事务堆积
- 避免过短的超时时间导致正常事务失败
- 参考系统的平均事务执行时间
- 建议设置为30-60秒
Q7: 如何预防锁问题?
A7: 预防锁问题的方法:
- 优化事务设计,减少锁持有时间
- 使用合适的索引,减少锁范围
- 选择合适的事务隔离级别
- 避免长事务和大事务
- 实现合理的并发控制机制
- 定期监控和分析锁指标
Q8: 如何评估锁优化的效果?
A8: 评估锁优化效果的方法:
- 对比优化前后的锁指标
- 观察系统吞吐量的变化
- 查看事务响应时间的改善
- 检查死锁和锁等待事件的减少情况
- 评估系统的并发处理能力提升
Q9: 如何处理长事务导致的锁问题?
A9: 处理长事务导致的锁问题的方法:
- 识别长事务,分析其必要性
- 拆分长事务为多个短事务
- 将非核心操作移出事务
- 设置合理的事务超时时间
- 考虑使用异步处理方式
Q10: 锁指标和其他性能指标有什么关系?
A10: 锁指标与其他性能指标的关系:
- 锁等待时间增加会导致事务响应时间延长
- 锁竞争激烈会降低系统吞吐量
- 死锁会导致系统性能突然下降
- 长事务持有锁会影响其他事务的执行
- 锁指标是评估数据库并发性能的重要指标
