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

Зачем мне это?

Причин две:

  • С PostgreSQL я работаю уже лет 10 (тогда же я первый раз отказался от MySQL, не устроила производительность на первой версии черного квадрата), все знаю, умею и все такое. Этой причины, собственно, достаточно.
  • MyISAM неделю назад имел честь развалиться на пустом месте (без ресета сервера, перезапусков MySQL и вообще под нулевой нагрузкой), говорят что это обычное его поведение. Производительность InnoDB (даже с большим кэшом, больше всех данных) меня не устроила (причем, Петр Зайцев на HL++, улыбаясь, заметил, что это для InnoDB нормально, без тщательной настройки нормально не работает, что и дает MySQL-консультантам кусок хлеба).

Совместимость Drupal и PostgreSQL

Drupal Core

Весной 6-й Drupal был в виде версии 6.2, совместимость которой с PostgreSQL была условной: даже core modules работали не все (даже редактирование блоков не работало). К версии 6.5 все известные мне баги поправили, всеми входящими в поставку модулями вроде бы можно пользоваться, я проверил.

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

Помимо этого, используемый эскейпинг спецсимволов приводит к warnings в логе. Это лечится вот этим патчем.

Если ваша установка Postgres имеет настроенную default-клиентскую кодировку, отличную от UTF8, то нужен еще вот такой патч, который явно выставляет кодировку после коннекта к базе данных.

Дополнительные модули

Потребовались правки

Единственный модуль, потребовавший серьезных правок - это Comment Subscribe. Он написан на хардкорном MySQL, с использованием ifnull, if, concat и update table1,table2, что ни в какие стандартно-SQL-ные ворота никак не лезет. Пришлось его изрядно дописать, патч к версии 6.x-1.1 можно взять тут: comment_subscribe-pgsql.diff или в моем багрепорте. Помимо нестандартных SQL-запросов, мой патч правит еще и ошибку, возникающую при установке модуля на сайт, где никаких комментариев еще нет.

Работают из коробки

Протестированы и работают без правок:

  1. Admin Block
  2. GeSHi Filter и GeSHi node
  3. Image, Image assist, Image Attach, ImageMagick Advanced Options
  4. Advanced Help
  5. Site Menu
  6. Taxonomy Menu
  7. CAPTCHA pack, Random CAPTCHA
  8. Tagadelic
  9. Views

Перенос живого сайта с MySQL на PostgreSQL

Формально все очень просто: нужно перенести структуры данных, сами данные, переключить data source в конфигурации и настанет восторг и благолепие.

В реальной жизни все сложнее: прямой перенос структуры таблиц не работает (в деталях не разбирался). Кроме того, c Postgres не работает модуль Backup and Migrate, а быстрый взгляд в его нутро показал, что дешево запустить его не получится.

Альтернативное решение: создать нужную структуру данных самим Drupal-ом, а для переноса данных написать маленький скрипт.

В Drupal свои структуры данных в БД может иметь любой из модулей, поэтому работающая процедура переноса выглядит так:

  1. Разворачиваем Drupal, накладываем необходимые патчи (см. выше), ставим нужные модули, накладываем патчи и на них (если нужно). Собственно, если Drupal уже установлен, то можно попатчить имеющуюся инсталляцию, в этом случае переносимый сайт должен иметь свой каталог в sites/ (не быть default).
  2. Запускаем на этой установке новый Drupal-сайт, использующий Postgres, с произвольным именем сайта (на этапе копирования данных все данные будут заменены на данные с исходного сайта).
  3. Разрешаем все модули, установленные на сайте-источнике. Это создает необходимую структуру таблиц и секвенсоров. Если какой-то из модулей был установлен на исходном сайте ранее, а сейчас отключен, то на новом сайте его нужно включить (и можно сразу выключить - все таблицы уже созданы).
  4. Запускаем мегаскрипт копирования данных (подробнее ниже)
  5. Если используется перевод интерфейса, то экспортируем данные старого сайта и импортируем на новый (данные locale мегаскриптом не копируются т:к: там бывают битые данные, у меня они были).
  6. Копируем содержимое каталога files из старого сайта в новый c сохранением прав на файлы.

Замечание. Если у вас нет shell-доступа к серверу, на котором все установлено, то я не знаю чем вам помочь. Все мои рецепты предполагают полный доступ к серверу.

Мегаскрипт drupal-mysql2pgsql.pl

Сам скрипт можно скачать здесь: drupal-mysql2pgsql.pl.gz (не забудте распаковать перед запуском).

Для работы скрипта требуется Perl 5.x (у меня везде 5.8) с библиотеками DBI, DBD:Pg и DBD::mysql.

Параметры запуска: drupal-mysql2pgsql.pl source-db dest-db, где source-db - имя базы данных MySQL, dest-db - имя базы данных PostgreSQL.

Предполагается, что к обоим базам данных вы имеете доступ без пароля, если это не так, то проще поправить скрипт по месту (добавить username/пароль в вызовы DBI->connect).

Скрипт делает:

  • Получает списки таблиц в исходной базе и в БД назначения, ругается (и продолжает работать) если в БД назначения чего-то не хватает.
  • Стирает все данные из таблиц БД-получателя.
  • Копирует данные из исходной базы в БД-получателя. Не копируются таблицы cache* и locales*, первые не нужны, а вторые копируются штатными средствами (копирование locales отключено т.к. я столкнулся с тем, что Drupal помещает туда данные в неизвестной науке кодировке, что обижает PostgreSQL).
  • Инициализирует все секвенсоры в правильное значение (max(нужный_столбец).

Скрипт предоставляется AS IS, хочется надеяться, что те, кому он действительно нужен - сумеют разобраться в 120 строчках перла.

Comments

Леха,

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

Ну я вообще сабмичу патчи прямо в Друпал, они там доступны. Ну, кроме скрипта миграции.

Про скрипт - постараюсь напрячься и нагадить друпалу в Postgresql group (http://groups.drupal.org/postgresql), тогда пришлю ссылку когда осилю (м.б. сегодня вечером)

Очень полезно! Сам подумываю о переходе на postgre
Спасибо!

Вот же монстер))) Один Тутубалин опять лишил работы сотню друпальных индусов)))))

Вот смотрю я на все Ваши доработки и одного не понимаю: (про то, что охота Вам этим заниматься вместо чего-то иного опустим, это личное дело) - неужели Вас так слабо беспокоит, что за таким пластом элементарно нетестированной кривой функциональности находятся ещё горы неизвестных багов, которые могут рвануть в любой момент?
Или это просто выбор наименьшей из зол в виде доработки хоть какой-то, главное существующей и удовлетворяющей основным Вашим требованиям системы?

Ну вот у меня есть потребность - "контентные сайты". На которых приятно иметь всякие странные фичи, от RSS-ленты и облака тегов, то почтовой нотификации автора комментария об ответе. Ну и всякой прочей хрени - рубрики, сборку из блоков, access control, много всего.

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

А баги, могущие рвануть - ну беспокоят немного. Но я предохраняюсь сколько могу - под бесправным юзером, в jail, авось пронесет. По идее, я рискую только содержимым сайтов, ну так с бэкапу подниму, не барин.

Ну да, это я понимаю, наименьшее из зол ;)

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

Я к нему скорее хорошо отношусь - для пресловутых контентных (с community) сайтов - скорее все работает.
А запуск такого сайта - меньше часа, большая часть из которого уходит на выбор бесплатной "темы".

Т.е. делать свое - это во много раз больше времени, гарантированно. При этом на свое эти бесплатные дизайны просто не будут натягиваться, а для меня это серьезный аргумент против, ибо я не веб-дизайнер совсем, а работа с наемными дизайнерами - это либо геморой во всю задницу, либо очень дорого.

Да, понимаю...
В рамках того, что он умеет out-of-the-box и плюс отлаженные плагины - хорошая позитивная штуковина и для решения своих задач вполне подходит. Самому писать аналогичное же, конечно, ни малейшего смысла нет...

У меня просто была (да и сейчас активна) задача сделать сайт с весьма нестандартной функциональностью и я очень надеялся, что смогу друпал докрутить до этого. 2 недели жизни летом убил на вникание в его особенности, внутренней устройство и работу с ним. С непременной помощью матери тех индусов уже написал пару расширений и...просто в усмерть убило то, что движок, который из коробки же позиционируется как основа сайтов для социальных сетей, не умеет позволять пользователям разрешать или запрещать комменты к своим конкретным записям в блоге. Точной причины и формулировки не помню уже, но просто какая-то совершенно аналогичная функциональность по разделению прав в чём-то другом там уже была, а вот у блога, где казалось бы это совершенно очевидно, - не было. Получается никто там и никогда не продумывал общую концепцию и архитектуру системы, не было по сути никакой внятной её модели, короче над "vision artefact" никто никогда не заморачивался, иначе бы такую элементарную вещь не упустили. Короче, вышло стойкое впечатление, что наклепали в единого Франкенштейна кто что хотел, кое-как соединили вместе и стали всем пудрить мозг: "во чуваки, смотрите, какую крутую штуку мы сделали!". Не серьёзно это. Про неуправляемость аццкого процедурного кода вообще не говорю, там даже сами индусы путаются.
Отличная идея по задумке оказалась в усмерть убита отсутствием элементарной продуманности реализации... Это особенно жестоко выглядело на фоне Джумлы 1,5, с которой тогда недавно хорошо разбирался - вот уж где просто приятно посмотреть на код и архитектуру, всё в лёт понимается и работает... Но, да, у неё функциональность довольно ограниченная. Зато всё задекларированное в манифесте она честно выполняет на все 100%, чем заслужила симпатию и доверие ;)

Короче, разозлился жутко, плюнул, достал Zend Framework и ушёл в свободное плавание ;)) Правда, плыву до сих пор, что тоже, конечно, важно отметить и плыть ещё долго, но берега уже видны, что не может не радовать ;)

А для вполне стандартных контентных сайтов, да, соглашусь на все 100... Вполне возможно им пользоваться.

Движок, по меньшей мере, в 6-ке позволяет разрешать/запрещать комментирование к отдельной записи блога, никаких проблем.

По меньшей мере, у меня на libraw.su такая галка есть, она работает (к каким-то техническим новостям я комментирование запрещал), что будет если зайти прямо по нужному URL - ну не знаю, не пробовал, но думаю что все нормально.

А в настройке content type есть масса настроек про комментирование (что делать с анонимами, default view и т.п.), но вот их конкретный юзер действительно не увидит.

5-ю версию не смотрел (точнее, смотрел, но она меня чем-то не устроила, забыл чем)

> Движок, по меньшей мере, в 6-ке позволяет разрешать/запрещать комментирование к отдельной записи блога, никаких проблем.

С шестёркой (6.3) и ковырялся.
Хм. Может быть сейчас уже неправильно формулирую проблему, забыл, давно это было. Но суть была в том, что столкнулся с явным косяком, где не сделали простую настройку, которую по моему должны были бы сделать в соответствии со здравым смыслом и целями проекта. То ли просто забыли, то ещё что. А может быть я и не нашёл даже, как это другим способом решается - хрен знает, там не сразу врубаешься в возможные настройки.
Короче, пока решил: "пусть пробуют они, я лучше пережду" (с) ;))

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

Уж не знаю какую Вы версию тестировали, но в 5.3 разрешить, запретить или разрешить только чтение комментариев отлично работает. Говорю на примере тут

Спасибо за статью! Грамотно и ответственно подошел к исследованию вопроса. Мы уже пару лет пользуем Drupal на PostgreSQL, еще с 4.х версий, на 6.х все вроде тоже работает, причем без патчей. Правда, модуль Comment Subscribe не пользовали, но касательно длины строки - действительно, ругается. Боремся, как умеем :)

Проблема с длиной поля решена заменой поля на blob, комит в 6ку прошел, но нужно еще в 7ке решить в связи с http://drupal.org/node/278592

Что-то ссылка какая-то неправильная, перебрасывает на голову drupal.org

Пардон, со второго раза получилось. Не знаю что это было.