Функция mySQL ведет себя по-разному на двух серверах, которые по сути одинаковы.

Хорошо, вот сложный... У меня есть сервер разработки с mySQL 5.1.73, на котором я написал функцию для нормализации строки для целей поиска. При перемещении функции в производственную среду та же версия mySQL, та же основная версия ОС (CentOS 6.5), новейшие исправления, та же основная версия ядра и т. д. Функция перестала работать.

Вот функция

  CREATE DEFINER=`user`@`%` FUNCTION `normalize`(str VARCHAR(255)) RETURNS varchar(255) CHARSET utf8
  BEGIN
     DECLARE normstring VARCHAR(255);
     DECLARE i INT;

     SET i = 0;
      SET normstring = '';
      SET str = lower(str);

      loop1: WHILE i < length(str) DO
        CASE substring(str,i,1)
           WHEN 'ä' THEN SET normstring = concat(normstring,'ae');
           WHEN 'ö' THEN SET normstring = concat(normstring,'oe');
           WHEN 'ü' THEN SET normstring = concat(normstring,'ue');
           WHEN 'ß' THEN SET normstring = concat(normstring,'ss');
              WHEN '/' THEN SET i = i + 1; ITERATE loop1;
              WHEN '.' THEN SET i = i + 1; ITERATE loop1;
              WHEN '-' THEN SET i = i + 1; ITERATE loop1;
              WHEN '(' THEN SET i = i + 1; ITERATE loop1;
              WHEN ')' THEN SET i = i + 1; ITERATE loop1;
              WHEN ' ' THEN SET i = i + 1; ITERATE loop1;
              WHEN '\'' THEN SET i = i + 1; ITERATE loop1;
              WHEN '\\' THEN SET i = i + 1; ITERATE loop1;
           ELSE SET normstring = concat(normstring,substring(str,i,1));
        END CASE;
         SET i = i + 1;
     END WHILE;
  RETURN normstring;
  END$$
  DELIMITER ;

На сервере разработки это преобразует «Mönßtär» в «moensstaer», а на рабочем сервере — в «mönßtä».

Замена SET i = 0; и WHILE i < length(str) на SET i = 1; и WHILE i <= length(str) исправляет отсутствующий последний символ, так что результат "mönßtär", но один сервер не должен начинать счет с 0, а другой с 1, верно? И рабочий сервер оставляет все специальные символы нетронутыми.

Я сравнил все глобальные переменные, а не только те, которые явно установлены в my.cnf, и, за исключением настроек часового пояса, пароля и символической ссылки, они равны (да, я должен исправить эти различия, но это не должно иметь ничего общего с моей проблемой, да?)

Есть ли какие-то настройки компиляции, которые могут повлиять на это поведение, или какие-то внешние библиотеки, которые использует mySQL? Вероятно, мне придется найти обходной путь для проблемы - я планирую нормализовать в приложении, а не в базе данных - функция все равно слишком медленная в больших запросах - но было бы неплохо преобразовать существующие данные в базе данных. Но мне действительно любопытно, что вызывает такое странное поведение.

Настройки набора символов на обоих серверах (из работающей среды):

character_set_client........................ utf8
character_set_connection.................... utf8
character_set_database...................... utf8
character_set_filesystem.................... binary
character_set_results....................... utf8
character_set_server........................ utf8
character_set_system........................ utf8
collation_connection........................ utf8_unicode_ci
collation_database.......................... utf8_unicode_ci
collation_server............................ utf8_unicode_ci

person Chris    schedule 02.05.2014    source источник


Ответы (1)


Я считаю, что у вас разные наборы символов между вашей локальной средой и производством. Посмотрите эти статьи о том, как обнаружить Как узнать набор символов сервера по умолчанию в mysql? и как изменить Изменить переменную сервера character_set_server.

person Matas Vaitkevicius    schedule 02.05.2014
comment
Нет, все настройки сервера абсолютно одинаковы с обеих сторон, за исключением переменных, которые я упомянул. Все установлено ту utf8. - person Chris; 02.05.2014