1. 程式人生 > 其它 >pt-osc改表過程中的中文亂碼問題

pt-osc改表過程中的中文亂碼問題

//

pt-osc改表過程中的中文亂碼問題

//

下午使用pt-osc工具對線上表進行變更的時候,發現了一個問題,在對latin1字符集進行變更的時候,變更完畢之後的表的中文註釋都變成了'?',無法正常顯示了。於是在測試環境上進行了實驗。

mysql> show create table latin_test1\G
*************************** 1. row ***************************
       Table: latin_test1
Create Table: CREATE TABLE `latin_test1` (
  `id` int(11) NOT NULL,
  `name` varchar(10) DEFAULT NULL COMMENT '任務名稱',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

# pt指令
pt-online-schema-change --user=dba_admin --password=xxxxxxxx -h127.0.0.1 -P4306 --alter " ADD index idx_name(name)  " D=yeyz,t=latin_test1 --alter-foreign-keys-method=auto --recursion-method=none --print --charset=latin1 --execute

首先建立一張字符集為latin1的表,它包含id和name兩個欄位,然後對這個表的name欄位新增索引,變更的pt指令如上文,其中:

--charset=latin1

當我們變更完成之後,發現變更的新表內容變成:

mysql> show create table latin_test1\G
*************************** 1. row ***************************
       Table: latin_test1
Create Table: CREATE TABLE `latin_test1` (
  `id` int(11) NOT NULL,
  `name` varchar(10) DEFAULT NULL COMMENT '????',
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

可以看到,comment的值變成了'????',而不是我們之前的任務名稱。

出現這個情況之後,我重新做了一個測試,在pt工具的指令中,將--charset引數改成了utf8,pt指令如下:

pt-online-schema-change --user=dba_admin --password=xxxxxxx -h127.0.0.1 -P4306 --alter " modify name varchar(10) DEFAULT NULL COMMENT '任務名稱' " D=yeyz,t=latin_test1 --alter-foreign-keys-method=auto --recursion-method=none --print --charset=utf8 --execute  

執行完成之後,結果如下:

mysql> show create table latin_test1\G
*************************** 1. row ***************************
       Table: latin_test1
Create Table: CREATE TABLE `latin_test1` (
  `id` int(11) NOT NULL,
  `name` varchar(10) DEFAULT NULL COMMENT '任務名稱',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

這個結果中,我們可以看到2點:

1、我們的表latin_test1的字符集仍舊是latin1,而沒有被改成utf8的字符集

2、表中的中文註釋已經可以顯示了。

--charset這個引數在pt-osc這個工具中,指的是使用哪種字符集去連線資料庫,如果使用utf8的話,那麼在連線到資料庫之後,會首先執行set names utf8;它指定了客戶端和伺服器之間傳遞字元的編碼規則為UTF8。如果我們使用latin1這個字符集,則說明pt-osc工具和mysql互動的字符集是latin1,而這個字符集是無法儲存漢字的,所以結果中就出現了????的字眼。

除此之外,今天還專門看了下pt-osc工具建立的三個觸發器的內容,觸發器的內容不是單純的將主庫上的動作原封不動的搬遷到從庫上,它的建立規則如下:

(1)對於DELETE操作,pt工具使用DELETE IGNORE在新表進行刪除,當新有資料時,我們才進行操作,也就是說,當在後續匯入過程中,如果刪除的這個資料還未匯入到新表,那麼我們可以不在新表執行操作,因為在以後的匯入過程中,原表中改行資料已經被刪除,已經沒有資料,那麼這條記錄也就不會匯入到新表中; (2)對於INSERT操作,所有的INSERT INTO全部轉換為REPLACE INTO,當有新資料插入到原表時,如果觸發器還未把原表資料同步到新表,而這條資料已經被pt工具匯入到新表了,再次insert就會發生報錯,那麼我們就可以利用replace into進行覆蓋,這樣資料也是一致的 (3)對於UPDATE操作,所有的UPDATE也轉換為REPLACE INTO,因為當更新的資料的行還未同步到新表時,新表是不存在這條記錄的,直接update肯定會報錯,那麼我們就只能插入該條資料,如果已經同步到新表了,那麼也可以進行覆蓋插入,所有資料與原表也是一致的;