前一段在月黑風高的夜里,修改線上服務器的表結構,直接導致崩潰,在此記錄過程;
事件回顧
原始表結構
原始表結構類似如下,原先只有一個bill_sn的唯一索引(索引類型為HASH,這里本身就是有些問題的);
CREATE TABLE `op_bill`(`id` bigint(20) NOT NULL AUTO_INCREMENT,
`billSn` varchar(17) NOT NULL COMMENT '單號',
`imcome` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '收入金額',
`outgo` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '支出金額',
`currentBalance` decimal(10,2) NOT NULL COMMENT '當前帳戶余額',
`type` int(10) NOT NULL DEFAULT '1' COMMENT '1 支付 2 退款 3 充值',
`createAt` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `bill_sn` (`billSn`) USING HASH,
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='流水信息(帳戶余額變更記錄)';
修改表結構
- 修改語句很簡單,如下:
ALTER TABLE `op_bill` ADD INDEX `create_at` (`createAt`) USING BTREE ;
- 執行后提示:
ERROR 2013 (HY000): Lost connection to MySQL server during query
- 再次刷新后提示 對該表的任何操作均會提示:
Table doesn't exist in engine
,但show tables
可以顯示出該 表
處理過程
嘗試1:
查看表結構文件及數據文件,無缺失
查詢ibdata/ibdata_logfile1/ibdata_logifle2等文件,無缺失;
重啟數據庫無效;
嘗試2:
新建一張相同表結構的表,表名定義為xxx_1,修改項目中對應的表,讓線上環境能夠寫入數據,記錄當前的position地址;
在測試環境測試,刪除原表,提示一個警告,查詢表已經刪除,但新建該表結構時又提示該表存在,已經刪除表結構文件與表數據文件,嘗試幾次無果;
重構測試數據,在強制恢復模式下可以完全刪除該表,然后重建表結構(xxx);
恢復數據
- 找到之前冷備份的數據,篩出該的數據,導入;
- 從冷備數據找到備份時的postion,和數據庫donw時的position,從mysql-binlog中找出該時段內該表的執行sql(mysqlbinlog -d xxx > xxx.sql);
- 從sql中grep該表的記錄,並導入到表中;
- 將異常時間段內的數據(xxx_1)寫入到xxx表中(insert inot xxx select * from xxx_1);
異常總結
- 這次可能是遇到了mariadb的bug;
- 要有測試環境,兩個環境的數據庫環境要保持一致,所有操作在測試環境先測試無誤后再到生產環境;
- 數據庫至少一天內的全備數據要有;
- 直接刪表的方法有待商榷,是否有修復成功的可能性;