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 05 MySQL
left join、inner join、right join的区别
Apr 05 MySQL
MySQL触发器的使用
May 24 MySQL
SQL实现LeetCode(196.删除重复邮箱)
Aug 07 MySQL
SQL IDENTITY_INSERT作用案例详解
Aug 23 MySQL
MySQL定时备份数据库(全库备份)的实现
Sep 25 MySQL
Mysql案例刨析事务隔离级别
Sep 25 MySQL
教你使用VS Code的MySQL扩展管理数据库的方法
Jan 22 MySQL
分享几个简单MySQL优化小妙招
Mar 31 MySQL
MySQL分区路径子分区再分区
Apr 13 MySQL
MySQL如何修改字段类型和字段长度
Jun 10 MySQL
MySQL表字段数量限制及行大小限制详情
Jul 23 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 中self,this的区别和操作方法实例分析
2019/11/04 PHP
jquery 取子节点及当前节点属性值
2014/07/25 Javascript
javascript结合CSS实现苹果开关按钮特效
2015/04/07 Javascript
javascript结合canvas实现图片旋转效果
2015/05/03 Javascript
js实现改进的仿蓝色论坛导航菜单效果代码
2015/09/06 Javascript
基于jQuery实现拖拽图标到回收站并删除功能
2015/11/25 Javascript
一种基于浏览器的自动小票机打印实现方案(js版)
2016/07/26 Javascript
jQuery 判断元素整理汇总
2017/02/28 Javascript
jquery应用实例分享_实现手风琴特效
2018/02/01 jQuery
vue环形进度条组件实例应用
2018/10/10 Javascript
javascript sort()对数组中的元素进行排序详解
2019/10/13 Javascript
一看就会的vuex实现登录验证(附案例)
2020/01/09 Javascript
vue cli4下环境变量和模式示例详解
2020/04/09 Javascript
vue+ElementUI 关闭对话框清空验证,清除form表单的操作
2020/08/06 Javascript
[02:36]DOTA2上海特锦赛 回忆电竞生涯的重要瞬间
2016/03/25 DOTA
[01:09:16]DOTA2-DPC中国联赛 正赛 SAG vs Dynasty BO3 第一场 1月25日
2021/03/11 DOTA
Python break语句详解
2014/03/11 Python
Python跳出循环语句continue与break的区别
2014/08/25 Python
Python创建一个空的dataframe,并循环赋值的方法
2018/11/08 Python
Django学习笔记之为Model添加Action
2019/04/30 Python
Django网络框架之HelloDjango项目创建教程
2019/06/06 Python
Python关于__name__属性的含义和作用详解
2020/02/19 Python
学习Python需要哪些工具
2020/09/04 Python
HTML5拖拽文件上传的示例代码
2021/03/04 HTML / CSS
Bugatchi官方网站:男士服装在线
2019/04/10 全球购物
如何使用PHP session
2015/04/21 面试题
毕业生简历自我评价范文
2014/04/09 职场文书
银行竞聘演讲稿范文
2014/04/23 职场文书
物理教育专业求职信
2014/06/25 职场文书
办理护照工作证明
2014/10/10 职场文书
生死抉择观后感
2015/06/09 职场文书
七年级作文之《我和我的祖国》观后感作文
2019/10/18 职场文书
MySQL令人咋舌的隐式转换
2021/04/05 MySQL
PostgreSQL通过oracle_fdw访问Oracle数据的实现步骤
2021/05/21 PostgreSQL
Python数据分析之绘图和可视化详解
2021/06/02 Python
Javascript使用integrity属性进行安全验证
2021/11/07 Javascript