Mysql Мистическая ошибка с кодировкой при записи. Прошу гуру помощи.

Modder

Новичок
Проблема очень нестандартная и странная.

При записи данных (а именно строка с кирилицей в UTF-8) в БД (таблица InnoDB utf8_general_ci) иногда(!) русские буквы записываются вот такими кракозябрами Александр.
Записываемые исходные данные нормальные в UTF-8.
Язык PHP.

Кодировки везде установлены правильные. mysql_set_charset() использую. SET NAMES 'utf-8' тоже пробовал. Но это всё не то. Потому как проблема возникает иногда!

Какие особенности появления этой ситуации я заметил?
  1. Если только что коряво записанные данные сразу же считать из БД и вывести на экран, то они нормальные! Т.е. в том же PHP скрипте при том же подключении к БД.
  2. Почему-то проблема появляется в таблицах, к которым давно (где-то сутки или пол суток) не производился запрос на запись. После этой первой ошибочной записи, все последующие запросы проходят без проблем.
  3. Проблема замечена только в двух таблицах из всех. Таблицы не маленькие по полям. В одной 50 столбцов, в другой - 100. Записей в них не много. Данные - обычные тексты (VARCHAR, CHAR) да числа (INT, MEDIUMINT, TINYINT), пару ENUM, и по-одному TIME и DATE.

Прошу специалистов MySQL большущей помощи!
 

AnrDaemon

Продвинутый новичок
SHOW CREATE TABLE вашатаблица;
Сколько клиентов используют этот же логин-пароль?
Когда вы наконец прекратите использовать php_mysql ?
 

Modder

Новичок
AnrDaemon,
Код:
код удалён
2. Один.
3. Что есть, то есть.
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
Один подразумевается один скрипт, я надеюсь?
Ищите, сколько раз у вас вызывается set_charset/запрашивается "SET NAMES".
Где-то вы выполняете запрос на вставку до того, как установится кодировка соединения.
 

AnrDaemon

Продвинутый новичок
Как вариант, можно попробовать НА СЕРВЕРЕ принудительно установить кодировку по умолчанию для конкретного логина. Точного формата команды, к сожалению, не помню. Давно не приходилось так страдать.
 

Modder

Новичок
AnrDaemon,
1. Смотря что вы подразумеваете под "Сколько клиентов используют этот же логин-пароль?"
2. Один раз вызывается mysql_set_charset('utf8').
Еще пробовал только SET NAMES 'utf8'. И совместно с mysql_set_charset().
И еще пробовал
SET character_set_client = 'utf8'
SET character_set_results = 'utf8'
SET collation_connection = 'utf8_general_ci'

3. Это невозможно.
 

AnrDaemon

Продвинутый новичок
Это и подразумеваю. Сколько клиентов. (Приложений, скриптов... как хотите считайте.)
Надеюсь, вызывается оно немедленно после подключения к БД?
Почему же невозможно? Дайте угадаю, очередной говношаред хостинг?
 

Modder

Новичок
Да, приложение одно.

Да, сразу коннект к базе -> SET NAMES -> выбор БД, а потом уже всякий PHP код с вычислениями и запросам к БД.

"Невозможно" было по поводу:
Где-то вы выполняете запрос на вставку до того, как установится кодировка соединения.
А хостинг неплохой. Вот только бы конкретнее меня направить где это делать.
 

AnrDaemon

Продвинутый новичок
Попробуйте делать в обратном порядке.
Сначала выбор БД, потом "SET NAMES utf8".
Попробуйте везде прямо указывать ресурс подключения.
А по поводу невозможности... Очень даже возможно. Надеюсь, для вас не будет открытием, что расширение MySQL использует пул соединений, и если сервер/логин/пароль совпадают, то новое соединение не устанавливается, а используется существующее? В котором кодировочка оччень даже может несовпадать с вашей...
 

AnrDaemon

Продвинутый новичок
А вообще я сейчас вспомнил, что с подобным сталкивался уже.
Часть сайта работала в cp1251, часть в UTF8. И постоянно то одна то другая начинала выдавать чёрт знает что.
Как решил, уже не помню. Это было 10 лет назад, и у меня больше нет доступа к этому серверу.
Да, точно помню, что как минимум одна часть использовала php_mysql. За вторую не поручусь.
 

Modder

Новичок
AnrDaemon, не помогло. Опять выдало Запор.

Что я ещё пробовал:
Сделал запрос SHOW VARIABLES LIKE "%character_set%" и получил:
Код:
character_set_client = utf8
character_set_connection = utf8
character_set_database = utf8
character_set_filesystem = binary
character_set_results = utf8
character_set_server = cp1251 <-- чужой
character_set_system = utf8
character_sets_dir = /usr/share/mysql/charsets/
Там где делаю SET NAMES 'utf8' рядом добавил запрос на изменение этих переменных:
Код:
SET
character_set_results = 'utf8',
character_set_client = 'utf8',
character_set_connection = 'utf8',
character_set_database = 'utf8',
character_set_server = 'utf8'
Но на решение основной проблемы это не повлияло :(
 

AnrDaemon

Продвинутый новичок
Ищите, где у вас отдельно выставляется character_set_server, раз, и два: ищите, на каких строках таблицы у вас нет явно установленного COLLATION. На конкретных строках.
 

Modder

Новичок
AnrDaemon, нет. Вы меня не поняли. Значение переменных меняется на то что надо (utf8), но на проблему это не влияет. COLLATION везде установлено. Причина не в этом.
 

Modder

Новичок
Ребят, проблема всё ещё не решена. Есть у кого какие-то мысли?
 

AnrDaemon

Продвинутый новичок
mysql.allow_persistent = false
С гарантией запретит использование пула подключений, но если у вас VPS, всё может рухнуть из-за переполнения памяти открытыми подключениями.
 

Modder

Новичок
AnrDaemon, у нас нет доступа к глобальным настройкам.

Кое что вырисовывается:
Путём лога выявилось, что во время ошибочных записей, параметры
Код:
character_set_client = cp1251
character_set_connection = cp1251
character_set_results = cp1251
character_set_server = cp1251
т.е. имеют глобальные значения.

Но это очень странно, т.к. эти же параметры переназначаются при каждом подключении к MySQL вначале PHP скрипта 100%.
Код:
SET
character_set_results = 'utf8',
character_set_client = 'utf8',
character_set_connection = 'utf8',
character_set_server = 'utf8'
Смущает еще настройка init_connect = SET NAMES cp1251, которую нельзя изменить.
Может этот init_connect как-то перебивает свои установки.
 

AnrDaemon

Продвинутый новичок
ЧТООООООО??????????????
Пишите в саппорт, чтобы убрали это дерьмо из настроек MySQL!
А ещё лучше сваливайте оттуда, и не завтра, а прямо сейчас.
 

Absinthe

жожо
Modder, не вижу смысла решать твою проблему (тратить на это время) обходными путями.
Правильное решение ты уже знаешь.
 
Сверху