Кодирование хранимого значения СУБД с помощью конечного стража для обнаружения усечения / повреждения; профи? минусы? альтернативы?

Недавно группа, которую я поддерживаю, столкнулась с проблемой со значением, которое они хранили (и извлекали) из базы данных MySQL. Они говорят мне, что хранили значение с разделителями-запятыми в столбце (VARCHAR(255)?).

Они сообщили, что их значение было молча усечено (их код в основном Ruby, некоторая другая обработка выполняется в Scala) и попросили нас удвоить размер этого столбца.

Естественно, я предложил, чтобы они нормализовали... хранили каждое из этих значений (ранее разделенных запятыми) в отдельных строках и использовали SELECT для извлечения набора (который раньше был бы одной строкой). Они отодвинулись и настаивают на том, что им никогда не нужны эти разделенные значения для любого другого вида запроса к базе данных, и что им никогда не понадобится, чтобы поле было шире, чем новая (512) ширина.

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

Мои вопросы:

  • Как их данные молча усекались? Есть ли какие-то настройки в MySQL или в их драйверах БД для Ruby, которые подавляют ошибку?
  • Каковы плюсы и минусы этого терминированного значения по сравнению с более нормализованным подходом?
  • Есть ли какой-либо термин искусства или псевдоним для этого термина прекращено значение?
  • Что может быть лучше для решения их проблемы?

2 ответа

Если в вашей базе данных не включен строгий режим, MySQL будет обрезать строки, которые не вписываются в varchar(n) столбец и выдают только предупреждение об усечении. Если вы включите строгий режим, то в таких случаях вы получите ошибку (и больше душевного спокойствия).

Большая проблема с вашим значением Sentinel заключается в том, что они проверяют его только на чтение. Это означает, что они могут (и, безусловно, будут) хранить неверные / поврежденные данные, но не будут знать о проблеме до тех пор, пока не попытаются распаковать эти данные; но когда они распаковывают данные, будет слишком поздно, чтобы восстановить то, что было потеряно.

Есть несколько лучших подходов:

  1. Правильно нормализованные таблицы.
  2. Включить строгий режим в MySQL.
  3. Предварительная вставка или предварительное обновление проверки длины.
  4. Если они на самом деле используют Rails, то, возможно, они могли бы использовать serializeавтоматически конвертировать данные в / из (cringe) YAML; в этом случае им придется использовать больший тип столбца TEXT, и у них все еще будет проблема с усечением.

Таким образом, 2 и 3 должны быть выполнены немедленно, 1 будет лучшим, 4 может быть средним вариантом, если они боятся (или не понимают) нормализации.

На самом деле довольно просто "пропустить" усечение в MySQL, но также довольно легко заставить его строго уведомлять вас, вместо того, чтобы пытаться быть полезным.

Из руководства MySQL:

Если режим строгого SQL не включен и вы присваиваете столбцу CHAR или VARCHAR значение, которое превышает максимальную длину столбца, это значение усекается, чтобы соответствовать, и генерируется предупреждение. Для усечения непространственных символов вы можете вызвать ошибку (а не предупреждение) и запретить вставку значения, используя строгий режим SQL. Смотрите Раздел 5.1.6, "Режимы SQL сервера".

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

Другие вопросы по тегам