Архив сообщений в RSS-транспорте и веселый юникод-2

Да, я снова вляпался в utf8mb4.

Прежде всего по транспорту: захотелось иметь возможность получать по запросу последние несколько сообщений – видел такое в каком-то RSS-транспорте. Отправляешь цифру – получаешь запрошенное число новостей. Расширил таблицу sent, чтобы хранить не только хэши, а и “живые” данные. Сделал обработку команд для получения новостей, вроде все ок, раскатал на сервере – и на обновлении данных с одной из лент получил облом: incorrect string на вставке в базу. Благо опыт уже есть и догадался быстро: после проверки таблиц в базе вспомнил, что в python-mysqldb utf8mb4 заменяется на простой utf8 (кстати, а зачем?), а utf8 в современных реалиях не способен хранить смайлики вида “одноногие темнокожие геи-азиаты-трансвеститы, идентифицирующие себя как…”. Можно было попробовать убрать проверку на utf8mb4 в либе, что могло привести к непредсказуемым результатам, плюс потребовало бы править либу на всех серверах. Альтернативой стало решение заменить все 4-байтные символы по мотивам этой ссылки. Все заработало как надо.

Ну, почти. Я уже натыкался раньше на то, что при выборке из базы данных в функции для проверки того, зарегистрирована ли лента получал некорректные результаты. Тогда это решил переводом функции на работу с массивом вместо базы – массив все равно уже есть, плюс это порядком сократило нагрузку на базу:

На сейчас такой фокус не прокатил бы – другая таблица, которую тащить в память и переделывать всю логику работы в скрипте с ней ну никак не хотелось. Сделал костыльный вариант с закрытием курсора – так работало (ссылка для истории). Сходу идей о правильной реализации не было, но в голове еще сидели воспоминания о некоторых недавних тредах на ЛОРе про неизвестные мне ранее стороны мускуля. В итоге создал свой тред, где дали отсылку на уровни изоляции транзакций. Почитал, немного вник, поправил скрипт, вроде все заработало. Хотя до сих пор не ясно несколько моментов – поначалу вроде сделал все правильно, но получил старое поведение (ок, возможно где-то недосмотрел что-то). Плюс, например, консоль мускуля. Делаем SHOW VARIABLES LIKE '%ISOL%'; – там у нас дефолтный REPEATABLE-READ. Но после коммита транзакций после обновления лент в транспорте я таки начинаю видеть изменения. В чем разница? Update: нашел в чем разница: по этой ссылке (которая, в свою очередь, является отсылкой из описания дефолтного REPEATABLE READ) есть весьма наглядная схема, где показано, каким образом видны данные при нескольких сессиях. Вкратце: в моем случае можно не переключаться на более “легкий” уровень изоляции, а делать коммит перед вычиткой (в том случае, если автокоммит отключен), тогда все будет нормально. Что касается консоли и вопроса выше – в консоли как раз таки и включен автокоммит, поэтому все изменения я вижу сразу:

MariaDB [jabberes]> SHOW VARIABLES LIKE '%AUTOCOMMIT%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| autocommit | ON |
| wsrep_retry_autocommit | 1 |
+------------------------+-------+
2 rows in set (0.004 sec)

Так или иначе, архив сделан, получать сообщения можно. Дальше пришла идея с поиском по архиву, что и сделал в следующей (1.10) версии. Попутно добавились несколько команд и алиасов для лент, а по просьбе одного из пользователей сделал зачистку от старых записей в базе настраиваемой через конфиг – на случай, когда хочется архив новостей побольше.

Да, а еще чуть поднял разрешение для datetime в базе до десятых долей секунды. Раньше иногда напрягало то, что сообщения могли идти в базе непоследовательно, сейчас такой вариант исключен, поэтому отправив “1” ленте мы гарантированно получим одно последнее сообщение.

Добавить комментарий