SQL血的教训--数据库故障30例汇总(更新到2025年3月)

记录一下这些年做DBA工作上遇到的各种数据库故障:

1,每次查询的数据要有限制

     2013年1月  产品独立数据库,由于多条SQL每次查询数据超过几千条,有些超过10万条数据未分页,造成应用服务器CPU有时持续100%。

2,禁止循环调用SQL

    2011年5月  程序调用Sys_User查询,每分钟执行超过3千次,造成服务器CPU持续100%

3,禁止使用递归方法调用SQL;

    方法内如出现数据异常,极易造成查询死循环

4,禁止每次写入大量数据
    2011年7月  深圳库导入订单的存储过程中加入一条insert语句,每次insert超过100万条,几个小时将深圳数据库服务器磁盘写满,业务无法运行,后来担心其他库也会有这样写满表情况(因当时研发流程比较混乱),就写了一个对比表行数脚本,结果没几天,发现有个表1,2天时间表行数爆增加几千万行,一查是有个研发同学程序的bug导致,立马让他改程序。

5,禁止在事务中使用循环加入缓存;
    2011年4月  批量更新Sys_user用户后,又在事务里循环加入缓存,造成事务运行太长,严重影响系统性能。

6,必须在语句的具体字段要明确列出

  2011年3月  查询Product表数据,每次查询出全部字段,包括不需要的产品详细描述信息(字段text类型),造成系统网卡流量暴高。

7,禁止使用业务逻辑大的事务
    2011年4月开始,前台客户最长等待需要超过30S完成下单,查询发现下单整个操作包在一个巨大的事务中,严重影响客户下单。

8,禁止使用SQL游标Cursor;

    游标使用不当,会严重影响系统性能

9,Select查询放到事务外

    2011年6月  某条insert语句很慢,检查发现取表的Sequence语句放在insert的事务里,在高并发下,失败率很高。

10, 禁止一次删除大量数据
     2012年11月  Customer_LoginLog表由于前台写入暴增,造成当天数据超过1500万条,SQL归档执行了6个小时未删除完,影响业务操作超过6个小时,后续在写归档存储过程时,每次delete 都会限制删除50 万条,循环删除,而不是一次性删除。

11,禁止主键删除再新建

    2016年,Coupon表数据,有1亿多条数据,查看其主键有大量碎片,当时不想用online的方式重建,还是想先删除,后创建。因为当时是早上4点多,

开发人员说基本没人使用, 就没有影响,就先删除主键,结果删除后,没想到系统有大量查询coupon的请求,而主键没有,数据库运行很慢,kill后一直有,

后来没办法,禁用这个连coupon表的账户,等主键创建成功后,再启用账户

12,禁止用系统登录触发器

    2017年9月,因为黑客攻击,想在数据库做个监控,对凌晨1-7点间登录数据库的做个监控,用了SQL Server的系统登录触发器,记录登录信息,结果触发器先建好,记录信息的表没有建,导致 登录触发器审计失败,这个失败导致,其他用户登录时也会触发这个系统登录触发器,也报登录失败,登录不了,自己试了其他4台备机,也都登录不了,前台,后台和wms程序全部报错,查了网上资料也没找到合适的方法,程序一直在报错,这时突然发现,已经登录同步实时从库(8.10),虽然不能登录,

    但是他已经登录了,这时我看,可以使用,我这时立刻删除刚建的触发器,执行AlwaysON切换,把数据库从主库切到实时备库。  经历了20多分钟的重大事故终于解决。

  事后发现有2个解决办法,1,备份master库,出现异常时还原master库   2,CMD最小化登录数据库删除触发器

     我这边发现就是还有一个登录好的实时备库,进去删除。

     因为这20多分钟经历太痛苦,一直不想去模拟2种处理方案,因为后续也不会用登录系统触发器。 

13,MySQL的从库Offline模式

      2020年9月 , 清理异常数据,重设为online模式 

14,MySQL的内核bug,导致十几从库回放binlog报错

      2020年9月 , 把主库的MySQL的binlog改成ROW模式,设置成FULL ,腾讯云增加监控只读实例剔除等监控

15, 云Redis,突然被云商下调带宽到正常,导致带宽打满

      扩容Redis的带宽 

16,云Redis,晚上6点开始,CPU持续80%左右

       关闭和重启异常的IP的程序解决

17,云Redis的内存持续增长

      在key里加上日期,key不停增长,内存暴涨,删除无用的key,同时修改程序 ,

      安装redis-rdb-tools工具,分析redis整体的大key  如:rdb -c memory /root/1 --bytes 1024 -f memory.csv

18,云Redis的CPU高峰期突破60%

     查询最耗时的命令,将hget命令一次取一个,改成mget命令一次取多个key,CPU下降

19,MySQL高并发曝高,JAVA网关冲曝

     2021年5月业务程序原查询redis改到MySQL,业务高峰导致MySQL的CPU曝高后,程序有3次重试,大量连接冲击网关,网关假死,线上程序大面积故障

  将大量的查询改到Redis,同时去掉程序的show columns from 表的命令

 20,MySQL从库一直延迟

      凌晨大量的更新数据,从库有简单SQL查询导致延迟很大,批量kill掉卡住的SQL,不延迟后提升从库内存从32G升级到64G      

 21,错误SQL执行全表更新

       亚马逊云MySQL执行的错误SQL,由于SQL太长没注意SQL有错误,执行后全表数据更新,发现是sql-mode设置问题,导致错误SQL能执行成功。

  发现执行错误后,通过亚马逊云的实例数据回滚,再通过数据导出还原。

 

22,大量长事务无法提交程序的定位(2023年4月)

     2023年3月,朋友新上线的订单系统,在阿里云RDS MySQL8.0上有大量未提交的事务,通过查询事务语句,又没有具体的执行SQL,能定位到具体服务,但服务业务代码太多,通过SQL全审计和慢日志都无法定位到具体程序方法, 后来有人发现执行事务开始时间有规律,就是每个事务的开始时间都是每分钟执行。后来和研发等沟通关闭xxl-job的相关的订单,3个每分钟job调用订单相关服务,发现数据库未事务不再增加,再看这3个服务,定位未提交事务的程序具体位置。

     以前出现这样未提交事务,一般通过下列SQL语句查出未提交的事务:

select timestampdiff(SECOND,trx_started,now()) diffsecond,b.host,b.user,concat('kill ',b.ID,' ;') killsql,b.db,
IFNULL(b.INFO,a.trx_query) runsql
from information_schema.innodb_trx a left join
information_schema.PROCESSLIST b on a.trx_mysql_thread_id=b.ID
-- where timestampdiff(SECOND,trx_started,now()) >=20  ;
order by 1 desc limit 50;  

     

     上面查询后,结果处理方法:

      1, 有SQL语句: 通过SQL去程序定位到方法

      2, 没有SQL语句: 通过下列命令去具体IP(172.17.16.137)的机器执行下列命令:

netstat -atpln | grep 46154   根据host的端口查看pid
ps -ef|grep 10935       这个10935就是上面查出的pid,查看对应的服务

      3,如果有日志ELK或CAT监控,可以Kill进程,去ELK日志或者CAT根据,出错,IP和端口(如172.17.16.137和46154) 反查执行的进程

     这次故障处理,通过SQL事务的开始时间找到规律,定位到xxl-job引起,也是第一次用到,故障处理有时真是考验细心和耐心。

 23 ,只读从库有未提交事务,加字段不成功,导致程序无法连接腾讯云MySQL从库 (2023年12月28日)

      上周在主库加了一个字段,数据不到百万条,执行比较快,没有发现问题,结果周末发现程序连接其中一个腾讯云只读RO组的数据库连不上,但通过Navicat 是可以连,研发一直在找问题,也问我数据库有做什么调整,我这几天也没调整数据库配置,

后来周一来,这问题还是有,通过22的查询长事务一查,发现从库5有未提交的事务,有2个SQL时间还很长   

  kill掉上面的长事务后,发现执行的加字段语句才开始执行:

   执行完成加语句的SQL,系统能连该只读从库了。 腾讯云的技术支持解释:”ddl操作需要获取mdl锁,如果没有获取到mdl锁会一直处于waiting metadata lock并且阻塞后续对该表的操作“,只读从库未提交的只读事务,是能影响DDL获取mdl锁。

  24,自建从库经常延迟 (2024年12月补充)

    腾讯云的RDS MySQL主库,在云主机下自建了MySQL,作为其从库,配置了云的SSD,4核16G内存,但经常自建从库有延迟:

      腾讯云MySQL从库的配置:  

sync_binlog=0; 性能最好的
innodb_flush_log_at_trx_commit=2;

   但自建云主库的从库的性能就是要比RDS MySQL从库要差,修改了以上配置就OK,但又会出现丢数据的情况:     

set global sync_binlog=500;
set global innodb_flush_log_at_trx_commit=2;

  25,简单加字段导致腾讯云MySQL从库延迟 (2024年12月2日补充)

      业务主库小表加一个字段,直接用alter命令执行,执行很快,没想到不久,程序同学说一个从库的数据延迟厉害,看了一下5个从库,4个成功了,另一个从库的alter命令一直在运行中,在等待获取MDL锁失败,原来这个库有个复杂的关联SQL查询一直在运行,SQL查询中就包含这个小表,导致无法alter成功,手工kill掉这个SQL就OK

  26,腾讯云GTID复制跳过错误 (2024年12月补充)

     业务从库回放SQL报错,缺少数据导致,但程序不能停止使用并要保证业务使用,咨询腾讯云的技术支持,先要需要跳过这个事务再加从库处理:

     这里的“xxxxx:N "也就是你的slave sql thread报错的GTID,或者说是你想要跳过的GTID   
STOP SLAVE;
SET SESSION GTID_NEXT = '0580073f-f1e5-11ea-a819-6c92bf46f8ba:1171724369';
BEGIN; COMMIT;
SET SESSION GTID_NEXT = AUTOMATIC;
START SLAVE;

  show slave status 看的 Executed_Gtid_Set (已经执行的GTID集合)的值,

   上面输入的GTID_NEXT:主Master的数据库ID,后面最大的GTID值加1,

   如下面,有多个MySQL的数据库ID,要找主库的ID后的GTID,gtid_executed变量一定是实时更新的不管主库和从库,可以通过GTID变动对比出数据库ID。加1后就是要跳过的值,如下:   

04cfe2d0-8709-11ea-993a-a4fa76fdf2a6:1-2542558987,
0580073f-f1e5-11ea-a819-6c92bf46f8ba:1-1171724368,
11d54078-63b0-11ea-9642-6c92bf48246b:1-9935,
151ba254-8709-11ea-95a6-a4fa76fdf4b0:1,

   临时跳过这个错误后,立即备份腾讯云主库,在该RO组新建一个读库替换旧的数据库从库,保证和主库数据一致。

   27,MySQL从库重启丢数据  (2025年3月补充)

      MySQL 从库down机中午突然down机,重启后,从库同步报主键重复的错误,删除从库的主键即可

       因为:非双1模式,数据库异常重启时可能会导致部分事务丢失数据

       详细过程:https://www.cnblogs.com/zping/p/10108702.html

   28,主库DML操作慢故障 (2025年3月补充)

      从2018年8月份开始,特别是每天早上9:00--11:00,做活动的时候,研发发现下单的insert需要1秒,有些有3秒的,而且是大量出现,简单的insert也很慢有,严重影响业务 ,自己查了主库,的确没发现什么异常的,就是有大量的等待事件HADR_SYNC_COMMIT,一开始以为是监控数据不对,主库的CPU和IO性能都正常,怎么可能这么慢,而且不是一直慢,而是在一时间段,这一直困扰找不到原因后来偶尔查了实时备库,发现备库的查询的SQL大量的慢SQL,而且是这些SQL有些查询特别大的表,很耗CPU。后来让研发把这个大的慢的查询改掉,不读这个实时备库。改完第二天就没有问题,

       详细过程:https://www.cnblogs.com/zping/p/10110671.html

  对一些实时同步备份的从库,也要监控其性能,主库有实时同步,实时的从库的处理性能也会影响主库的DML写入

  29,线上使用未经严格测试的第三方代码导致故障 (2025年3月补充)

      几年前在3C电商做DBA,有次网上看到了自动复制表结构的存储过程代码,测试了一下觉得很方便,有次刚好有个财务表需要重建,就使用该存储过程创建copy结构,导入数据后,看数据都正常,没过几天,负责这块的研发经理说业务反应,客户下单后给寄的发票,都没有小数点,只有整数,我一查,原来该存储过程copy表结构时,对小位数的字段是转换成整数,立刻检查把财务表的字段,改成decimal类型,跟领导反映了这是copy建表的导致的,后来研发经理跟研发总监说,没办法让仓库把这些发票作废,重新给客户邮寄新的发票,几天时间估计有个好几百张发票,也幸亏当时的领导没有追究,加上不久前又出个数据库故障,等于这2,3周的时间连续出现了2次故障,后来有点不敢动这个数据库了,生怕又搞出事情,慢慢平复心情后才走出这2次故障的阴影,后来对第三方工具和代码,没有经过长期验证的, 坚决不在线上数据库使用。

   30,连接数爆满,程序无法申请新的连接 (2025年3月补充)

      业务急速发展,研发几乎每天都上线程序,有时未严格测试,能读redis缓存,直接读MySQL库的,在高峰期就会出现连接池爆满,出现这样情况,就进腾讯云后台批量kill进程,出现几次,研发测试的流程短期无法改变,就想尽量减少单个程序和单个账号出现异常导致整个系统的不可用,后面将全部账号的最大连接数max_connections从2000调到9000,单个账号最大连接数max_user_connections改成3000。

posted @ 2019-09-17 13:33  zping  阅读(650)  评论(2)    收藏  举报