Artisan Numérique

/développement/bases de données/sgbdr/base de données/mysql/postgresql/ Migrer Drupal de MySql vers PostgreSql

Après avoir migré de Drupal 4.6 à 4.7 (avec quelques pertes de modules dont la coloration syntaxique), je me suis dis, bon, il est temps de laisser notre petit Mysql de côté pour passer à quelque chose de plus solide : PostgreSQL.

Certains se demanderont : "quel est l'intérêt d'une telle migration ?" Pour répondre simplement, j'ai plus confiance en PostgreSQL que j'utilise dans le cadre professionnel que MySql qui a plein de mérite mais que j'ai du mal à appeler une "Base de Donnée". Elle évolue, certes, mais point de vues, des triggers à peine sec, des relations un peu tangantes, et l'argument des performances qui, toujours dans le cadre pro, a été complètement invalidé. Bref, n'ayant pas envie d'avoir 36 bases d'installées et ayant besoin d'un SGBD plus conséquent pour d'autres projets que drupal, j'ai sauté le pas.

La migration des données entre ces deux bases est théoriquement très simple. Dans la pratique il va se poser pas mal de problème. Ce qui suit est donc ma recette de cuisine qu'il faudra adapter à vos spécificités (les modules que vous avez à migrer par exemple).

Création du dump de MySql

J'ai mis pas mal de temps à trouver la bonne formule de mysqldump convenant à PostgreSql. Dans le cas d'une migration drupal, je n'ai besoin que des données dans la mesure où Drupal est fournit avec son scripte de création PostgreSql. Nous y reviendrons. Pour l'heure, voici la commande permettant de créer LE bon dump, en prenant mon_site comme nom de base drupal pour l'exemple :

mysqldump \
-u root -p -tv \
--default-character-set=utf8 \
--quote-names=false \
--add-locks=false \
--complete-insert \
--compatible=postgresql \
--extended-insert=false mon_site > dump.sql

Cette ligne après authentification, vas nous créer un dump en UTF8 (important pour la suite), compatible PostgreSql avec les noms de champs dans les inserts. Ce dernier point est important si comme moi vous avez migré de 4.6 à 4.7 et que les colonnes des tables ne sont pas dans le même ordre entre MySql et le scripte de création de base PostgreSQL de drupal.

Pour limiter les problèmes, j'ai fait un peu de ménage sur la base mySql, éliminant ce qui n'avait pas d'interêt (pour moi) à être migré :

delete from cache;
delete from sessions;
delete from watchdog;
delete from locales_source;
delete from locales_target;
delete from accesslog;
commit;
quit;

Création de la base PostgreSql

La première chose à faire, dans la mesure où il s'agit d'une migration, est de modifier le scripte de création de base de PostgreSql (fichier database/database.pgsql) et d'enlever tous les inserts finaux. En effet, faisant un import, nous n'avons pas besoin de valeurs par défait. Ceci fait, il faut lancer les commandes suivantes (avec mon_user_pgsql un utilisateur déjà créé sous Postgresql) :

dropdb ma_base -U mon_user_pgsql
createdb --encoding=UNICODE -U janus --owner=ma_base_owner mon_user_pgsql
psql -q -f database/database.pgsql mon_site mon_user_pgsql
# la ligne suivante seulement si vous avez installé ce module
psql -q -f trackback/trackback.pgsql mon_site mon_user_pgsql
psql -q -f dump.sql mon_site mon_user_pgsql

Gestion des séquences

Voilà, la base est créé, les données importées avec quelques erreurs, évidement. La plus importante porte sur sequences qui ne sert plus à rien avec PostgreSql. A ignorer donc. Ceci dit, un certain nombre de séquences ont été crées, il va falloir les modifier un peu pour éviter les conflits avec les id existants. La solution est simplement de modifier toutes les séquences pour qu'elles commencent à 1000, ainsi le prochain node créé sera d'id 1000 éloignant tout risque de conflit. Il faut donc lancer psql et coller le code qui suit :

alter sequence access_aid_seq              restart with 1000;
alter sequence accesslog_aid_seq           restart with 1000;
alter sequence aggregator_category_cid_seq restart with 1000;
alter sequence aggregator_feed_fid_seq     restart with 1000;
alter sequence aggregator_item_iid_seq     restart with 1000;
alter sequence authmap_aid_seq             restart with 1000;
alter sequence boxes_bid_seq               restart with 1000;
alter sequence client_cid_seq              restart with 1000;
alter sequence comments_cid_seq            restart with 1000;
alter sequence contact_cid_seq             restart with 1000;
alter sequence files_fid_seq               restart with 1000;
alter sequence filter_formats_format_seq   restart with 1000;
alter sequence locales_source_lid_seq      restart with 1000;
alter sequence menu_mid_seq                restart with 1000;
alter sequence node_access_nid_seq         restart with 1000;
alter sequence node_nid_seq                restart with 1000;
alter sequence node_revisions_vid_seq      restart with 1000;
alter sequence poll_choices_chid_seq       restart with 1000;
alter sequence profile_fields_fid_seq      restart with 1000;
alter sequence role_rid_seq                restart with 1000;
alter sequence term_data_tid_seq           restart with 1000;
alter sequence url_alias_pid_seq           restart with 1000;
alter sequence users_uid_seq               restart with 1000;
alter sequence vocabulary_vid_seq          restart with 1000;
alter sequence watchdog_wid_seq            restart with 1000;

Si psql vous enguirlande pour une vague histoire d'unicode, tapez la ligne suivante :

set client_encoding=latin1;

Paramétrage de Drupal

Il ne reste plus qu'à paramétrer Drupal en modifier le fichier settings qui va bien :

$db_url = 'pgsql://mon_user:son_pass@postgress_ip/mon_site';

Et c'est tout, j'ai migré ainsi 2 sites pour l'instant et sans pertes. Bonne chance :)