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 自定义变量的概念及特点
May 13 MySQL
浅谈mysql返回Boolean类型的几种情况
Jun 04 MySQL
QT连接MYSQL数据库的详细步骤
Jul 07 MySQL
MySQL 四种连接和多表查询详解
Jul 16 MySQL
MySQL子查询中order by不生效问题的解决方法
Aug 02 MySQL
一篇文章带你深入了解Mysql触发器
Aug 02 MySQL
Mysql分库分表之后主键处理的几种方法
Feb 15 MySQL
MySQL之MyISAM存储引擎的非聚簇索引详解
Mar 03 MySQL
实战 快速定位MySQL的慢SQL
Mar 22 MySQL
MySql分区类型及创建分区的方法
Apr 13 MySQL
MySQL 数据库范式化设计理论
Apr 22 MySQL
MySQL数据库实验之 触发器和存储过程
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
实现树状结构的两种方法
2006/10/09 PHP
php下使用以下代码连接并测试
2008/04/09 PHP
php中配置文件操作 如config.php文件的读取修改等操作
2012/07/07 PHP
PHP 断点续传实例详解
2017/11/11 PHP
购物车实现的几种方式优缺点对比
2018/05/02 PHP
JavaScript读取中文cookie时的乱码问题的解决方法
2009/10/14 Javascript
JavaScript 模拟用户单击事件
2009/12/31 Javascript
浅谈tudou土豆网首页图片延迟加载的效果
2010/06/23 Javascript
jquery 图片上传按比例预览插件集合
2011/05/28 Javascript
jQuery替换字符串(实例代码)
2013/11/13 Javascript
JavaScript实现防止网页被嵌入Frame框架的代码分享
2014/12/29 Javascript
js实现登陆遮罩效果的方法
2015/07/28 Javascript
node.js cookie-parser之parser.js
2016/06/06 Javascript
简单实现轮播图效果的实例
2016/07/15 Javascript
常用的js方法合集
2017/03/10 Javascript
JS+CSS实现下拉刷新/上拉加载插件
2017/03/31 Javascript
详解Angular 4.x Injector
2017/05/04 Javascript
详解React项目的服务端渲染改造(koa2+webpack3.11)
2018/03/19 Javascript
记一次webpack3升级webpack4的踩坑经历
2018/06/12 Javascript
JS构造一个html文本内容成文件流形式发送到后台
2018/07/31 Javascript
Element-ui中元素滚动时el-option超出元素区域的问题
2019/05/30 Javascript
基于JS实现简单滑块拼图游戏
2019/10/12 Javascript
小程序卡片切换效果组件wxCardSwiper的实现
2020/02/13 Javascript
python getopt详解及简单实例
2016/12/30 Python
Python判断telnet通不通的实例
2019/01/26 Python
python使用requests.session模拟登录
2019/08/09 Python
python3-flask-3将信息写入日志的实操方法
2019/11/12 Python
Python合并2个字典成1个新字典的方法(9种)
2019/12/19 Python
tensorflow 限制显存大小的实现
2020/02/03 Python
使用jupyter notebook直接打开.md格式的文件
2020/04/10 Python
基于css3的属性transition制作菜单导航效果
2015/09/01 HTML / CSS
Lookfantastic日本官网:英国知名护肤、化妆品和头发护理购物网站
2018/04/21 全球购物
婚礼答谢宴主持词
2014/03/14 职场文书
幼儿园中班开学寄语
2014/04/03 职场文书
建议书格式
2015/02/04 职场文书
高三语文教学反思
2016/02/16 职场文书