→

MySQL →  Как я фиксил баг в MySql

Эту историю можно было бы закинуть и в говнокод, но здесь не все очевидно и есть поучительные вещи.

Сотрудник сегодня скинул интересные запросы:

mysql> select * from db1.users t1 inner join db2.users t2 on t1.login=t2.username;

Empty set (1.61 sec)

mysql> select * from db1.users t1 where t1.login='igor';

1 row in set (0.11 sec)

mysql> select * from db2.users t2 where t2.username='igor';

1 row in set (0.03 sec)

Таблица t2 была создана до него, t1 создавал он сам.
В общем, он бил себя в грудь и орал, что нашел баг в мускуле. Я не верю ни в такие баги, ни в мистику (меня этому научили уже давно). Если вы видите такой «баг», то для начала найдите все баги у себя.

Не поверил я ему. Полез в эти базы, появился просто спортивный интерес:) Запускаю запросы, действительно отработали так, как он мне их сбросил. Я умышленно изменил таблицы и не показал результаты работы запросов, так вот, меня насторожило, что первый запрос выдал в результате поле login 'IGOR', а второй запрос — поле username 'igor'.

А он в качестве аргумента, что баг найден сделал так:
mysql> select if('IGOR'='igor',1,0);

+-----------------------+
| if('IGOR'='igor',1,0) |
+-----------------------+
| 1 |
+-----------------------+
1 row in set (0.00 sec)

mysql> select if('IGOR'!='igor',1,0);

+------------------------+
| if('IGOR'!='igor',1,0) |
+------------------------+
| 0 |
+------------------------+
1 row in set (0.00 sec)

Сука, думаю, вот тебе и баг у мускула. Полез дальше в структуру таблиц, а там я вижу.

t1.login — сравнение стоит utf8_bin
t2.username — сравнение стоит utf8_general_ci

utf8_bin — хранит буковки 'G' и 'g' по-разному.
Поменял utf8_bin на utf8_general_ci и пофиксил баг у mysql:)
3