MySQL的Slow_log如何记录SQL的MDL锁耗时

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL的Slow_log如何记录SQL的MDL锁耗时

操作环境

数据库版本:mysql-5.6.24 source code

操作系统版本:CentOS Linux release 7.6.1810 (Core)

现象

MySQL的慢日志判断逻辑是根据utime_after_lock 加上long_query_time的值与end_utime_of_query时间做比较判断的,要分析MDL锁在MySQL的慢日志中的记录逻辑,先看如下2个测试场景:

场景1:MDL请求正常执行完

执行请求1:

image-20200906173440367.png

执行请求2:

image-20200906173505344.png

由于请求1持有MDL锁未释放,请求2被阻塞,处于Waiting for table metadata lock状态,此时的long_query_time为10S:

image-20200906173607474.png
回滚请求1,此时请求2执行完成,查看慢日志记录情况:

image-20200906173919485.png

image-20200906173931664.png

此时,慢日志并未记录请求2的alter操作。

场景2:MDL请求被KILL

重复"MDL请求正常执行完"章节的请求1和请求2,当请求2阻塞超过10S时,手动终止alter 操作,查看慢日志的记录情况:

image-20200906191156448.png

image-20200906191212800.png

此时,慢日志记录了alter操作。并且query time为7分52秒,lock_time为0。

推测

通过上面的测试,MDL请求耗时在特定情况会计入慢日志,通过之前文章的慢日志函数分析,最终判断SQL是否是慢日志的函数为THD::update_server_status(),这里面起到关键作用的是utime_after_lock 变量。也就是上面的2种行为对应了utime_after_lock 的2种变化,当"MDL请求正常执行完"时,utime_after_lock 在SQL的执行过程中重新(较SQL开始时的初始化的赋值)做了赋值,而当"MDL请求被KILL"时,utime_after_lock 没有进行新的赋值。导致在进入THD::update_server_status()函数时,出现两种不同的现象。

调试分析

为了验证上面的推测,在该函数设置断点,复现2个现象,查看运行到该函数时,utime_after_lock 的变化:

场景1:MDL请求执行完

请求2添加索引(alter table)开始执行时间:21:00:55

请求1回滚(rollback)时间:21:1:14

THD::update_server_status()函数utime_after_lock值:21:1:14

当MDL请求正常执行完时,虽然请求2被请求1的元数据锁阻塞了很久(21:1:14减去21:00:55),但是当请求1回滚后,请求2的alter操作执行到THD::update_server_status()函数时,其utime_after_lock为21:1:14,并不是请求2的开始执行时间。

场景2:MDL请求被KILL

请求2添加索引(alter table)开始执行时间:20:52:23

请求2终止时间:20:53:10

THD::update_server_status()函数utime_after_lock值:20:52:24

当MDL请求被kill时,虽然请求2被请求1的元数据锁阻塞了很久(20:53:10减去20:52:23),但是当请求2被kill后,请求2执行到THD::update_server_status()函数时,其utime_after_lock为20:52:24,并不是请求2的终止执行时间,而与请求2的开始执行时间相近。

通过这两个结果的对比,也进一步的证明了之前推测的结论,也就导致被kill的 query会出现在慢日志中。

找到关键函数

对源码进行检索,MySQL中有三个函数会对utime_after_lock 的值进行改变:

thd_storage_lock_wait():

void thd_storage_lock_wait(THD *thd, long long value)

{

thd->utime_after_lock+= value;

}

调试该函数,发现该函数是引擎层调用,由于MDL并未进入引擎层,这不是当前问题需要关注的函数。

THD::set_time():

inline void set_time()

{

start_utime= utime_after_lock= my_micro_time();

if (user_time.tv_sec || user_time.tv_usec)

{

start_time= user_time;

}

else

my_micro_time_to_timeval(start_utime, &start_time);

#ifdef HAVE_PSI_THREAD_INTERFACE

PSI_THREAD_CALL(set_thread_start_time)(start_time.tv_sec);

#endif

}

inline void set_time(const struct timeval *t)

{

start_time= user_time= *t;

start_utime= utime_after_lock= my_micro_time();

#ifdef HAVE_PSI_THREAD_INTERFACE

PSI_THREAD_CALL(set_thread_start_time)(start_time.tv_sec);

#endif

}

调试该函数,该函数主要用于线程以及请求开始、执行过程中的start_utime、utime_after_lock等变量的初始化或者设置。也不是当前问题需要关注的函数。

THD::set_time_after_lock():

void set_time_after_lock()

{

utime_after_lock= my_micro_time();

MYSQL_SET_STATEMENT_LOCK_TIME(m_statement_psi, (utime_after_lock - start_utime));

}

调试该函数,该函数会在mysql_lock_tables()函数进行调用,这属于MySQL server层的调用,是判断MDL的utime_after_lock赋值问题要关注的函数

对THD::set_time_after_lock设置断点

通过对THD::set_time_after_lock函数设置断点,复现场景1与场景2,结果如下:

场景1:MDL请求正常执行完

在该场景下,当请求1执行rollback后,请求2停留在断点处,堆栈如下:

image.png

可以看到,mysql_lock_tables()函数会调用 THD::set_time_after_lock,mysql_lock_tables()函数调用THD::set_time_after_lock的位置在函数的最后,如下:

image-20200907004022553.png

场景2:MDL请求被KILL

在该场景下,当请求2被kill query后,请求2直接终止并提示ERROR 1317 (70100): Query execution was interrupted,不会触发断点。

结论

通过测试验证,MDL在特殊情况下计入慢日志的主要原因是没有运行到mysql_lock_tables()函数的 thd->set_time_after_lock()操作,导致utime_after_lock变量没有被正确赋值。以至于在做慢日志判断时,使用的依然是较早的(SQL开始初始化时)的utime_after_lock,导致THD::update_server_status()判断时认为是慢日志。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2天前
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
8天前
|
SQL 存储 关系型数据库
Mysql并发控制和日志
通过深入理解和应用 MySQL 的并发控制和日志管理技术,您可以显著提升数据库系统的效率和稳定性。
39 10
|
3天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
20 3
|
2天前
|
SQL 存储 缓存
日志服务 SQL 引擎全新升级
SQL 作为 SLS 基础功能,每天承载了用户大量日志数据的分析请求,既有小数据量的快速查询(如告警、即席查询等);也有上万亿数据规模的报表级分析。SLS 作为 Serverless 服务,除了要满足不同用户的各类需求,还要兼顾性能、隔离性、稳定性等要求。过去一年多的时间,SLS SQL 团队做了大量的工作,对 SQL 引擎进行了全新升级,SQL 的执行性能、隔离性等方面都有了大幅的提升。
|
20天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
19天前
|
SQL 关系型数据库 MySQL
MySQL 高级(进阶) SQL 语句
MySQL 提供了丰富的高级 SQL 语句功能,能够处理复杂的数据查询和管理需求。通过掌握窗口函数、子查询、联合查询、复杂连接操作和事务处理等高级技术,能够大幅提升数据库操作的效率和灵活性。在实际应用中,合理使用这些高级功能,可以更高效地管理和查询数据,满足多样化的业务需求。
56 3
|
21天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
345 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
14天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
333 3