FAQ系列|列型別被自動修改導致複製失敗

晚來風急發表於2017-08-02

0、導讀

在複製環境中,有個表的列型別總是被修改,導致複製程式報錯停止

1、問題描述

問題發生在朋友的資料庫上,做了主從複製,其中某表有一列型別是INT,但是該表上的INSERT事件在BINLOG中卻總被記錄為MEDIUMINT型別,導致這個事件在SLAVE上執行失敗。

相關現場資訊見下:

MySQL版本:官方5.5.版本。

表DDL定義:

CREATE TABLE `t` (

  `userid` int(10) unsigned NOT NULL DEFAULT 0,


這個表上的INSERT事件在BINLOG中的記錄:

### INSERT INTO `imysql`.`t`

### SET

###   @1=207 /* MEDIUMINT meta=0 nullable=0 is_null=0 */


我們看到BINLOG中,這個列型別顯示為MEDIUMINT,這個事件在SLAVE上就會報告下面的錯誤,導致SLAVE無法繼續複製:

Column 0 of table `imysql.t` cannot be converted from type `mediumint` to type `int(10) unsigned

又是一個看起來很奇葩的案例。

2、原因分析

經過溝通排查,瞭解到他們的業務模式有點特殊,是從一箇舊的空表中複製表結構生成每天日誌表,然後再將當天的日誌寫入該表。也就是大概做法是:

1、建立每天日誌表

CREATE TABLE t SELECT t_orig;


2、寫入日誌

INSERT INTO t SELECT * FROM t_orig;


其實問題就出在每天建立新表的過程中,源表結構像是這樣的:

CREATE TABLE `t_orig` (

  `userid` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,


從源表複製到新表之後,又執行了ALTER TABLE,把 userid 列型別從 MEDIUMINT 改為 INT,建立儲存過程等其他工作。

生成新表後,再寫入生成的日誌。但是呢,寫入日誌卻又是採用INSERT…SELECT的用法。一般情況下當然沒問題,但這個例子中,源表、目標表的 userid 列型別恰好不一樣(源是MEDIUMINT,目標是INT),結果導致在 binglog 中記錄event時,將 userid 列型別強制轉換為 MEDIUMINT 了。這個 INSERT 在 MASTER 端可以正常執行完畢,但卻引發了 SLAVE 檢測到二者資料型別不一致,寫入失敗,複製異常中斷。

3、問題建議

遇到這種案例也真的是醉了,從源表每天克隆一個新表做法沒問題,採用INSERT…SELECT也沒問題,但為啥要源表和新表使用不同資料型別呢,直接把源表的也改成INT不就行了嗎,只能說某些人懶得不像樣了。

4、類似案例

FAQ系列 | 寫新資料時某列值總是被自動修改

文章轉自老葉茶館公眾號,原文連結:https://mp.weixin.qq.com/s/fI3zdn7D4JOb8RPeImfbDQ


相關文章