MySQL定位长事务(Identify Long Transactions)的实现

 更新时间:2024年09月03日 09:05:57   作者:V1ncent Chen  
在MySQL的运行中,经常会遇到一些长事务,本文主要介绍了MySQL定位长事务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在MySQL的运行中,经常会遇到一些长事务。长事务意味着长时间持有系统资源,这在OLAP系统中很常见,但在OLTP系统中,长事务意味着争用、并发降低,等待。长事务伴随的典型现象就是经常听到开发人员说"xxx表被锁住了…"

一、长事务的成因

长事务表面上来看都是运行时间过长。但其背地里的成因却可能不同,我认为长事务的成因可以分为以下3类:

  • 表、索引设计不合理,存在慢SQL
  • 事务设计不合理,耦合度过高
  • 事务未正常结束,例如忘记事务提交或事务执行出错后没有后续处理。

第一类:表、索引设计不合理,这种就是常见的慢SQL导致事务执行时间过长,有些慢SQL在数据量低的时候可能无法发现,当生产数据逐渐增多,慢SQL的问题会越来越严重,最终导致长事务。这类长事务的解决方式是优化SQL(可以通过慢查询日志抓取慢SQL)。

第二类:事务设计不合理是将大量的逻辑处理塞到一个事务中,导致事务过于臃肿。这种问题需要从业务层面分析,看是否可以将过大事务拆分成多个独立事务,降低耦合,对于OLTP系统,大部分都应该是短小的事务。

第三类:事务未正常结束,这种可能是忘记提交,或者事务处理中出错,但用户没有后续处理。当事务某条语句出错时,其仍然处于活跃状态,已成功执行语句的锁会继续持有。某些人可能会直接杀死客户端连接,但对数据库来说,并没有收到显式结束事务的命令,它保持事务是活跃状态,一直等待用户的命令,直到互动超时(interactive_timeout 默认28800秒,即会话8小时没活动,关闭会话)。

以上三类长事务中,第一二类属于性能优化问题,事务通常可以正常结束。危害最大的是第三类,这种被遗忘的事务会长时间占用系统资源(默认8小时),是不可接受的。在事务执行出现问题时,需要显式的rollback或commit来结束该事务,如果客户端已经杀死连接,无法控制事务,那么只能从服务端杀死该会话。

二、查找长事务

MySQL已提供了相关性能视图帮助我们查询活跃事务信息,通过performance_schema.events_transactions_current可以查询所有当前事务的event,配合其他视图即可定位长事务及其会话信息,主要用到的视图如下:

  • performance_schema.events_transactions_current 查询事务的线程ID,状态,持续时间等信息
  • performance_schema.threads 查询线程类型,用户,IP地址等信息(MySQL中一个线程对应一个用户会话)
  • sys.processlist 查询线程当前的状态,执行的SQL等信息

各个视图的关键字段,即要查询的关键信息解释如下:

performance_schema.events_transactions_current

  • thread_id, event_id 事务线程ID,事件ID,这是一个联合主键,唯一定位一行记录
  • state 事务的状态,有ACTIVE, COMMITTED 或ROLLED BACK三种状态,找长事务需要关注的是ACTIVE状态
  • timer_start, timer_end, timer_wait 事务起始,结束(未结束则是当前)及持续时长,单位是皮秒(10的负12次方),我们要关注的是timer_wait
  • isolation_level 事务的隔离级别

注:如果是MySQL8.0.16之后的版本,可以直接用format_pico_time()函数将timer_wait转换成易读的格式。

performance_schema.threads

  • thread_id 线程ID
  • type 线程类型,分为BACKGROUND(后台线程)和FOREGROUND(用户线程),我们要关注的是用户线程
  • processlist_id 用户会话ID,只有用户线程才有
  • processlist_user 会话用户名,只有用户线程才有
  • processlist_host 会话主机地址(IP),只有用户线程才有
  • processlist_db 会话当前操作的数据库

sys.processlist

  • thd_id 线程ID
  • conn_id 会话ID
  • user 用户信息,user@host格式
  • db 用户操作数据库
  • command 当前会话状态
  • time 线程处于当前状态的时长
  • current_statement 当前执行SQL

了解了上面3个视图提供的信息含义,我们可以很容易的找出当前哪些事务执行时间过长,及这些事务当前在做什么:

select
t.thread_id 线程ID,
t.processlist_id 会话ID,
t.processlist_user 用户,
t.processlist_host 用户地址,
t.processlist_db 数据库,
p.command 会话状态,
e.state 事务状态,
format_pico_time(e.timer_wait) 事务持续时长,
p.current_statement 执行SQL
from performance_schema.events_transactions_current e
join performance_schema.threads t on t.thread_id=e.thread_id
left join sys.processlist p on p.thd_id=t.thread_id
where t.type='FOREGROUND'
and e.state='ACTIVE'
order by e.timer_wait desc;

  • 这里提前开了2个会话,通过begin手动开启事务,一个会话执行select sleep(10000),另一个执行了一条普通的insert into语句。
  • 第一个会话模拟了大事务/慢SQL的状态,会话的状态是Query,且执行SQL有内容,表示事务在运行中
  • 第二个会话模拟了事务未正常结束的状态,会话的状态是Sleep,执行SQL为NULL,表示事务处于空闲状态,这类事务需要重点关注
  • 第三条记录是这个查询本身

定位到长事务后,分析长事务属于哪一类,决定是否需要优化事务或人工介入。例如上面第二个事务,如果判断会话异常,可以通过杀死会话ID来结束该会话(事务);

kill 451;

到此这篇关于MySQL定位长事务(Identify Long Transactions)的文章就介绍到这了,更多相关MySQL定位长事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mysql5.7并发插入死锁问题解决

    Mysql5.7并发插入死锁问题解决

    死锁是数据库并发控制中的一种现象,它涉及多个事务在执行过程中相互等待对方占有的资源,导致无法继续执行,本文就来介绍一下Mysql5.7并发插入死锁问题解决,感兴趣的可以了解一下
    2024-09-09
  • mysql之数据库常用脚本总结

    mysql之数据库常用脚本总结

    这篇文章主要介绍了mysql之数据库常用脚本总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • mysql中用于数据迁移存储过程分享

    mysql中用于数据迁移存储过程分享

    mysql 数据迁移用的一个存储过程,需要的朋友可以收藏下。
    2011-05-05
  • MySQL的子查询及相关优化学习教程

    MySQL的子查询及相关优化学习教程

    这篇文章主要介绍了MySQL的子查询及相关优化学习教程,使用子查询时需要注意其对数据库性能的影响,需要的朋友可以参考下
    2015-11-11
  • MySQL进行JSON复杂查询的完全指南

    MySQL进行JSON复杂查询的完全指南

    这篇文章主要为大家详细介绍了MySQL中进行JSON复杂查询的相关知识,包括从等值判断到深度搜索,文中的示例代码讲解详细,感兴趣的喜欢可以了解下
    2025-07-07
  • MySQL基础之多表查询案例分享

    MySQL基础之多表查询案例分享

    这篇文章主要为大家分享了几个MySQL基础中的多表查询案例,文中的示例代码简洁易懂,对我们学习MySQL有一定的帮助,需要的小伙伴可以了解一下
    2022-10-10
  • MySQL8中误删数据恢复的7种方法完整指南

    MySQL8中误删数据恢复的7种方法完整指南

    在数据库管理中,误删数据是开发者和运维人员最恐惧的噩梦之一,本文将通过 5个核心步骤、7种恢复方法 和 12个实战代码示例,深度解析MySQL 8中误删数据的恢复策略,大家可以根据需要进行选择
    2025-09-09
  • 如何设置才能远程登录Mysql数据库

    如何设置才能远程登录Mysql数据库

    本地机器安装的数据库,本地程序可以访问,但是同事的机器却无法连接访问,发现是mysql数据库没有开启远程访问。那么我们需要如何设置呢,这就是本文探讨的内容了
    2014-08-08
  • MySQL之终端Terminal(dos界面)管理数据库、数据表、数据的基本操作

    MySQL之终端Terminal(dos界面)管理数据库、数据表、数据的基本操作

    这篇文章主要介绍了MySQL之终端(Terminal)管理数据库、数据表、数据的基本操作,需要的朋友可以参考下
    2015-03-03
  • MySQL order by实现原理分析和Filesort优化方式

    MySQL order by实现原理分析和Filesort优化方式

    这篇文章主要介绍了MySQL order by实现原理分析和Filesort优化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12

最新评论