«

»

May 13

Migração de dados Postgres -> Mysql

Bom, precisei esta semana migrar um banco de dados de postgres para MySQL …

A primeira tentativa foi utilizar o proprio MySQL Migration Tool, mas não deu certo por que ele não tem suporte nativo ao Postgres e se perdia direto nos campos Data, fazendo com que em qualquer tabela que tivesse um tampo Timestamp, ele não inserisse nenhuma linha …

Mas percebi que o Migration tool estava criando o schema corretamente no MySQL.

o que precisei fazer foi comentar a parte do schema que criava os relacionamentos e constraints, pois isto iria dificultar muito a migração dos dados.

e depois escrevi um pequeno programa java, que na verdade só tem uma classe pois foi escrito em 5 minutos, utilizando um pouquinho de JDBC nativo, não esta perfeitamente organizado, demora horas para rodar em um banco de dados com milhões de registros, mas funciona :D

E como isto foi para mim mesmo que precisei fazer, nenhum cliente estava me pagando para desenvolver isto, segue um passo a passo de migração MySQL -> PostgresSQL.

  1. Adicionar o jar do PostgreSQL no diretório lib do MySQL Migration Tool
  2. Rodar o Migration Tool informando corretamente as informações de conexão aos bancos de dados.
  3. na criação do Schema, marcar o checkbox que diz que deve ser criado um .sql
  4. Abrir o .sql e comentar as constraints
  5. executar o sql
  6. Executar o programa Migration.java
  7. alterar o sql para executar alter table(s) e adicionar as contraints
  8. Tudo pronto :D

Segue o código do programa, não esta perfeito, mas acho que pode pelo menos servir de exemplo para alguem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package teste;
 
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
 
public class Migrate {
        public static void main(String[] args) {
                try {
                        Class.forName("com.mysql.jdbc.Driver");
                        Class.forName("org.postgresql.Driver");
                } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                }
                try {
                        Connection source = DriverManager.getConnection("jdbc:postgresql:db", "postgres", "postgres");
                        try {
                                Connection destination = DriverManager.getConnection("jdbc:mysql:///db", "root", "admin");
                                try {
                                        DatabaseMetaData meta = source.getMetaData();
                                        ResultSet tables = meta.getTables(null, null, null, new String[] { "TABLE" });
                                        HashMap<string, ArrayList<string>> tableNames = new HashMap<string, ArrayList<string>>();
                                        try {
                                                while (tables.next()) {
                                                        tableNames.put(tables.getString(3), new ArrayList<string>());
                                                }
                                        } finally {
                                                tables.close();
                                        }
                                        for (String table : tableNames.keySet()) {
                                                ArrayList<string> columns = tableNames.get(table);
                                                ResultSet colNames = meta.getColumns(null, null, table, null);
                                                try {
                                                        while (colNames.next()) {
                                                                columns.add(colNames.getString(4));
                                                        }
                                                } finally {
                                                        colNames.close();
                                                }
                                        }
                                        for (Map.Entry<string, ArrayList<string>> table : tableNames.entrySet()) {
                                                prepareCopy(source, destination, table);
                                        }
                                } finally {
                                        destination.close();
                                }
                        } finally {
                                source.close();
                        }
                } catch (SQLException e) {
                        e.printStackTrace();
                }
        }
 
        private static void prepareCopy(Connection source, Connection destination, Map.Entry<string, ArrayList<string>> table) throws SQLException {
                String selectSql = buildSelectSQL(table.getKey(), table.getValue());
                String deleteSql = buildDeleteSQL(table.getKey(), table.getValue());
                String insertSql = buildInsertSQL(table.getKey(), table.getValue());
                System.out.println(selectSql);
                System.out.println(deleteSql);
                System.out.println(insertSql);
                doDelete(destination, deleteSql);
                Statement st = source.createStatement();
                try {
                        ResultSet sres = st.executeQuery(selectSql);
                        try {
                                PreparedStatement pst = destination.prepareStatement(insertSql);
                                try {
                                        int size = table.getValue().size();
                                        while (sres.next()) {
                                                doCopyLine(sres, pst, size);
                                        }
                                } finally {
                                        pst.close();
                                }
                        } finally {
                                sres.close();
                        }
                } finally {
                        st.close();
                }
        }
 
        private static void doCopyLine(ResultSet sres, PreparedStatement pst, int size) throws SQLException {
                for (int i = 0; i < size; i++) {
                        pst.setObject(i + 1, sres.getObject(i + 1));
                }
                pst.execute();
        }
 
        private static void doDelete(Connection destination, String deleteSql) throws SQLException {
                Statement dst = destination.createStatement();
                try {
                        dst.execute(deleteSql);
                } finally {
                        dst.close();
                }
        }
 
        private static String buildDeleteSQL(String key, ArrayList<string> value) {
                return "delete from " + key;
        }
 
        private static String buildInsertSQL(String key, ArrayList<string> value) {
                StringBuilder sb = new StringBuilder();
                sb.append("insert into ").append(key).append(" (");
                for (String col : value) {
                        sb.append(col).append(",");
                }
                int idx = sb.lastIndexOf(",");
                sb.replace(idx, idx + 1, ") values (");
                for (int i = 0; i < value.size(); i++) {
                        sb.append("?,");
                }
                idx = sb.lastIndexOf(",");
                sb.replace(idx, idx + 1, ")");
                return sb.toString();
        }
 
        private static String buildSelectSQL(String key, ArrayList<string> value) {
                StringBuilder sb = new StringBuilder();
                sb.append("select ");
                for (String col : value) {
                        sb.append(col).append(",");
                }
                int idx = sb.lastIndexOf(",");
                sb.replace(idx, idx + 1, " from ");
                sb.append(key);
                return sb.toString();
        }
}