美文网首页方案
惊!mysql表新增表字段时造成死锁—造成数据库瘫痪!!!(Wa

惊!mysql表新增表字段时造成死锁—造成数据库瘫痪!!!(Wa

作者: 小胖学编程 | 来源:发表于2021-05-19 19:24 被阅读0次

    事件起因:生产环境的mysql从库突然访问巨慢,且mysql的连接线程数飙升。

    1. 问题原因

    问题复现流程:

    1. 由于是mysql主从同步(查询操作在从库执行),alter操作在主库执行完毕后,将同步到从库执行alter操作。
    2. 但是某个项目正在使用flink查询从库select * from a操作(但是加了事务注解)。【因为这个事务方法及其耗时,便一直持有着数据库连接】
    3. alter操作发现有数据库连接在执行,会被阻塞;
    4. 从库中所有a表的sql语句(包含无事务的select)都被阻塞,等待alter执行。导致后续的a表的主从同步和查询功能都被阻塞,使得mysql连接线程数飙升。
    5. 连接线程数飙升后,导致mysql的从库访问巨慢,造成从库瘫痪,影响业务。

    alter操作等待事务提交,其他操作等待alter执行完毕,最终造成死锁。

    问题解决方案:

    select * from a的事务移除。

    问题分析:

    因为,会阻塞DDL语句的执行。而mysql发现阻塞队列中存在DDL语句时,为了防止执行的DML语句执行失败或者未查询出新增的字段,也会阻塞DML语句。由此会使得操作该表的数据库线程均被阻塞。从而导致整个数据库崩溃。

    问题复现

    用户1:开启事务查询某个表。该数据库连接一直被持有:

    image.png

    用户2:执行DDL语句,发现被阻塞:

    image.png

    用户3:模拟主从同步,或者单纯的查询操作,发现线程也会被阻塞:

    image.png

    2. 问题教训

    1. 加事务还是要谨慎,粒度要及其小。
    2. DDL语句尽量不要在访问高峰期进行操作!
    3. DDL执行时机需要有人监管!

    -----------------------------------------------分界线
    2021.6.21

    3. 问题再现

    某天凌晨12点执行ddl语句,主库再次被阻塞。

    经过DBA排查后,发现是phpAdmin执行的一条select语句,却一直存在于mysql主库的服务器中(已经存在一个月)。导致数据库连接一直被持有。再次阻塞ddl语句,而ddl语句阻塞其他的sql语句,造成系统崩溃。

    3.1 问题复现:

    查询数据库存在的进程:

    show processlist;
    
    image.png

    不仅是事务操作,单纯的大的select操作也会阻塞ddl语句。

    一个大的select操作。查询事务:

    SELECT * FROM information_schema.INNODB_TRX
    
    image.png

    结论:单纯的select * from table where id =1也存在事务。

    事务是多个sql语句共有一个数据库连接,而单条的select语句也是一个数据库连接。

    alter table的语句是很危险的(其实他的危险其实是未提交事物或者长事务导致的),在操作之前最好确认对要操作的表没有任何进行中的操作、没有未提交事务、也没有显式事务中的报错语句。如果有alter table的维护任务,在无人监管的时候运行,最好通过lock_wait_timeout设置好超时时间,避免长时间的metedata锁等待。

    推荐阅读

    MySQL出现Waiting for table metadata lock的原因以及解决方法

    相关文章

      网友评论

        本文标题:惊!mysql表新增表字段时造成死锁—造成数据库瘫痪!!!(Wa

        本文链接:https://www.haomeiwen.com/subject/hxfmjltx.html