天天看點

MySQL源碼學習:關于 'A' =='A '的問題

  昨天一位同僚問到一個問題,他的mysql中導入資料的時候,發現唯一索引沖突,原因是有兩行記錄,差別隻是有一條記錄多了最後的一個空格。 希望有方法将他們設定不同。

複現:

create table `t` (

`c` varchar(20) not null default '',

primary key (`c`)

) engine=innodb default charset=gbk;

insert into t(c) values("a");

insert into t(c) values("a ");

在執行第二個insert的時候,會報主鍵沖突。

原因:

gbk字元串判斷時,用的是這個函數 my_strnncollsp_gbk (strings/ctype-gbk.c)

簡單邏輯如下

從代碼上看,沒有什麼問題,邏輯是先用比較小的算出長度,然後作字元串對比,此時認為相同。然後根據宏定義,如果沒有加編譯參數varchar_with_diff_endspace_are_different_for_unique ,則diff_if_only_endspace_difference為0,是以當兩個字元串隻差別于末尾的空格個數時,認為字元串相同。

(不用擔心'a' 和 'ab'對比的情況, 省略号部分作了這個判斷的)

但是這個在5.0中新增的編譯參數并沒有用!!

原因是innodb在調用這個函數的時候,diff_if_only_endspace_difference傳的就是0。

也就是說,你就算加了這個編譯參數,行為并沒有改變, 沒有把這個值設定為1的代碼 。

方案:

a) 比較優美的方案是是把innodb中調用處傳入的diff_if_only_endspace_difference, 也改成按照varchar_with_diff_endspace_are_different_for_unique 來決定0還是1。

b) 比較簡單的方案是将上面代碼中的宏定義這段改寫成意思相同的ifdef寫法,

繼續閱讀