普通网友 2026-02-28 14:30 采纳率: 98.9%
浏览 1
已采纳

金仓数据库如何查看当前被锁的表和阻塞会话?

在金仓数据库(KingbaseES)中,生产环境中常因事务未提交、长事务或异常中断导致表级/行级锁堆积,进而引发会话阻塞。典型现象是某SQL执行缓慢或长时间无响应,而其他会话对同一表的DML操作被挂起。如何快速定位“谁锁了什么表”以及“哪个会话正在被阻塞”?这是DBA日常巡检与故障排查的关键需求。需明确:KingbaseES基于PostgreSQL内核但有定制视图,不能直接套用pg_locks/pg_stat_activity的原始写法;其系统视图如`sys_locks`、`sys_stat_activity`和`sys_locks_detail`才是权威数据源。常见误区包括混淆锁模式(AccessExclusive vs RowExclusive)、忽略事务持续时间、未关联`pid`与`backend_pid`导致无法kill源头会话。此外,V8R6及以上版本支持`sys_blocking_pids()`函数辅助分析阻塞链。掌握这些机制,才能高效诊断锁冲突并实施精准干预。
  • 写回答

1条回答 默认 最新

  • 桃子胖 2026-02-28 14:31
    关注
    ```html

    一、基础认知:KingbaseES锁机制与核心系统视图定位

    KingbaseES(V8R3+)深度定制了PostgreSQL内核,其锁管理不暴露pg_locks等原生视图,而是提供三类权威系统视图:sys_locks(当前锁持有/等待状态)、sys_stat_activity(活跃会话快照)、sys_locks_detail(含对象OID、锁模式、事务ID等细粒度信息)。特别注意:sys_locks中的pid字段对应后台进程ID,而sys_stat_activity中为backend_pid——二者必须严格关联,否则无法精准定位阻塞源头。

    二、现象识别:典型阻塞场景的SQL响应特征

    • 某UPDATE语句执行超时(>30s),EXPLAIN显示无全表扫描但实际卡住
    • 并发INSERT同一张订单表时持续WAITING,state = 'active'wait_event_type = 'Lock'
    • 应用日志出现“could not obtain lock on relation”或“deadlock detected”错误
    • 监控平台告警:blocked_session_count > 3且持续上升

    三、诊断路径:四步法快速定位阻塞链

    1. 查阻塞会话:使用sys_blocking_pids(backend_pid)(V8R6+)识别直接阻塞者
    2. 析锁关系:JOIN sys_lockssys_stat_activity,过滤granted = false(等待锁)和granted = true(持有锁)记录
    3. 定对象层级:通过objid关联sys_class获取表名,区分relation(表级锁)与tuple(行级锁)
    4. 溯事务根源:检查backend_startxact_startstate_change时间差,识别长事务(>5分钟)或idle in transaction

    四、核心SQL诊断脚本(生产环境可直接运行)

    SELECT 
      w.pid AS waiting_pid,
      w.usename AS waiting_user,
      w.application_name AS waiting_app,
      w.state AS waiting_state,
      w.query AS waiting_query,
      l.mode AS waiting_mode,
      t.relname AS locked_table,
      b.pid AS blocking_pid,
      b.usename AS blocking_user,
      b.application_name AS blocking_app,
      b.state AS blocking_state,
      b.query AS blocking_query,
      EXTRACT(EPOCH FROM (NOW() - b.xact_start))::INT AS blocking_xact_seconds,
      CASE 
        WHEN l.mode = 'AccessExclusiveLock' THEN 'DDL/_TRUNCATE/VACUUM'
        WHEN l.mode = 'RowExclusiveLock' THEN 'INSERT/UPDATE/DELETE'
        ELSE l.mode 
      END AS lock_impact_level
    FROM sys_stat_activity w
    JOIN sys_locks l ON w.pid = l.pid AND NOT l.granted
    JOIN sys_locks bl ON l.database = bl.database 
      AND l.relation = bl.relation 
      AND bl.granted
    JOIN sys_stat_activity b ON bl.pid = b.pid
    LEFT JOIN sys_class t ON l.relation = t.oid
    WHERE w.state = 'active' AND w.wait_event_type = 'Lock'
    ORDER BY blocking_xact_seconds DESC;

    五、锁模式语义对照表(避免常见误判)

    锁模式触发操作阻塞能力典型风险场景
    AccessExclusiveLockDROP TABLE, VACUUM FULL, ALTER TABLE阻塞所有DML及SELECT FOR UPDATE未提交的DDL长时间挂起
    RowExclusiveLockINSERT, UPDATE, DELETE仅阻塞冲突行/表级排他操作未提交事务锁住热点行
    ShareUpdateExclusiveLockVACUUM, CREATE INDEX CONCURRENTLY阻塞后续VACUUM及DDL大表索引创建被长事务阻塞

    六、阻塞链可视化分析(Mermaid流程图)

    graph LR A[Session-1024
    UPDATE orders SET status='shipped'
    xact_start=2024-05-20 09:15:00] -->|holds RowExclusiveLock on orders| B[Session-1087
    INSERT INTO orders ...
    wait_event_type=Lock] B -->|waits for same row| C[Session-1024] D[Session-1152
    VACUUM orders
    xact_start=2024-05-20 09:10:00] -->|requires ShareUpdateExclusiveLock| A style A fill:#ffcccc,stroke:#f66 style B fill:#ccffcc,stroke:#6c6 style D fill:#ccccff,stroke:#66f

    七、精准干预策略与安全Kill规范

    禁止直接KILL -9操作系统进程!应使用KingbaseES标准终止方式:

    • 温和终止SELECT pg_cancel_backend(1024); —— 中断当前查询,保留事务上下文
    • 强制终止SELECT pg_terminate_backend(1024); —— 回滚整个事务并释放所有锁
    • 批量清理:对state = 'idle in transaction'xact_start < NOW() - INTERVAL '10 minutes'的会话执行自动终止

    八、长效防控机制建设

    在运维体系中嵌入三层防护:

    1. 应用层:强制设置JDBC连接参数defaultTransactionIsolation=TRANSACTION_READ_COMMITTED,禁用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    2. 数据库层:配置idle_in_transaction_session_timeout = 300000(5分钟),自动终结滞留事务
    3. 监控层:基于Prometheus + Grafana构建锁等待热力图,阈值告警联动企业微信机器人推送

    九、版本差异关键提示(V8R3 vs V8R6+)

    能力项V8R3–V8R5V8R6+
    阻塞会话识别需多表JOIN模拟blocking_pids原生支持sys_blocking_pids(pid)函数
    锁详情视图sys_locks缺少transactionid字段sys_locks_detail新增xid, virtualxid, classid等审计字段

    十、实战避坑指南(高频误区总结)

    • ❌ 错误认为sys_locks.pid = sys_stat_activity.pid → 实际应匹配backend_pid
    • ❌ 将RowExclusiveLock误判为严重阻塞 → 需结合objidpage/tuple进一步判断是否热点行竞争
    • ❌ 忽略database = 0的锁(全局锁)→ 可能由CREATE DATABASEREINDEX引发
    • ❌ 在只读备库执行pg_terminate_backend → KingbaseES备库不接受该命令,需切至主库操作
    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 3月1日
  • 创建了问题 2月28日