如何查看当前事务的锁信息?

wen IT资讯 240

本文目录导读:

如何查看当前事务的锁信息?

  1. MySQL (InnoDB)
  2. PostgreSQL
  3. Oracle
  4. SQL Server
  5. 总结建议

在不同的数据库系统中,查看当前事务的锁信息方法不同,以下是主流数据库(MySQL/PostgreSQL/Oracle/SQL Server)的具体查询方式:

MySQL (InnoDB)

MySQL 提供了 SHOW ENGINE INNODB STATUS 和系统表 performance_schema 来查看锁信息。

查看 InnoDB 引擎状态(最常用,但信息较原始)

SHOW ENGINE INNODB STATUS\G
  • 注意较长,需查看 LATEST DETECTED DEADLOCKTRANSACTIONS 部分,此方法主要显示最近发生死锁或当前大量锁等待的信息,不直接显示所有锁。

performance_schema 查询(MySQL 5.6+,推荐) 首先确保启用了 performance_schema(默认在 MySQL 5.7+ 中开启)。

-- 查看当前正在等待锁的事务(谁在等)
SELECT * FROM performance_schema.data_lock_waits\G
-- 查看当前所有持有和等待的锁(更详细)
SELECT * FROM performance_schema.data_locks\G
  • data_locks 显示每个事务持有的锁对象。
  • data_lock_waits 显示阻塞关系:哪个事务在等待哪个事务持有的锁。

查询 INFORMATION_SCHEMA(旧版方法)

-- 查看当前正在运行的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G
-- 查看 InnoDB 的锁(部分信息)
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
-- 将三个表关联,查看具体锁等待关系
SELECT 
  waiting_trx_id, 
  waiting_thread, 
  blocking_trx_id, 
  blocking_thread
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

PostgreSQL

PostgreSQL 主要通过系统视图 pg_locks 查看。

查看当前所有锁信息:

SELECT 
  locktype,        -- 锁类型(relation, tuple, transactionid 等)
  database, 
  relation::regclass, -- 被锁的表名
  page, 
  tuple, 
  virtualxid, 
  transactionid, 
  pid,             -- 持有锁的进程ID
  mode,            -- 锁模式(AccessShareLock, RowExclusiveLock 等)
  granted,         -- 是否已获得锁(true=持有, false=等待)
  fastpath
FROM pg_locks
WHERE database = (SELECT oid FROM pg_database WHERE datname = current_database());

查看当前锁等待的详细信息(谁阻塞了谁):

SELECT
  blocked_locks.pid AS blocked_pid,
  blocked_activity.usename AS blocked_user,
  blocked_activity.query AS blocked_query,
  blocking_locks.pid AS blocking_pid,
  blocking_activity.usename AS blocking_user,
  blocking_activity.query AS blocking_query
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_locks.pid = blocked_activity.pid
JOIN pg_catalog.pg_locks blocking_locks 
  ON blocking_locks.locktype = blocked_locks.locktype
  AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
  AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
  AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
  AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
  AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
  AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
  AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
  AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
  AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
  AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_locks.pid = blocking_activity.pid
WHERE NOT blocked_locks.granted;

Oracle

Oracle 的锁信息主要来自 V$LOCKV$SESSIONV$SESSION_BLOCKERS

查看当前数据库中的所有锁:

SELECT 
  sid, 
  type,        -- 锁类型(TM=表锁, TX=事务锁, UL=用户自定义)
  id1,         -- 标识符(取决于类型,TM 是对象ID)
  id2, 
  lmode,       -- 锁模式(数字:2=行共享, 3=行排他, 4=共享, 6=排他)
  request,     -- 请求的锁模式(gt;0,表示正在等待)
  block       -- 是否阻塞其他会话(1=是)
FROM v$lock;

查看锁等待及阻塞关系(更实用):

SELECT 
  blocking_session,   -- 阻塞者
  sid,               -- 等待者
  serial#,
  username,
  program,
  machine,
  wait_class,
  seconds_in_wait,
  state
FROM v$session
WHERE blocking_session IS NOT NULL;

SQL Server

SQL Server 通过动态管理视图(DMV)查看。

查看当前所有锁:

-- 需要 VIEW SERVER STATE 权限
SELECT 
  request_session_id,    -- 会话ID
  resource_type,         -- 资源类型(DATABASE, OBJECT, PAGE, KEY, RID 等)
  resource_database_id, 
  resource_associated_entity_id,
  request_mode,          -- 锁模式(S=共享, X=排他, IX=意向排他 等)
  request_status         -- 状态(GRANT=持有, WAIT=等待, CNVRT=转换)
FROM sys.dm_tran_locks
ORDER BY request_session_id;

查看当前阻塞链(更直观):

SELECT 
  session_id, 
  blocking_session_id, 
  wait_type, 
  wait_time, 
  wait_resource, 
  command, 
  text AS query_text
FROM sys.dm_exec_requests
CROSS APPLY sys.dm_exec_sql_text(sql_handle)
WHERE blocking_session_id > 0;

总结建议

数据库 最推荐/最实用的命令
MySQL SELECT * FROM performance_schema.data_lock_waits;
PostgreSQL SELECT * FROM pg_locks WHERE NOT granted; 并关联 pg_stat_activity 查询具体阻塞
Oracle SELECT blocking_session, sid FROM v$session WHERE blocking_session IS NOT NULL;
SQL Server sys.dm_tran_locks 结合 sys.dm_exec_requests 查询等待

通用排查锁问题的思路

  1. 先找谁在等待锁granted = falserequest_status = 'WAIT')。
  2. 再找谁持有锁阻塞了别人(通常是阻塞链顶端的那个会话/事务)。
  3. 最后确认持锁事务是否在运行中(查询当前活跃的SQL),可以杀死阻塞进程KILL 命令,需谨慎)或者等待其自动完成。

抱歉,评论功能暂时关闭!