共计 1848 个字符,预计需要花费 5 分钟才能阅读完成。
这篇文章主要讲解了“mysql autocommit= 0 引起的业务 hang 住问题分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“mysql autocommit= 0 引起的业务 hang 住问题分析”吧!
背景
有用户报告一个普通的 select 语句被 hang 住了,执行超时。查明之后发现是 autocommit 使用不当导致。这里将 case 简化,说明复现步骤及原因。
复现
session1 建表并插入数据:create table if not exists t(id int primary key, c int);
set autocommit=0;
insert into t values(1,1);
insert into t values(2,2);
insert into t values(3,3);
commit;
select count(*) from t;
这个执行流程的目的很直观,建表、插入数据、查询结果。貌似没有问题。维持 session1 不断,新建一个连接 session2,执行 create table if not exists t(id int primary key, c int);
此时该语句处于等待状态.
再新建一个连接 session3, 执行 select count(*) from t; 该语句处于等待状态.
于是从业务上看就是一个 select 语句被 hang 住。
原因分析
MySQL Tips: 如果服务中某些语句无法执行完成,追查问题时第一步要先保留现场,pstack pid of mysqld tmplog 之一个常用的方法。
这两个等待线程的栈如:#0 0x000000310ce0b7bb in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x000000000063ba46 in MDL_wait::timed_wait(THD*, timespec*, bool, char const*) ()
#2 0x000000000063e095 in MDL_context::acquire_lock(MDL_request*, unsigned long) ()
可以看到,堵在 MDL_wait.
简单说明下什么是 MDL。试想,如果一个语句在执行一个表上的查询过程中,表结构被改了,或者表被 drop,这样会得到一个错误的结果。因此在一个事务持续期间,就需要对访问的表结构作保护。这个就是 meta data lock (MDL).
很容易理解的,对表数据作增删改查,需要对 MDL 加读锁,修改表结构、删除表等操作则加写锁。
MySQL Tips: MDL 是 5.5 才加入的机制,5.1 版本下本文的 case 不会复现。 MySQL Tips: 事务中 MDL 申请时机是在首次使用时,释放时机是在事务结束后。
也就是说文章开头的这个 case,原因是 session2 等待在加写锁过程。而 session3 虽然只是加读锁,但与 session2 冲突,也需要等待。
session1 的事务
也就是说 session1 还持有表 t 的 MDL 读锁。但我们的事务明明已经提交 (commit) 了。这里就涉及到一个常见的误解。以前有看过文章说,可以用 set autocommit= 0 开启一个事务。其实这个描述不准确.
MySQL Tips: set autocommit= 0 是将本线程设置为非自动提交模式。在每个事务结束后,下个语句开始时自动新建一个事务。
这就意味着,session1 最后的那个 select count(*)操作,实际上之前隐含了一个 begin 操作。由于该事务没有提交,因此 session1 持有表 t 的 MDL 读锁。因此对于业务方的建议就是,及时提交这些读事务,或断开连接。
MySQL Tips: 连接断开时,MySQL 会自动回滚当前未提交的事务。 由于本 case 里面 session1 的最后一个事务只是一个 select 语句,因此回滚不影响业务。
感谢各位的阅读,以上就是“mysql autocommit= 0 引起的业务 hang 住问题分析”的内容了,经过本文的学习后,相信大家对 mysql autocommit= 0 引起的业务 hang 住问题分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!
正文完