本文目录导读:

在不同的数据库系统中,查看当前事务的锁信息方法不同,以下是主流数据库(MySQL/PostgreSQL/Oracle/SQL Server)的具体查询方式:
MySQL (InnoDB)
MySQL 提供了 SHOW ENGINE INNODB STATUS 和系统表 performance_schema 来查看锁信息。
查看 InnoDB 引擎状态(最常用,但信息较原始)
SHOW ENGINE INNODB STATUS\G
- 注意较长,需查看
LATEST DETECTED DEADLOCK和TRANSACTIONS部分,此方法主要显示最近发生死锁或当前大量锁等待的信息,不直接显示所有锁。
从 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$LOCK、V$SESSION 和 V$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 查询等待 |
通用排查锁问题的思路:
- 先找谁在等待锁(
granted = false或request_status = 'WAIT')。 - 再找谁持有锁阻塞了别人(通常是阻塞链顶端的那个会话/事务)。
- 最后确认持锁事务是否在运行中(查询当前活跃的SQL),可以杀死阻塞进程(
KILL命令,需谨慎)或者等待其自动完成。