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.


Odpowiedzi
Dodaj nową odpowiedź