Migrujemy Drupala z bazy danych MySQL na PostgreSQL
Baza danych MySQL jest bardzo popularna, dostępna na licencji GPL lub komercyjnej. Praktycznie każdy hosting oferuje właśnie ten typ baz danych pomijając groźnego konkurenta jakim bez wątpienia jest PostgreSQL dostępny na licencji BSD.
O różnicach, podobieństwach, mocnych stronach jak i słabościach tych dwóch baz danych można przeczytać na WikiVS. W tym wpisie skupię się na praktycznym procesie migracji z PostgreSQL na MySQL oraz odwrotnie.
Największym problemem w migracji pomiędzy tymi bazami jest struktura tabel. O ile posiadamy taką samą strukturę w bazie MySQL oraz PostgreSQL to możemy bez problemu przenieść dane. Niestety sprawa struktury nie wygląda tak wesoło jak przenoszenie danych. Mamy dwa wyjścia z sytuacji – przepiszemy tabele z jednego systemu na drugi lub użyjemy instalatora dla konkretnego programu który chcemy przenieść na inny typ baz danych. Do tej pory przeprowadziłem dwie migracje jedną Drupala oraz drugą Django. Jedna w stronę PgSQL druga w stronę MySQL. Dzięki temu, że Drupal jak i Django posiadają instalatory bazy danych problem struktury został rozwiązany.
Na początku proponuję zrobić backup obecnej strony, zwłaszcza bazy danych (MySQL). Następnym krokiem powinno być założenie bazy danych na którą chcemy przenieść naszego Drupala (PostgreSQL). Kiedy mamy już wszystko przygotowane najwygodniej będzie stworzyć tymczasową subdomenę, bądź katalog wskazujący na stronę z Drupalem. Wszystko dlatego, że musimy postawić czystą instancję Drupala wraz z wszystkimi modułami które są zainstalowane na przenoszonej stronie z jedną uwagą – instalacja odbywa się już na bazie do której migrujemy (PostgreSQL). Cały zabieg ma na celu stworzenie struktury tabel w nowej bazie danych.
Kiedy przeprowadzimy instalację na docelowej bazie danych i zainstalujemy wszystkie modułu które są zainstalowane na stronie – chodzi o samą instalację. Proces konfiguracji możemy pominąć, ponieważ dane zostaną przeniesione ze źródłowej bazy danych (MySQL).
Teraz nie pozostaje nic innego jak wyczyszczenie tabel z bazy danych PostgreSQL i przerzucenie danych z MySQLa. Eksport danych można wykonać na przykład przez phpMyAdmin lub też w konsoli używając programu mysqldump (opcja której jestem zwolennikiem).
-
mysqldump -n -t -u użytkownik_MYSQL (-p) baza_adnych > plik.sql
Parametry -n i -t odpowiadają za nietworzenie bazy danych i strukury tabel, natomiast parametr -p informuje mysqldump że autoryzacja powinna odbyć się z hasłem i program zapyta nas o hasło użytkownika. Mając już zrzut danych należy go zaimportować do Postgresa.
Użytkownik Alex Tutubalin napisał specjalny skrypt w perlu który zrobi całą czarną robotę (związaną z przenoszeniem danych) za nas.
-
#!/usr/bin/perl
-
# Copyright (C) 2008, Alex Tutubalin, lexa@lexa.ru
-
-
## NOTES
-
## 1. Backup your existing MySQL-based drupal installation
-
## 2. Apply PgSQL-related patches (blog.lexa.ru/programmirovanie/web/drupal)
-
## 3. Create new drupal instance (PgSQL based), dump them to create clean PgSQL db dump
-
## 4. Activate same modules and themes in new instance as in old one
-
## 5. Run this script drupal-mysql2pgsql.pl old-mysql-db-name new-pgsql-db-name
-
## NOTE: you need passwordless account in both databases to run this script
-
## 6. Copy localized strings by standard Drupal way (export/import) b/c on MySQL locale
-
## can have incorrect symbols
-
-
use DBI;
-
use Data::Dumper;
-
use strict;
-
-
-
$srcdb->do("SET names \'utf8\'"); #character_set_client = utf8");
-
-
-
my $srctables = $srcdb->selectall_arrayref("show tables");
-
my $desttables = $destdb->selectall_hashref("select * from pg_tables where not tablename ~\'^(pg_|sql_)\'","tablename");
-
-
my $seqlist = $destdb->selectall_arrayref("select relname from pg_class where relkind=\'S\'");
-
my $seqmap;
-
foreach my $s(@$seqlist)
-
{
-
my $seqname = $s->[0];
-
if ($seqname=~/^(.*)_([a-z]+)_([a-z]+$)/)
-
{
-
my $item;
-
$item->{seq}=$seqname;
-
$item->{field}=$2;
-
my $table = $1;
-
{
-
}
-
else
-
{
-
}
-
}
-
}
-
-
$destdb->{AutoCommit}=0;
-
-
foreach my $t(@$srctables)
-
{
-
my $table = $t->[0];
-
{
-
next;
-
}
-
clear_table($destdb,$table);
-
next if $table=~/^cache/;
-
next if $table=~/^locales/;
-
my $cnt = copy_table($srcdb,$destdb,$table) unless $table=~/^cache/;
-
init_seq($destdb,$table,$seqmap->{$table}); # if (exists $seqmap->{$table});
-
}
-
-
$destdb->commit;
-
-
-
sub init_seq
-
{
-
my ($db,$table,$list)=@_;
-
for my $item (@{$list})
-
{
-
my $val = $ref->[0]->[0];
-
if ($val)
-
{
-
}
-
}
-
-
-
}
-
-
sub clear_table
-
{
-
my ($dbh,$table)=@_;
-
}
-
-
# hope, field set in both databases is same
-
sub copy_table
-
{
-
my ($srcdb,$destdb,$table)=@_;
-
my $slf = $srcdb->prepare("select * from $table limit 1");
-
my $rec1 = $slf->fetchrow_hashref;
-
$slf->finish;
-
my $sel = $srcdb->prepare("select * from $table");
-
my $cnt = 0;
-
while (my $data = $sel->fetchrow_hashref)
-
{
-
$cnt++;
-
}
-
$ins->finish;
-
$sel->finish;
-
}
Skrypt uruchamiamy z dwoma parametrami - pierwszy to nazwa źródłowej bazy danych w MySQL-u a drugi to nazwa docelowej bazy danych w PostgreSQL-u.
Oczywiście nie jest to rozwiązanie dedykowane pod migrację Drupala - jest to uniwersalny skrypt do przenoszenia danych MySQL -> PostgreSQL.
Niestety do odwrotnego procesu skryptu już nie można wykorzystać - jednak po co przenosić się z PostgreSQL-a ;-)
To byłoby na tyle jeżeli chodzi o zmianę bazy danych.


kwiat
pon., 08/11/2010 - 16:25
odnośnik
mysqldump posiada opcję --compatible:
o --compatible=name
Produce output that is more compatible with other database systems
or with older MySQL servers. The value of name can be ansi,
mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb,
no_key_options, no_table_options, or no_field_options. To use
several values, separate them by commas. These values have the same
meaning as the corresponding options for setting the server SQL
mode. See Section 5.1.8, "Server SQL Modes".
This option does not guarantee compatibility with other servers. It
only enables those SQL mode values that are currently available for
making dump output more compatible. For example,
--compatible=oracle does not map data types to Oracle types or use
Oracle comment syntax.
This option requires a server version of 4.1.0 or higher. With
older servers, it does nothing.
quex
pon., 08/11/2010 - 16:33
odnośnik
Muszę przyznać że nie próbowałem robić importu odpowiednio wyeksportowanych danych z mysql do postgresql.
Jeżeli znajdę chwilę czasu to sprawdzę to - być może ułatwi to proces migracji w przypadku kiedy wykonywanie takich skryptów jest niemożliwe np. jeżeli nie mamy dostępu do powłoki.
Dodaj nową odpowiedź