Skip to Content

PostgreSQL

Postgresql HA Q

Апгрейдил тут постгрес с 8.4 на 9.1, типа давно пора.

Поднял в соседней виртуальной машине (jail-е, точнее) второй сервер БД, отнес все туда, запустил postgresql-relay, вроде все работает, стал постепенно апгрейдить.

Где-то через час заметил, что PHP-шные (друпальские) сайты - работают (медленно), а перловые - нет. Ну так, из общих соображений, PHP ходит через локальный сокет, а если не вышло - через localhost:5432 (а там у меня relay), а DBI::Pg, если hostname не указали, ходит только в /tmp/.s.PGSQL... и все.

Отсюда вопросы, раз уж всплыла тема:

  1. А есть ли такой постгресовый proxy, который и локальный сокет эмулирует тоже?
  2. А есть ли такой постгресовый proxy, который на psql -l нормально отзывался бы, показывая бы нечто, согласно своей конфигурации?
  3. А есть ли такой простой постгесовый proxy, который умеет делать fallback на запасной сервер? Ну вот был master-slave, мастер сдох, а жить то надо.
Я знаю про PL/proxy, но идея со stored procedures меня совершенно не радует, у меня написанные мной за 15 лет скрипты, у меня написанные совершенно не мной всякие штуки, это банальные 'select a from b where c' и переписывать их нет никаких возможностей.

Drupal6 -> Drupal7

В очередной раз подошел к снаряду по имени Drupal7. Имею сказать:

1. Если у вас PostgreSQL, то даже Drupal 7.9 (текущий) не сможет поапгрейдиться гладко. Оно пытается сконвертировать поля типа text в тип bytea, а в PostgreSQL 9.1 (другие не пробовал) автоматического преобразования этих типов нет.

Лечение (применяется к базе PostgreSQL до апгрейда):

  1. CREATE OR REPLACE FUNCTION text2bytea(text) RETURNS bytea AS
  2. $BODY$
  3. begin
  4.  return convert_to($1,'UTF-8');
  5. end;
  6. $BODY$
  7. LANGUAGE 'plpgsql' VOLATILE;
  8. CREATE CAST (text as bytea) with function text2bytea(text) as implicit;
Может я тут что и перепутал и as implicit не нужно, но работает и "базовый" сайт (core modules) переносит.

2. А вот в том, что касается contributed modules - счастья у меня нет:

ljcomments2drupal

LJ Sync за несколько дней эксплуатации совершено опротивел. Изрядную часть его достоинств я почикал, оставил только импорт комментариев, но и с этим оно справляется не на пятерку:

  • Комментарии с пустым сабжектом - так и оставляет пустым, в результате RSS без ссылок, список свежих комментариев - тоже без них. Поправить недолго, но...
  • Уведомления о ЖЖ-комментах приходят дважды, один раз из ЖЖ, второй раз из моего блога. Это, типа, фича.
  • Работает долго т.к. каждый раз разбирает многомегабайтный XML в котором весь мой ЖЖ за все времена.

Друпал - усугубляем бардак с алиасами

У меня исторически имеет место бардак с именами URL: все они порождены из заголовков записей, но

  • В большинстве случаев дефис заменен подчеркиванием (и в заголовок данной записи специально добавлен дефис, чтобы проверить).
  • В некоторых случаях дефис оставлен дефисом, это привет MovableType, настроенного по умолчанию из лета 2008 года.
  • В некоторых случаях дефис вовсе скушали, какая-то версия MT заменяла конструкцию ' - ' не на '___' и не на '_-_', а на '__'.
Причем, как выяснилось по логам, есть внешние ссылки на разные представления одного и того же, уж не знаю откуда они взялись.

Проблема лечится вот таким вот SQL-оператором (regexp_replace() - чисто постгресовское, MySQL-аналог найдите сами. Это только для nodes, с таксономией в моем случае проблем нет совсем.

  1.  insert into url_alias(src,language,dst) select src,language,regexp_replace(dst,'-','_','g') from url_alias where src like 'node%' and dst like '%-%';

Миграция Movable Type -> Drupal. Синхронизация с ЖЖ, наведение марафета, финал

Руководство по прыжкам с парашютом, издание второе, исправленное

Теги/рубрики/категории

При миграции контента с тегами и категориями был предложен такой метод

  1. Делаем категории тегами (чтобы не заполнять значения).
  2. Импортируем.
  3. Меняем тип таксономии категории на "Multiple select/Mandatory".
  4. Правим пути к категориям.

Увы, но где-то на этом пути теряются категории у изрядной части записей и теги - у единиц, повторный импорт лечит только частично. Я подозреваю, что крышу рвет, если есть теги, совпадающие с категориями, но не уточнял.Теги портит LJ Sync, пришлось его еще шашкой....

Пришлось написать скрипт (качать тут), который правит эту проблему, анализируя таблицу mt_posts самостоятельно (запускать после импорта, когда все теги/категории уже созданы).

Миграция MovableType -> Drupal. День 1: постановка задачи

Предуведомление

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

Короче, не нравится - не читайте :)

Статус этих записок

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

Зачем переезжать

Моя причина очень простая: мне надоело поддерживать две платформы (Drupal и Movable Type). При этом, по комплексу свойств Друпал побеждает, а значит с MT пора прощаться. А новогодние каникулы - хороший повод позаниматься чем-то полезным.

PostgreSQL 8.4.0 UTF conversion

Представим себе типичную ситуацию: есть таблица в UTF8, какой-то клиент вводит туда данные, работая, скажем, в кодировке windows-1251 и вводит, например, знак номера.

Потом другой клиент, работая уже в KOI8-R сделает по этой таблице SELECT и вместо результатов выборки увидит

ERROR: character такой-то of encoding "UTF8" has no equivalent in "KOI8R"

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

Начиная с 8.1.4 я делаю патчи для этой функциональности: вместо выдачи ошибки и прекращения запроса невыводимый символ просто меняется на пробел. Дошла очередь и до 8.4.0:

Патчи для старых версий тоже можно брать у меня:

Стандартный дисклеймер: если вы не знаете что такое "патч", то он вам не нужен.

P.S. Своего мнения про 8.4 пока не имею, сформирую - напишу. Пока тестирую, в бой выставлять рановато. pg_migrator не понравился, слишком уж много дополнительных условий, в которых я не уверен.

Drupal + PostgreSQL (опять, да)

Передайте разработчикам <программы такой-то>, что лучше бы они ее больше не разрабатывали

Похоже, что тестировать варез становится просто немодно, чем дальше, тем больше огорчаюсь.

Про моральных индусов я уже плакался, но там речь шла о 3rd-party модуле, а сейчас удивляюсь прямо таки на Drupal core. Удивляюсь, соответственно, сильнее, ибо для core поддержка PostgreSQL заявлено, а вот с тестированием... впрочем я повторяюсь.

Drupal Comment Notify (опять)

Drupal закричал мне, что у меня все устарело, нужно срочно апгредиться. Ну, как он любит. Поапгрейдил, в том числе и Comment Notify до версии 1.2, про натягивание которого на Postgresql я уже писал.

Поапгрейдив, имею вопрос: а что, в MySQL у поля написано NOT NULL, то там самостоятельно появится еще и DEFAULT ...? Потому что я не верю, что автор Comment Notify его совсем не тестирует, однако в нем:

  • В таблице заводится крайне полезное поле, позволяющее не слать повторные нотификации если комментарий редактировался. Но оно NOT NULL и без DEFAULT.
  • Вставка в эту таблицу делается без инициализации данного поля.

Патчить можно или сам модуль или процедуру инсталляции/апгрейда. Точнее, без правки .install никак не обойтись, поэтому вот минимальный патч, который превращает Comment Notify 1.2 в работающий под Postgresql (про MySQL ничего не знаю, не проверял):

comment-notify-1.2-install.diff.gz

Если вы переезжаете с Comment Subscribe, то нужно выполнить еще две SQL-команды (чтобы уже разосланные нотификации не рассылались повторно):

UPDATE comment_notify set notified=1;
UPDATE comment_notify set notify=1 where cid in (SELECT cid FROM z_com
mentsubscribe WHERE subscribe > 0);

Drupal Comment Notify + PostgreSQL = ....

Продолжаю воспитание модулей Drupal. В этот раз под горячую руку попал Comment Notify, захотелось разобраться, почему автор Друпала выбрал именно его.

Как оно регулярно бывает с Друпалом, этот модуль с PostgreSQL тоже не работает. И почему я не удивлен.....

Вместе с тем, количество требуемых изменений очень невелико и патч вполне компактный. Проблемы обычные: ifnull, concat, "UPDATE table LEFT JOIN table2".

comment-notify-1.1-pgsql.diff.gz

Продолжаю воспитание модулей Drupal. В этот раз под горячую руку попал Comment Notify, захотелось разобраться, почему автор Друпала выбрал именно его.

Как оно регулярно бывает с Друпалом, этот модуль с PostgreSQL тоже не работает. И почему я не удивлен.....

Вместе с тем, количество требуемых изменений очень невелико и патч вполне компактный. Проблемы обычные: ifnull, concat, "UPDATE table LEFT JOIN table2".

comment-notify-1.1-pgsql.diff.gz

Drupal Comment Subscribe 6.x-1.2 и PostgreSQL

Я тут в соседнем микроблоге уже нажаловался на моральных индусов. А в этом блоге - конструктив.

comment_subscribe-12-pgsql.diff.gz

Накладывается поверх чистой установки (или апгрейда) модуля Comment Subscribe версии 6.x-1.2. Исправляются несовместимости с PostgreSQL плюс немножко еще:

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

Патч сейчас засабмичу автору, посмотрим на результат второй итерации....

Drupal + PostgreSQL + comment_subscribe

В моих правках к модулю Comment Subscribe для его работы с PostgreSQL обнаружилась бага: если кто-то отвечал в треде несколько раз, то он может получить несколько писем-уведомлений, когда ответит кто-то еще.

С чувством невыразимого облегчения


lexa@www:~# cd /var/db/pkg/
lexa@www:/var/db/pkg# pkg_delete -f *mysql*

Натягивание Drupal на PostgreSQL

Несмотря на мой исходный пессимизм, появившееся неделю назад острое отвращение к MySQL заставило меня расчехлить напильник и наконец доработать Drupal 6.5 до устраивающей меня совместимости с PostgreSQL.

В настоящую минуту один из моих сайтов уже работает под PgSQL со всеми нужными мне модулями, а остальные будут переведены после нескольких дней тестирования первого.

Несмотря на мой исходный пессимизм, появившееся неделю назад острое отвращение к MySQL заставило меня расчехлить напильник и наконец доработать Drupal 6.5 до устраивающей меня совместимости с PostgreSQL.

В настоящую минуту один из моих сайтов уже работает под PgSQL со всеми нужными мне модулями, а остальные будут переведены после нескольких дней тестирования первого.

Drupal + PostgreSQL = еще один патч

В процессе попыток использования Drupal 6.5 с PostgreSQL выявилась мелкая неприятность: интерфейс к постгресу не вполне правильно эскейпит строки со спецсимволами. Постгрес хочет, чтобы ему давали в виде E '\r\n', а Друпал дает без E. Пожелание это новое, появилось в какой-то из восьмых версий, на функциональность не влияет, но противно забивать лог неизвестно чем.

Патч прилагается: drupal65-pgsql8x-patch2.diff.gz

В Drupal тоже настучал, глядишь добавят в 6.6 или там в семерку (до кучи сдал туда же предыдущий патч, от него тоже никакого вреда, кроме пользы).

Drupal + PostgreSQL: вторая попытка

Внезапно возникшее отвращение к MySQL (каменты тоже читать) заставило посмотреть на связку Drupal + PostgreSQL еще раз.

Если аккуратно, то все работает. Т.е. к core у меня и раньше претензий не было, а сломался я в модуле Backup-Restore. Сейчас - с минимальным набором 3rd-party (Tagadelic, Inline Tags, Site Menu, Pathauto, Transliteration) все вроде живет. Точнее, Transliteration не транслитерирует, но оно этого и с MySQL не делало, но всяких сообщений об ошибках и прочих безобразий пока нет, за исключением одного:

У меня на разных инсталляциях PostgreSQL стоит разный default client_charset. Где-то KOI8, где-то CP1251, но нигде не стоит UTF8 (базы все, естественно, в UTF). Это все по соображениям совместимости - много где живут скрипты многолетней давности и вставлять в каждый из них set client_charset мучительно.
Drupal о такой подлости не подозревает (MovableType - подозревает и выставляет), что лечится простым патчем:

drupal64.pgsql.diff.gz

Drupal + PostgreSQL = фиаско

Умный Беляев не ошибался: Drupal с Postgresql не живет. Увы.

Последней каплей оказалась попытка побэкапить MySQL-ный вариант сайта и все-таки отнести его на Postgres (я его лучше знаю, лучше умею бэкапить, лучше умею настраивать и так далее).
Увы, Backup and Migrate получает список таблиц для бэкапа через 'SHOW TABLE STATUS', а это место, понятное дело, в постгресе не работает.

Впрочем, справедливости ради, на маленькой базе на MySQL оно работает в пару раз быстрее за счет query cache. А большой базы у меня пока нет.

Drupal и PostgreSQL

Попытка использовать Drupal совместно с PostgreSQL 8.3 с грохотом провалилась. Основная функциональность работает, но стоит копнуть чуть глубже и налетаешь на проблемы. Например на эту, судя по переписке там ниже - проблема не только в блоках (ну и вообще, идея делать join по двум полям, одно числовое, а второе - какое-то, несколько потрясла)

Довольно печально, кстати, смотреть, как ошибка найденная 2 месяца назад - не поправлена, хотя с тех пор было 1 или 2 релиза.

Натыкался и на проблемы с форматом даты, при попытке поставить русский формат (DD.MM.YYYY) оно прямо в таком формате и в базу хочет записаться.

Еще про Drupal: словил невнятный подземный стук. Смена языка пользователем сначала работала, а потом почему-то перестала, работает только смена в системе в целом. В том же месте другие грабли: экспорт строк для перевода экспортирует только те строки, которые встречались системе при работе, нормального способа экспортировать все на свежеустановленной CMS - не нашел.

Резюме. Несмотря на то, что система мне очень понравилась, впечатление пионерской поделки временами перебивает все прочие.

Прогресс - зло!

Потерял полдня, прежде чем сложил все кубики в пирамидку (и то, не уверен что правильно).

Нужно: получить PHP5 с клиентом PosgreSQL (всякие прочие extensions на вырост), в виде апачевского модуля, все происходит под FreeBSD7.

  • Apache 1.3, все собираем из ports - не работает. SIGSEGV где-то внутри инициализации pthreads, хотя никому из участников эти threads нафиг не нужны и непонятно кто их приволок. /usr/local/bin/php - работает.
  • Apache 1.3, собираем PHP --with-pgsql - все работает, пока нет загружаемых extensions. Как только появляется хоть одно - падаем.
  • Apache 2.2, собираем все из ports - работает.
  • FreeBSD6 в этот раз не пробовал, но когда в прошлый раз пробовал - работало.

Получается, из-за скромненькой фигулинки всем проектам показан переезд под Apache2 ? И mod_perl2 ? А mod_perl2 небось тоже не работает ?

MySQL не предлагать. С Apache я совладаю как-нибудь, а два сервера баз данных в моей жизни - это уже перебор. Снести семерку тоже не предлагать, UFS2 на терабайтных FS - уже перебор.

FreeBSD: UTF-8 russian collate (вторая попытка)

Несколько дней назад я опубликовал исходник LC_COLLATE для кодировки ru_RU.UTF-8 для использования в FreeBSD. Там же я обещал, что если понадобится не "универсальная" сортировка, а такая же, как в FreeBSD, то сделаю и ее, а обещания нужно выполнять.

Помимо этого, старый вариант не имел вообще никаких шансов попасть в FreeBSD (причины этого мне объяснил Андрей Чернов: нарушается FreeBSD-шное правило, что большие буквы отдельно, а маленькие - отдельно), а новый - такие шансы еще не потерял.

FreeBSD: ru_RU.UTF-8 LC_COLLATE

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

Наш читатель, Александр Загребин, любезно поделился исходником locale LC_COLLATE для FreeBSD, который лечит проблему сортировок для ru_RU.UTF-8. Я немножко поправил Makefile, чтобы результат ставился прямо поверх системного файла, выкладываю (с согласия автора, естественно) это для всеобщего использования:

Update
Я сделал работу над ошибками, обновленный вариант (с тем же URL) и комментарии к нему берите здесь.

Лечение проблем LC_COLLATE при использовании UTF-8 в PostgreSQL под FreeBSD

Как я уже писал, при использовании UTF-8 в PostgreSQL под FreeBSD результат больно бъется: сортировка русских букв неправильная (касается это только буквы ё). Причина - в кривой locale под FreeBSD (и Mac OS X).

Естественно, на эти грабли уже много раз наступали и для PostgreSQL 8.1 существуют патчи имени Palle Girgensohn, позволяющие использовать IBM-овскую библиотеку ICU в которой все сделано правильно для безумного количества языков.

Больно ударился об UTF-8

Уже много лет я насаждаю UTF-8 как кодировку хранения всяких текстов. С переменным успехом, но большинство баз данных в округе - вроде перевел. На третий день Зоркому Глазу подсказали, что в доме нету пары стен.

Берем русские тексты с буквой ё. Да, их немного, но они есть. Заливаем в Postgresql, начинаем сортировать и делать всякие прочие upper/lower преобразования. Видим... плохое видим:

lexa=# SELECT * from aa order by bb;
 bb
----
 еа
 ее
 ея
 её
(4 rows)

При этом, если база в кодировке KOI8 (попробовал) или cp1251 (не пробовал, но должно быть так же), то все отлично.

Причина выяснилась, оказалась банальной:

$ uname -v
FreeBSD 6.2-RELEASE-p9
$ ls -l /usr/share/locale/ru_RU.UTF-8/LC_COLLATE
lrwxr-xr-x  1 root  wheel  28 Dec  3 23:30 /usr/share/locale/ru_RU.UTF-8/
LC_COLLATE -> ../la_LN.US-ASCII/LC_COLLATE

Надо сказать, что такого свинства в 21-м веке я как-то не ожидал.

Да, чтобы два раза не вставать. В Леопарде локаль такая же

Postgresql 8.3b1 UTF conversion patch

Я уже писал (а потом писал еще), что, в силу многих причин, стандартное поведение PostgreSQL при конверсии из UTF-8 в однобайтовые русские кодировки меня не устраивает. Ну нельзя обижаться и ломаться в ситуации, когда мы, например, импортировали текст в кодировке windows-1251 с кавычками-лапками, а показать хотим его в KOI8-R, где кавычек-лапок нет.

Патч для версий 8.1.4-8.2 можно найти по ссылке выше. Для 8.3-beta1 он не подходит, поэтому пришлось сделать новый: postgres-8.3.b1-conversion.patch.gz

Это хак, правильность которого я обсуждать не желаю, ибо идеологически он неверен, но без него не работают старые приложения.

MT: перенос темплейтов (боремся с чужой жадностью)

Разработчики MovableType, судя по всему, предполагают, что вся работа с темплейтами должна происходить внутри интерфейса системы. В ряде сортов колбасы потребности, очевидно, нет. В частности, нет способов сделать:
  • backup/restore только темплейтов;
  • использование темплейтов одного блога для другого;
  • редактирование внешним редактором, а не встроенным уебибожеством.

Понятно, что разработчики плагинов в стороне не остались и Mark Carey предлагает готовое решение в виде плагинов Template Exporter и Template Installer. Есть правда одна закавыка, Installer бесплатен для некоммерческого использования, а вот за Exporter автор хочет $97.

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

  1. <b>pg_dump -E UTF8 -F c -t mt_template movabletype | ssh server pg_restore -d movabletype -c </b>

Это, естественно, для инсталляции MT на PostgreSQL. C MySQL я практически не знаком, но уверен что средства побэкапить-поресторить табличку есть и там. Для переноса Archive Mapping нужно таскать табличку mt_templatemap. Конечно, мы неявно предполагаем что:
  • blog_id на двух инсталляциях совпадает
  • нужно перенести все темплейты всех блогов.

Естественно, для чуть более сложной задачи: экспортировать не все, а только для одного блога, экспортировать в файлы (и импортировать из них) придется попрограммировать. На первый взгляд, экспорт в формате, пригодном для импорта через Template Installer должен уложиться строчек в 20.

Syndicate content


.