MySQL 數據丟失排查案例
前言
最近,有一位朋友突然微信聯系我,說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 數據丟失排查的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- MySQL 5.7之關於SQL_MODE的設置
- MySQL sql_mode的使用詳解
- 高版本Mysql使用group by分組報錯的解決方案
- mysql數據庫表增添字段,刪除字段,修改字段的排列等操作
- MySQL時間設置註意事項的深入總結