Created
February 11, 2013 10:46
-
-
Save nikoma/4753784 to your computer and use it in GitHub Desktop.
Migrates data from MySQL to Postgresql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# | |
# this script moves all the data from mysql to postgres | |
# modules required are: | |
# | |
# http://search.cpan.org/~timb/DBI-1.616/DBI.pm | |
# | |
# please change the dsn, srcUser/srcPass and dstUser/Pass variables. | |
use DBI; | |
use strict; | |
my $srcUser = 'user'; | |
my $srcPass = ''; | |
my $srcDbName = 'database_name'; | |
my $srcDbHost = 'localhost'; | |
my $dstUser = 'user'; | |
my $dstPass = ''; | |
my $dstDbName = 'database_name'; | |
my $dstDbHost = 'localhost'; | |
### do not modify ## | |
my $srcDb = DBI->connect("dbi:mysql:database=$srcDbName;host=$srcDbHost", $srcUser, $srcPass) or die; | |
my $dstDb = DBI->connect("dbi:Pg:database=$dstDbName;host=$dstDbHost", $dstUser, $dstPass) or die; | |
####main######## | |
print "Starting to move data from $srcDbHost to $dstDbHost\n"; | |
$srcDb->do("SET NAMES \'UTF8\'"); | |
$dstDb->do("SET CLIENT_ENCODING=\'UTF8\'") or die; | |
my $srcTables = $srcDb->selectall_arrayref("SHOW TABLES"); | |
my $dstTables = $dstDb->selectall_hashref("SELECT * FROM pg_tables WHERE NOT tablename ~\'^(pg_|sql_)\'","tablename"); | |
my $seqlist = $dstDb->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; | |
if (exists $dstTables->{$table}) { | |
push @{$seqmap->{$table}},$item; | |
} else { | |
print STDERR "WARN: cannot find table for sequence $seqname\n"; | |
} | |
} | |
} | |
$dstDb->{AutoCommit}=0; | |
my $totalRowCount = 0; | |
foreach my $t(@$srcTables) { | |
my $table = $t->[0]; | |
unless (exists $dstTables->{$table}) { | |
print STDERR "WARN: table $table does not exists in dest db Pg:$dstDbName\n"; | |
next; | |
} | |
print "Clearing data from table $table in $dstDbHost\n"; | |
clear_table($dstDb,$table); | |
next if $table=~/^cache/; | |
next if $table=~/^locales/; | |
print "Copying data from mysql table $table in $srcDbHost to postgres table $table in $dstDbHost\n"; | |
my $cnt = copy_table($srcDb,$dstDb,$table) unless $table=~/^cache/; | |
$totalRowCount = $totalRowCount + $cnt; | |
print "$cnt rows copied ($table)\n"; | |
init_seq($dstDb,$table,$seqmap->{$table}); # if (exists $seqmap->{$table}); | |
print "Commiting changes \n"; | |
$dstDb->commit; | |
print "$totalRowCount rows were copied.\n"; | |
} | |
exit 0; | |
sub init_seq { | |
my ($db,$table,$list)=@_; | |
return unless $list; | |
for my $item (@{$list}) { | |
my $ref = $db->selectall_arrayref("SELECT MAX($item->{field}) FROM $table") or die; | |
my $val = $ref->[0]->[0]; | |
if ($val) { | |
$db->do("SELECT SETVAL(\'$item->{seq}\',$val)") or die; | |
} | |
} | |
} | |
sub clear_table { | |
my ($dbh,$table)=@_; | |
return unless $table; | |
$dbh->do("DELETE FROM $table") or die; | |
} | |
sub copy_table { | |
my ($srcDb,$dstDb,$table)=@_; | |
die unless $table; | |
my $slf = $srcDb->prepare("select * from $table limit 1"); | |
my $rows = $slf->execute() or die; | |
return 0 if $rows < 1; | |
my $rec1 = $slf->fetchrow_hashref; | |
$slf->finish; | |
my @fieldnames = sort keys %$rec1; | |
my @qm = map { '?'} @fieldnames; | |
my $ins = $dstDb->prepare("INSERT INTO $table (".join(",",@fieldnames).") VALUES(".join(",",@qm).")"); | |
my $sel = $srcDb->prepare("SELECT * FROM $table"); | |
$sel->execute or die; | |
my $cnt = 0; | |
while (my $data = $sel->fetchrow_hashref) { | |
$ins->execute(map {$data->{$_}} @fieldnames) or die; | |
$cnt++; | |
} | |
$ins->finish; | |
$sel->finish; | |
return $cnt; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment