开发者社区> 阿里云柳璃> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

误用autocommit引起的业务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语句,因此回滚不影响业务。

小结

1) 显式的启动事务的方法是begin或start transaction; 提交事务的方法是commit;

2) set autocommit=0的好处是在频繁开启事务的场景下,减少一次begin的交互。

3) 注意set autocommit=0修改了线程变量,会影响本线程存活期间的事务行为。

4) set autocommit=1可以提交事务并改变值,可以与set autocommit=0成对出现。

阿里云RDS feature

当出现如上的错误用法时,修改业务代码需要一段时间。

针对这种case,阿里云RDS版本提供了trx_idle_timeout参数,设置空闲事务停留时间。当超过设置的值(单位为秒)后,连接自动断开。

比如设置为10,在示例的case里面,sessino1在空闲10s后断开连接,session2继续执行,之后session3继续执行。

该值默认为0。

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何避免长事务对业务的影响?
大家好前面我们大概了解了关于事务的隔离级别,实现方式,启动方式的细节,长事务与短事务的区别。今天我们延伸介绍一下,如果因为失误用了长事务,那我们在工作中如何发现问题,排查问题?
0 0
BUG记录-多线程对事务的影响有多么大?
BUG记录-多线程对事务的影响有多么大?
0 0
一个诡异的SQL事务现象
今天测试过程中,同事提出了一个,看似诡异,实则很基础的问题,乍一看会被迷惑。 用实验来复现下这个问题, (1) 创建测试表,A表的id字段是主键,B表的id_a字段是外键,参考A表的id主键, (2) 应用有这么一个逻辑,一个事务中,先更新表A,再INSERT表B,其中表B的id_a字段值是来自于表A刚才操作的主键,模拟如下, 可以看出,更新表A的操作正常,但使用表A的主键值id=1,来INSERT表B的时候,报了FK_B_A外键完整性约束的错误。
856 0
密码延迟验证导致的系统HANG住
又是一个11g新特性导致的问题。 [@more@] 这个新特性很早之前就研究过,也在其他客户处碰到过类似的问题。从11g开始,如果一个用户使用不正确的密码尝试登录数据库,那么随着登录失败次数的增加,每次登录验证前延迟等待...
759 0
11gR2修改用户后导致系统HANG住
【背景】今天中午的时候用户反馈需要修改数据库的和应用的连接密码,修改密码这种小事情,本以为不会不会出现问题的。没想到午休到一半的时候就接到用户的电话,系统连接不进去了。
805 0
[20140117]疑似checkpoint堵塞数据库连接
注:这个说法是不成立的,问题已经解决,但是无法正确的定位到具体什么原因:[20140702]奇怪的应用程序超时 背景:       开发通过应用程序的日志发现间歇性的出现,数据库连接超时 原因:      只能大概猜测,没有碰到过这个问题,google,baidu也没有找出过问题。
445 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载