CentOS 7环境下MariaDB执行子查询更新时出现ERROR 2013连接丢失问题求助
解决CentOS 7上MariaDB执行带IN子查询的UPDATE时丢连接的问题
碰到过类似的生产环境故障,结合MyISAM的特性(表级锁、对子查询的优化能力有限),给你几个针对性的排查和解决方向,按优先级来试:
1. 先调大关键的连接与数据包参数
这个ERROR 2013最常见的原因就是连接超时或者数据包大小不够。先查一下当前的配置:
- 执行这条SQL看超时参数:
如果SHOW VARIABLES LIKE '%timeout%';wait_timeout和interactive_timeout的值小于3600(比如默认的600秒),临时调大试试:SET GLOBAL wait_timeout = 3600; SET GLOBAL interactive_timeout = 3600; - 再查数据包大小:
如果这个值小于64M,临时调大:SHOW VARIABLES LIKE 'max_allowed_packet';
要永久生效的话,编辑SET GLOBAL max_allowed_packet = 67108864; -- 64M,根据你的数据量可以再调大/etc/my.cnf(或者/etc/my.cnf.d/server.cnf),在[mysqld]段加:
然后重启MariaDB:wait_timeout = 3600 interactive_timeout = 3600 max_allowed_packet = 64Msystemctl restart mariadb
2. 把IN子查询改成JOIN写法
MyISAM对子查询的优化真的不如InnoDB,尤其是IN子查询有时候会生成低效的执行计划,导致长时间锁表或者资源耗尽。把你的更新语句改成JOIN形式试试:
原语句:
UPDATE table1 SET sal=32 WHERE prikey IN (SELECT id FROM table2 WHERE ....);
改成JOIN:
UPDATE table1 t1 JOIN table2 t2 ON t1.prikey = t2.id SET t1.sal=32 WHERE t2.[你的过滤条件];
这种写法执行效率更高,MyISAM处理起来更稳定,我之前碰到过好几次换写法就解决问题的情况。
3. 检查系统层面的资源限制
CentOS 7的系统资源限制也可能搞崩MariaDB:
- 先看内存:
free -h,如果内存不足触发OOM Killer杀掉mysqld进程,就会丢连接。查系统日志/var/log/messages或者dmesg,搜Out of memory看看有没有相关记录。 - 再看文件描述符:MyISAM会打开很多表文件,文件描述符不够会出问题。查当前mysqld的限制:
如果值小于65535,就编辑cat /proc/$(pidof mysqld)/limits | grep "Max open files"/etc/security/limits.conf加:
重启MariaDB生效。mysql soft nofile 65535 mysql hard nofile 65535
4. 扒MariaDB的错误日志找细节
别忽略错误日志,里面肯定有更详细的报错信息。日志路径一般是/var/log/mariadb/mariadb.log,搜Lost connection或者error关键词,比如如果看到Got an error writing communication packets,那基本就是max_allowed_packet或者超时的问题;如果有锁表相关的日志,那就是MyISAM表级锁导致的超时。
5. 临时切换存储引擎测试(谨慎操作)
如果前面的方法都没用,可以考虑临时把表转成InnoDB测试(一定要先备份数据!生产环境选低峰期操作):
ALTER TABLE table1 ENGINE=InnoDB; ALTER TABLE table2 ENGINE=InnoDB;
如果转成InnoDB后问题消失,那说明就是MyISAM本身的局限性导致的,长期来看建议逐步迁移到InnoDB——毕竟MyISAM已经被官方逐步淘汰,InnoDB在并发、崩溃恢复、事务支持上都强太多。
内容的提问来源于stack exchange,提问作者sygram
相关产品推荐
相关产品推荐

