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中使用or、in与union all在查询命令下的效率对比
May 26 MySQL
mysql 如何获取两个集合的交集/差集/并集
Jun 08 MySQL
MySQL 发生同步延迟时Seconds_Behind_Master还为0的原因
Jun 21 MySQL
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
Jun 26 MySQL
MySQL的Query Cache图文详解
Jul 01 MySQL
详解MySQL中timestamp和datetime时区问题导致做DTS遇到的坑
Dec 06 MySQL
MySQL的InnoDB存储引擎的数据页结构详解
Mar 03 MySQL
简单聊一聊SQL注入及防止SQL注入
Mar 23 MySQL
MySQL视图概念以及相关应用
Apr 19 MySQL
MySql中的json_extract函数处理json字段详情
Jun 05 MySQL
MySQL详细讲解变量variables的用法
Jun 21 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
2020最新CPU的性能排名
2020/04/02 数码科技
用libTemplate实现静态网页的生成
2006/10/09 PHP
PHP整数取余返回负数的相关解决方法
2014/05/15 PHP
PHP curl 抓取AJAX异步内容示例
2014/09/09 PHP
PHP实现通过中文字符比率来判断垃圾评论的方法
2014/10/20 PHP
PHP explode()函数用法讲解
2019/02/15 PHP
Laravel基础_关于view共享数据的示例讲解
2019/10/14 PHP
基于jquery的一个浮动框(扩展性比较好 )
2010/08/27 Javascript
javascript分页代码实例分享(js分页)
2013/12/13 Javascript
JavaScript实现单击下拉框选择直接跳转页面的方法
2015/07/02 Javascript
JS实现仿新浪黄色经典滑动门效果代码
2015/09/27 Javascript
js实现select下拉框菜单
2015/12/08 Javascript
解决JS无法调用Controller问题的方法
2015/12/31 Javascript
原生JS实现匀速图片轮播动画
2016/10/18 Javascript
微信小程序去哪里找 小程序到底如何使用(附小程序名单)
2017/01/09 Javascript
js获取地址栏中传递的参数(两种方法)
2017/02/08 Javascript
jquery操作select取值赋值与设置选中实例
2017/02/28 Javascript
bootstrap模态框远程示例代码分享
2017/05/22 Javascript
浅析webpack 如何优雅的使用tree-shaking(摇树优化)
2017/08/16 Javascript
NodeJS实现视频转码的示例代码
2017/11/18 NodeJs
微信小程序实现日历效果
2018/12/28 Javascript
小程序实现新用户判断并跳转激活的方法
2019/05/20 Javascript
js实现单元格拖拽效果
2020/02/10 Javascript
Vue3配置axios跨域实现过程解析
2020/11/25 Vue.js
使用Python将数组的元素导出到变量中(unpacking)
2016/10/27 Python
为什么str(float)在Python 3中比Python 2返回更多的数字
2018/10/16 Python
12个步骤教你理解Python装饰器
2019/07/01 Python
Python list与NumPy array 区分详解
2019/11/06 Python
python db类用法说明
2020/07/07 Python
与世界上最好的跑步专业品牌合作:Fleet Feet
2019/03/22 全球购物
关于圣诞节的广播稿
2014/01/26 职场文书
中华魂演讲稿
2014/05/13 职场文书
小学生国庆65周年演讲稿范文(2篇)
2014/09/21 职场文书
入党积极分子十八届四中全会思想汇报
2014/10/23 职场文书
2019各种保证书范文
2019/06/24 职场文书
导游词之云南丽江古城
2019/09/17 职场文书