MySQL中​Performance Schema和锁

2024年 1月 30日 49.7k 0

杨老师写的这篇文章《MySQL 8.0:Performance Schema中锁相关的表》介绍了和锁相关的表,可以学习了解。

关于锁的历史文章如下,

《一招解决MySQL中DDL语句被阻塞的问题场景》

《MySQL中锁的介绍》

《如何定位锁定用户的元凶?》

《MySQL快速定位全局锁的途径》

《MySQL锁等待超时的解决路径》

《MySQL的MDL锁解惑》

《InnoDB快速定位行锁争用会话的过程和操作》

《小白学习MySQL - 查询会锁表?》

《enq: TM - contention锁争用的解决》

MySQL 8.0 中,Performance Schema已经成为监控和分析数据库锁状态的首选方法。 在本文中,我们将探讨Performance Schema中和锁相关的表,并通过实例介绍如何使用这些表来发现当前会话的锁、识别哪些锁被阻塞、以及确定谁持有锁。

Performance Schema中的锁相关的表

Performance Schema提供了多个与锁相关的表,主要包括,

data_locks:   当前的锁信息,包括锁的类型、模式和持有者。
data_lock_waits: 锁等待信息,展示请求锁的事务和阻塞该请求的事务之间的关系。

data_locks表

data_locks
表提供了关于当前被数据库持有的锁的信息。这些信息包括锁的类型、模式以及所属对象等。关键列,

ENGINE: 存储引擎,对于InnoDB,值是INNODB。
ENGINE_LOCK_ID: 锁的唯一标识符。
ENGINE_TRANSACTION_ID: 事务的唯一标识符。
THREAD_ID: 执行事务的线程ID。
OBJECT_SCHEMA: 锁定对象的数据库名。
OBJECT_NAME: 锁定对象的名字。
LOCK_TYPE: 锁的类型,例如表锁或行锁。
LOCK_MODE: 锁的模式,如S(共享)或X(独:)。该值依存储引擎而定。对于InnoDB,允许的值包括 S[,GAP]、X[,GAP]、IS[,GAP]、IX[,GAP]、AUTO_INC 和 UNKNOWN。
除了 AUTO_INC 和 UNKNOWN 之外的锁模式,如果存在,则表示间隙锁。关于 S、X、IS、IX 和间隙锁的信息,请参考InnoDB锁定。

LOCK_STATUS :锁的请求状态。GRANTED持有锁 / WAITING 等待锁
LOCK_DATA: 与锁关联的数据(如果有)。锁相关的数据(如果有的话)。该值依存储引擎而定。对于InnoDB来说,
如果LOCK_TYPE 是 RECORD,则会显示一个值,否则该值为 NULL。
如果锁定在主键索引上,则会显示被锁记录的主键值。如果锁定在辅助索引上,
则会显示被锁记录的辅助索引值,并附加上主键值。如果没有主键,
LOCK_DATA 会显示选择的唯一索引的键值,或者根据InnoDB聚簇索引使用规则(参见聚簇和辅助索引),
显示InnoDB内部的唯一行ID号码。对于在supremum伪记录上获取的锁,
LOCK_DATA 会报告 "supremum伪记录"。如果包含被锁记录的页面因为在锁定期间被写到磁盘而不在缓冲池中,
InnoDB不会从磁盘获取该页面。相反,LOCK_DATA 将报告 NULL。

结合一下案例,可以认识data_locks相关的字段,

mysql >  select OBJECT_SCHEMA,OBJECT_NAME,INDEX_NAME, LOCK_MODE, LOCK_DATA from data_locks ;
+---------------+-------------+------------+-----------+------------------------+
| OBJECT_SCHEMA | OBJECT_NAME | INDEX_NAME | LOCK_MODE | LOCK_DATA              |
+---------------+-------------+------------+-----------+------------------------+
| test          | t           | NULL       | IX        | NULL                   |
| test          | t           | PRIMARY    | X         | supremum pseudo-record |
| test          | t           | PRIMARY    | X         | 1                      |
| test          | t           | PRIMARY    | X         | 4                      |
| test          | t           | PRIMARY    | X         | 5                      |
| test          | t           | PRIMARY    | X         | 6                      |
+---------------+-------------+------------+-----------+------------------------+
6 rows in set (0.00 sec)
mysql [localhost:8030] {msandbox} (performance_schema) > select * from test.t;
+----+------+
| id | a    |
+----+------+
|  1 |    3 |
|  4 |    4 |
|  5 |    6 |
|  6 |    6 |
+----+------+
4 rows in set (0.00 sec)

上述查询中OBJECT_NAME= PRIMARY时,LOCK_DATA为主键的记录, 如果访问了非索引字段?select * from t where a=4 for update;

从MySQL 8.0.1开始INFORMATION_SCHEMA.INNODB_LOCKS被P_S的data_locks表取代。

注意两者的差异,

1. 如果一个事务持有一个锁,只有当另一个事务正在等待这个锁时,INNODB_LOCKS才会显示这个锁。无论是否有事务在等待这个锁,data_locks始终会显示这个锁。

2. INNODB_LOCKS表需要全局的PROCESS权限。data_locks表则需要Performance Schema权限的只读权限,例如要查询的表需要SELECT权限。data_lock_waits表

data_lock_waits表显示了锁等待情况,包含了发出锁请求的事务和阻塞该请求的事务的信息。关键列,

REQUESTING_ENGINE_LOCK_ID: 请求锁的引擎锁标识符。
REQUESTING_ENGINE_TRANSACTION_ID: 发出锁请求的事务ID。
REQUESTING_THREAD_ID: 请求锁的线程ID。
BLOCKING_ENGINE_LOCK_ID: 阻塞请求的引擎锁标识符,持有锁的锁标示符
BLOCKING_ENGINE_TRANSACTION_ID: 阻塞请求的事务ID。
BLOCKING_THREAD_ID: 持有锁的线程ID。

data_lock_waits表和innodb_lock_waits表之间的差异,其实和上面写的差异差不多。权限和字段部分有差异。实际应用示例

以下是一些实用的SQL查询示例,帮助利用Performance Schema监控和分析MySQL中的锁。

查找当前正在等待锁的事务

SELECT 
    r.THREAD_ID AS waiting_thread_id,
    r.OBJECT_SCHEMA AS waiting_object_schema,
    r.OBJECT_NAME AS waiting_object_name,
    b.THREAD_ID AS blocking_thread_id,
    b.OBJECT_SCHEMA AS blocking_object_schema,
    b.OBJECT_NAME AS blocking_object_name
FROM 
    performance_schema.data_lock_waits w
INNER JOIN 
    performance_schema.data_locks b ON 
    b.ENGINE_LOCK_ID = w.BLOCKING_ENGINE_LOCK_ID
INNER JOIN 
    performance_schema.data_locks r ON 
    r.ENGINE_LOCK_ID = w.REQUESTING_ENGINE_LOCK_ID;

例如两个会话,

session1 begin; select * from  t where id=1 for update ; 

session2 update  t set a=4 where id=1;

查找特定会话的锁,

SELECT *
FROM performance_schema.data_locks
WHERE THREAD_ID = YOUR_THREAD_ID;  -- 替换为实际的线程ID

识别哪些锁被阻塞,

SELECT *
FROM performance_schema.data_lock_waits;

查看谁持有锁,

SELECT *
FROM performance_schema.data_locks
WHERE LOCK_STATUS = 'GRANTED';

通过Performance Schema中的锁表,我们可以获得数据库锁的实时视图,并对锁争用事件做出快速响应,以维护数据库的稳定性和性能。

官方文档,

https://dev.mysql.com/doc/mysql-perfschema-excerpt/8.0/en/performance-schema-data-locks-table.html

https://dev.mysql.com/doc/mysql-perfschema-excerpt/8.0/en/performance-schema-data-lock-waits-table.html

Oracle、MySQL、SQL Server这种成熟的商业数据库,官方文档还是值得深入了解和学习的资源。

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

近期更新的文章:《Oracle备份与恢复常见但难解决的15个问题》
《MySQL常用监控指标学习了解》
《一招解决MySQL中DDL语句被阻塞的问题场景》
《MySQL的列非空和自增属性》
《如何将印象笔记文件转换成无需授权的md文件?》
近期的热文:《推荐一篇Oracle RAC Cache Fusion的经典论文》
《"红警"游戏开源代码带给我们的震撼》
文章分类和索引:《公众号1300篇文章分类和索引》

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论