MySQL 数据丢失排查案例


Posted in MySQL onMay 08, 2021

前言

最近,有一位朋友突然微信联系我,说MySQL出现了数据丢失的情况;毫无疑问,对于一个DBA而言,这无疑是最令人紧张的一件事情,没有之一;听到这个消息后,我也就立刻投入到问题排查中。

现场排查

一开始听到这个消息,我心里面当然也是非常紧张,不过很快就让自己冷静下来,开始进行排查:

(1)实例状态是不是正常的?    --经确认,实例状态正常

(2)业务库是哪个?是否还存在?是否被删除?    --经确认,业务库存在

(3)业务是访问哪个表报错?该表是否存在?是否被删除?    --经确认,业务表存在

(4)应用用户的权限是否正常?    --经确认,应用用户拥有业务库的所有权限

(5)业务访问是报什么错?    --经确认,业务侧是访问某些页面报错

(6)排查到这里,一方面是怀疑应用程序是否有异常,另一方面是怀疑是否出现部分记录丢失;开发侧和运维侧同时在排查,这边给运维侧排查的思路是 业务表是否有主键?业务侧访问报错和业务表的对应关系是怎样的?能否找出相对应的记录?

(7)进一步分析发现,该业务表有主键,开发侧也提供了查询的记录,经排查该记录存在,并未被误删除;开发侧排查应用程序,日志也未很清晰打印出报错信息

(8)在这种情况下,只能先咨询一下当晚是否有做什么变更/发布?    --经确认,当晚有做一些表的DDL变更

继续排查发现,当晚DDL变更有涉及到该业务表的操作,变更内容为修改字段长度,类似alter table xxx modify column xxx char(x);问题到这里也就开始有思路了,接下去开始排查sql_mode配置、查询相应的完整行记录给开发确认,最终确认是DDL变更导致字段被截断,最后只能通过备份进行恢复,问题最终得到解决。

案例复现

看完刚刚的排查过程,相信很多童鞋都会有疑问,为什么修改字段长度对导致数据被截断?MySQL难道不会不会做数据校验吗?让我们接着往下看。

(1)场景1

mysql> select * from sbtest2 limit 1;
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| id | k       | c                                                                                                                       | pad                                                         |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
|  1 | 3718516 | 08566691963-88624912351-16662227201-46648573979-64646226163-77505759394-75470094713-41097360717-15161106334-50535565977 | 63188288836-92351140030-06390587585-66802097351-49282961843 |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table sbtest2 modify column pad char(1);
ERROR 1265 (01000): Data truncated for column 'pad' at row 1

mysql> select * from sbtest2 limit 1;
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| id | k       | c                                                                                                                       | pad                                                         |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
|  1 | 3718516 | 08566691963-88624912351-16662227201-46648573979-64646226163-77505759394-75470094713-41097360717-15161106334-50535565977 | 63188288836-92351140030-06390587585-66802097351-49282961843 |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
1 row in set (0.00 sec)

(2)场景2

mysql> select * from sbtest2 limit 1;
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| id | k       | c                                                                                                                       | pad                                                         |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
|  1 | 3718516 | 08566691963-88624912351-16662227201-46648573979-64646226163-77505759394-75470094713-41097360717-15161106334-50535565977 | 63188288836-92351140030-06390587585-66802097351-49282961843 |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> alter table sbtest2 modify column pad char(1);Query OK, 100 rows affected, 100 warnings (0.06 sec)
Records: 100  Duplicates: 0  Warnings: 100

mysql> select * from sbtest2 limit 1;
+----+---------+-------------------------------------------------------------------------------------------------------------------------+------+
| id | k       | c                                                                                                                       | pad  |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+------+
|  1 | 3718516 | 08566691963-88624912351-16662227201-46648573979-64646226163-77505759394-75470094713-41097360717-15161106334-50535565977 | 6    |
+----+---------+-------------------------------------------------------------------------------------------------------------------------+------+
1 row in set (0.00 sec)

场景1是比较符合我们预期的,直接报错“数据被截断”;场景2是执行成功,导致“数据部分丢失”;那么,MySQL是没有进行数据校验吗?其实MySQL都有对数据进行校验的,只是在场景2中,因为sql_mode配置有问题,没有设置STRICT_TRANS_TABLES,导致MySQL没有阻止该操作执行,从而导致“数据丢失”惨案。

总结

至此,“数据丢失”惨案也就可以告一段落,根本原因是sql_mode没有设置STRICT_TRANS_TABLES;这个案例也是在提醒我们,sql_mode是一个非常关键的配置,千万不可随便设置和修改;关于sql_mode的更多内容,下篇文章会继续给大家分享。

以上就是MySQL 数据丢失排查案例的详细内容,更多关于MySQL 数据丢失排查的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL 慢查询日志深入理解
Apr 22 MySQL
MySQL优化之如何写出高质量sql语句
May 17 MySQL
MySQL 重命名表的操作方法及注意事项
May 21 MySQL
Mysql效率优化定位较低sql的两种方式
May 26 MySQL
MySQL 数据类型选择原则
May 27 MySQL
mysql分表之后如何平滑上线详解
Nov 01 MySQL
MYSQL 表的全面总结
Nov 11 MySQL
mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
Feb 12 MySQL
面试中老生常谈的MySQL问答集锦夯实基础
Mar 13 MySQL
mysql 8.0.27 绿色解压版安装教程及配置方法
Apr 20 MySQL
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
Apr 20 MySQL
MySQL中JOIN连接的基本用法实例
Jun 05 MySQL
MySQL update set 和 and的区别
May 08 #MySQL
MySQL查询学习之基础查询操作
May 08 #MySQL
MySQL sql_mode修改不生效的原因及解决
May 07 #MySQL
一篇文章弄懂MySQL查询语句的执行过程
详解MySQL主从复制及读写分离
MySQL 表空间碎片的概念及相关问题解决
MySQL kill不掉线程的原因
May 07 #MySQL
You might like
PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据
2012/04/09 PHP
PHP检测用户是否关闭浏览器的方法
2016/02/14 PHP
tp5框架基于Ajax实现列表无刷新排序功能示例
2020/02/10 PHP
JQuery的ajax获取数据后的处理总结(html,xml,json)
2010/07/14 Javascript
指定区域的图片自动按比例缩小的js代码(防止页面被图片撑破)
2014/02/21 Javascript
禁用页面部分JavaScript不是全部而是部分
2014/09/03 Javascript
jquery中ajax使用error调试错误的方法
2015/02/08 Javascript
JavaScript中的条件判断语句使用详解
2015/06/03 Javascript
JavaScript实现九九乘法表的简单实例
2016/06/07 Javascript
AngularJS 应用身份认证的技巧总结
2016/11/07 Javascript
jQuery中的select操作详解
2016/11/29 Javascript
十大 Node.js 的 Web 框架(快速提升工作效率)
2017/06/30 Javascript
VueJs组件之父子通讯的方式
2018/05/06 Javascript
AngularJS标签页tab选项卡切换功能经典实例详解
2018/05/16 Javascript
vscode vue 文件模板的配置方法
2019/07/23 Javascript
Nuxt.js实战和配置详解
2019/08/05 Javascript
JS简单表单验证功能完整示例
2020/01/26 Javascript
[37:02]OG vs INfamous 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
基于python3实现socket文件传输和校验
2018/07/28 Python
用python生成(动态彩色)二维码的方法(使用myqr库实现)
2019/06/24 Python
Python 中的参数传递、返回值、浅拷贝、深拷贝
2019/06/25 Python
python+openCV调用摄像头拍摄和处理图片的实现
2019/08/06 Python
对python中的*args与**kwgs的含义与作用详解
2019/08/28 Python
Python高级编程之消息队列(Queue)与进程池(Pool)实例详解
2019/11/01 Python
PyCharm 2020.2下配置Anaconda环境的方法步骤
2020/09/23 Python
python利用 keyboard 库记录键盘事件
2020/10/16 Python
css3实现一款模仿iphone样式的注册表单
2013/03/20 HTML / CSS
雅诗兰黛美国官网:Estee Lauder美国
2016/07/21 全球购物
柒牌官方商城:中国男装优秀品牌
2017/06/30 全球购物
来自圣地亚哥的实惠太阳镜:Knockaround
2018/08/27 全球购物
学生自我鉴定
2013/12/18 职场文书
家长给学校的建议书
2014/05/15 职场文书
商务英语专业求职信
2014/06/26 职场文书
幼儿学前班评语
2014/12/29 职场文书
2016年乡镇综治宣传月活动总结
2016/03/16 职场文书
iPhone13 Pro外观确定,升级4800万镜头,4月20日发新品
2021/04/15 数码科技