This is a perl script I’ve used to move data from mysql 5.1 to postgres 9, this script doesn’t create a schema, it only grabs the data from mysql and try to put it on the same table in postgres.

The only requirement is DBI for mysql and postgres.

  1. #!/usr/bin/perl
  2. #
  3. # this script moves all the data from mysql to postgres
  4. # modules required are:
  5. #
  6. # http://search.cpan.org/~timb/DBI-1.616/DBI.pm
  7. #
  8. # please change the dsn, srcUser/srcPass and dstUser/Pass variables.
  9.  
  10. use DBI;
  11. use strict;
  12.  
  13. my $srcUser = 'ivan';
  14. my $srcPass = '123';
  15. my $srcDbName = 'datatocopy';
  16. my $srcDbHost = 'mini';
  17.  
  18. my $dstUser = 'ivan';
  19. my $dstPass = '456';
  20. my $dstDbName = 'migrateddata';
  21. my $dstDbHost = '192.168.1.145';
  22.  
  23. ### do not modify ##
  24.  
  25. my $srcDb = DBI->connect("dbi:mysql:database=$srcDbName;host=$srcDbHost", $srcUser, $srcPass) or die;
  26. my $dstDb = DBI->connect("dbi:Pg:database=$dstDbName;host=$dstDbHost", $dstUser, $dstPass) or die;
  27.  
  28. ####main########
  29. print "Starting to move data from $srcDbHost to $dstDbHost\n";
  30. $srcDb->do("SET NAMES \'UTF8\'");
  31. $dstDb->do("SET CLIENT_ENCODING=\'UTF8\'") or die;
  32. my $srcTables = $srcDb->selectall_arrayref("SHOW TABLES");
  33. my $dstTables = $dstDb->selectall_hashref("SELECT * FROM pg_tables WHERE NOT tablename ~\'^(pg_|sql_)\'","tablename");
  34. my $seqlist = $dstDb->selectall_arrayref("SELECT RELNAME FROM pg_class WHERE relkind=\'S\'");
  35. my $seqmap;
  36. foreach my $s(@$seqlist) {
  37. my $seqname = $s->[0];
  38. if ($seqname=~/^(.*)_([a-z]+)_([a-z]+$)/) {
  39. my $item;
  40. $item->{seq}=$seqname;
  41. $item->{field}=$2;
  42. my $table = $1;
  43. if (exists $dstTables->{$table}) {
  44. push @{$seqmap->{$table}},$item;
  45. } else {
  46. print STDERR "WARN: cannot find table for sequence $seqname\n";
  47. }
  48. }
  49. }
  50. $dstDb->{AutoCommit}=0;
  51. my $totalRowCount = 0;
  52. foreach my $t(@$srcTables) {
  53. my $table = $t->[0];
  54. unless (exists $dstTables->{$table}) {
  55. print STDERR "WARN: table $table does not exists in dest db Pg:$dstDbName\n";
  56. next;
  57. }
  58. print "Clearing data from table $table in $dstDbHost\n";
  59. clear_table($dstDb,$table);
  60. next if $table=~/^cache/;
  61. next if $table=~/^locales/;
  62. print "Copying data from mysql table $table in $srcDbHost to postgres table $table in $dstDbHost\n";
  63. my $cnt = copy_table($srcDb,$dstDb,$table) unless $table=~/^cache/;
  64. $totalRowCount = $totalRowCount + $cnt;
  65. print "$cnt rows copied ($table)\n";
  66. init_seq($dstDb,$table,$seqmap->{$table}); # if (exists $seqmap->{$table});
  67. }
  68. print "Commiting changes \n";
  69. $dstDb->commit;
  70. print "$totalRowCount rows were copied.\n";
  71. exit 0;
  72. sub init_seq {
  73. my ($db,$table,$list)=@_;
  74. return unless $list;
  75. for my $item (@{$list}) {
  76. my $ref = $db->selectall_arrayref("SELECT MAX($item->{field}) FROM $table") or die;
  77. my $val = $ref->[0]->[0];
  78. if ($val) {
  79. $db->do("SELECT SETVAL(\'$item->{seq}\',$val)") or die;
  80. }
  81. }
  82. }
  83. sub clear_table {
  84. my ($dbh,$table)=@_;
  85. return unless $table;
  86. $dbh->do("DELETE FROM $table") or die;
  87. }
  88.  
  89. sub copy_table {
  90. my ($srcDb,$dstDb,$table)=@_;
  91. die unless $table;
  92. my $slf = $srcDb->prepare("select * from $table limit 1");
  93. my $rows = $slf->execute() or die;
  94. return 0 if $rows < 1;
  95. my $rec1 = $slf->fetchrow_hashref;
  96. $slf->finish;
  97. my @fieldnames = sort keys %$rec1;
  98. my @qm = map { '?'} @fieldnames;
  99. my $ins = $dstDb->prepare("INSERT INTO $table (".join(",",@fieldnames).") VALUES(".join(",",@qm).")");
  100. my $sel = $srcDb->prepare("SELECT * FROM $table");
  101. $sel->execute or die;
  102. my $cnt = 0;
  103. while (my $data = $sel->fetchrow_hashref) {
  104. $ins->execute(map {$data->{$_}} @fieldnames) or die;
  105. $cnt++;
  106. }
  107. $ins->finish;
  108. $sel->finish;
  109. return $cnt;
  110. }