Перейти к контенту
  • записи
    4
  • комментариев
    7
  • просмотра
    43 264

Лечим убитую в ноль кодировку


Ritsuka

3 518 просмотров

Разгребал вчера неудачный апгрейд 2.3.6 до 3.0.1. Для начала вводная - как запороть свой форум в ноль в процессе обновления:

 

1) конечно же, не делать бекапа БД,

2) внести до запуска скрипта обновления в conf_global.php строку "$INFO['sql_charset']='utf8';", но не сконвертировать в utf-8 саму базу.

 

Что произойдет в процессе обновления при таком сценарии:

 

Скрипт обновления будет брать данные из старых win-1251 таблиц и вносить в бинарном виде в новые таблицы utf-8. В результате мы получим всю админку в таких вот строках:

(82, 'Показывать версию IPB?', '', 8, 'yes_no', 'ipb_display_version', '', '1', '', '', 1, 38, '', 0, 1, ''),
(83, 'Отключить возможность анонимной авторизации?', 'Если опция включена, то пользователи не увидят опцию "Скрытность" в форме входа.', 8, 'yes_no', 'disable_anonymous', '', '0', '', '', 1, 39, '', 0, 1, ''),
(84, 'Отключить возможность  администраторам видеть анонимных пользователей на форуме?', '', 8, 'yes_no', 'disable_admin_anon', '', '0', '', '', 1, 40, '', 0, 1, ''),

Это уникальнейший образец клинописи - мы имеем в БД поля типа utf-8, в которых хранятся однобайтовые win-1251 символы. Как это раскодировать? Да почти никак! При любой попытке извлечь данные, MySQL формирует на выходе совершенно покореженные последовательности, обратной трансофрмации почти не поддающиеся. iconv from cp-1251 to utf-8 над дампом оставляет все в таком же виде, а если добавить параметр "игнорировать неверные последовательности" (-c), то обрезает строки до первого включения букв "и", "ш" и проч. Штирлиц из windows, равно как и многочисленные онлайн-конвертеры, также пасуют. Попытка сменить типы полей также ничего не дает, т.к. в процессе смены типа MySQL "декодирует" все в кашу прямо на лету.

 

Единственный разумный выход в таком случае - откатиться к бекапу, сначала сконвертировать базу, а затем уже запустить скрипт обновления. А если бекапа нет?

 

Почти 2 часа поисков привели к ответу. Вот запрос, который может извлечь оригинальные данные из этой мешанины:

SELECT CONVERT(CONVERT(CONVERT(field USING cp1251) USING binary) USING utf8) FROM table

 

Чуть изменив его, можно за один заход выполнить "починку" одного поля:

UPDATE table SET filed = CONVERT(CONVERT(CONVERT(field USING cp1251) USING binary) USING utf8)

 

А теперь вспомните, сколько у нас полей и в каком количестве таблиц ;) Тщательный проход по всем таблицам с русскими покореженными буквами (их более 10) для каждого поля я оставляю за вами. Иммет смысл хотя бы теперь сделать бекап - т.к. одна ошибка - например, два раза запустить скрипт на одном столбце - и все снова превратится в кашу.

 

Кстати, что-то можно и не обновлять, а взять в виде дампа из установленного на локали чистого форума (это касается приложений, настроек, групп настроек, репутаций, языковой и некоторых других таблиц).

 

После этой работы, сброса всех кэшей и перепрочтения данных в шаблоны из xml-lang-файла все засияет красивыми русскими буквами.

4 комментария


Рекомендуемые комментарии

Как это раскодировать? Да почти никак!

Сделать дамп, скормить тайгерпеду, перекодировать СРАЗУ ВЕСЬ дамп, залить дамп.

Проверял на полугиговой базе (ноутбук, под денвером), справился за пол-часа.

Вместо тайгерпеда пойдет iconv прямо на сервере. 100-метровый дамп конвертился на шареде секунд 30, сливался и заливался секунд 15; итого чистого времени минута.

Ссылка на комментарий
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, вы соглашаетесь на использование файлов cookie, а также с нашим положением о конфиденциальности Политика конфиденциальности и пользовательским соглашением Условия использования.