用Java写了一个程序,将一个Mysql库中的表,迁移到另外一个server上的Mysql库中

2023-05-13,,

用Navicat做数据迁移,因为数据量比较大,迁移过过程中一个是进展不直观,另外就是cpu占用率高的时候,屏幕跟死机了一样点不动按钮,不好中断。

想了想,干脆自己写一个。

在网上找了一个sqllite迁移mysql数据的基础代码,然后在这基础上做了修改。

1、用这一个程序就能搞定指定数据库表的数据迁移执行工作。

2、目前每次可以执行指定的数据库表数组,但是不能仅仅单独指定库迁移所有表。

3、对于超大表的读取和数据迁移做了优化,每次读取1000条数据,每次迁移1000条数据。

4、整这代码的时间就两个小时左右,所以观赏性不佳,能执行数据迁移就ok。

5、支持mysql中中文数据的迁移,mysql库要求用utf-8编码。

6、如果迁移的表存在,则会先把表删除,然后重建对应的表。

还有很多不足,敬请包涵。

  1 package com.alex;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.PreparedStatement;
6 import java.sql.ResultSet;
7 import java.sql.SQLException;
8 import java.sql.Statement;
9
10
11
12 public class TransDbData {
13 //author 8482322@qq.com
14 private Connection connSource=null;
15 private Connection connDest=null;
16
17 ///transTables=要传输的数据表名字的数组,如果是多个表,则完善此数组即可
18 public static String[] transTables={"table-1","talbe-2","table-3"};
19 private static int curLine=0;
20
21 public static void main(String[] args) {
22 TransDbData test = new TransDbData();
23 int k=0;
24 int tableLineCount=0;
25 int offset=1000;
26 int start=0;
27 int loopTimes=0;
28 try {
29 for(int i=0;i<transTables.length;i++) {
30 test.createDestTable(transTables[i]);
31 tableLineCount=test.getTableLineCount(transTables[i]);
32 int xx=tableLineCount%1000;
33 loopTimes=(int) Math.ceil(tableLineCount/offset);
34 for(int loopN=0;loopN<loopTimes;loopN++) {
35 curLine++;
36 System.out.println("正在处理第"+curLine+"批(每批数据1000条)数据");
37 test.deal(transTables[i],tableLineCount,loopN,offset);
38 }
39 }
40 } catch (SQLException e) {
41 e.printStackTrace();
42 }
43 }
44
45
46
47 private Connection getSourceConn(){
48 try {
49 Class.forName("com.mysql.jdbc.Driver");
50 String connStr="jdbc:mysql://mysql-server-数据源-ip:3306/yourdb?useSSL=false&Charset=utf8&characterEncoding=utf-8";
51 connSource = DriverManager.getConnection(connStr,"root","abcdef");
52 if(connSource!=null) {
53 System.out.println("源数据库连上了"+connStr);
54
55 }
56 return connSource;
57 } catch (ClassNotFoundException | SQLException e) {
58 e.printStackTrace();
59 }
60 return null;
61 }
62
63 private Connection getDestConn(){
64 try {
65 Class.forName("com.mysql.jdbc.Driver");
66 String connStr="jdbc:mysql://mysql-server-目标库-ip:3306/your-db?useSSL=false&Charset=utf8&characterEncoding=utf-8";
67 connDest = DriverManager.getConnection(connStr,"root","123456");
68 if(connDest!=null) {
69 System.out.println("目标数据库连上了"+connStr);
70 }
71 return connDest;
72 } catch (ClassNotFoundException | SQLException e) {
73 e.printStackTrace();
74 }
75 return null;
76 }
77
78 /**
79 * 获得表的数据总量
80 * @param transTableName
81 * @return
82 */
83 public int getTableLineCount(String transTableName) {
84 Connection srcConn = this.getSourceConn();
85 Statement srcStmt;
86 int count=0;
87 try {
88 srcStmt = srcConn.createStatement();
89 ResultSet srcRsCount = srcStmt.executeQuery("select count(*) from "+ transTableName);
90 while(srcRsCount.next()) {
91 count=srcRsCount.getInt(1);
92 System.out.println("一共有["+srcRsCount.getInt(1)+"]条数据要传输");
93 }
94 srcRsCount.close();
95 srcStmt.close();
96 srcConn.close();
97 } catch (SQLException e) {
98 e.printStackTrace();
99 }
100 return count;
101 }
102
103
104 /**
105 *
106 * @param transTableName 被传输的数据库表名称
107 * @throws SQLException
108 */
109 public void deal(String transTableName,int tableLineCount,int loopN,int offset) throws SQLException {
110 //数据源数据库
111 Connection srcConn = this.getSourceConn();
112 Statement srcStmt =srcConn.createStatement();
113
114 int startPosition = loopN*offset +1;
115 ResultSet srcRs = srcStmt.executeQuery("select * from "+ transTableName +" limit "+startPosition+" ,"+offset+" ");
116 //结果集获取到的长度
117 int size = srcRs.getMetaData().getColumnCount();
118 //比较懒,拼接insert into 语句
119 StringBuffer sbf =new StringBuffer();
120 sbf.append("insert into "+transTableName+" values (");
121 String link ="";
122 for (int i = 0; i <size ; i++) {
123 sbf.append(link).append("?");
124 link=",";
125 }
126 sbf.append(")");
127 //MySQL数据库
128 Connection destconn = getDestConn();
129 PreparedStatement destPstmt = destconn.prepareStatement(sbf.toString());
130 //System.out.println(sbf.toString());
131 //取出结果集并向MySQL数据库插入数据 ( 使用批处理 )
132 //完成条数
133 int count =0;
134 int num=0;
135 //取消事务(不写入日志)
136 destconn.setAutoCommit(false);
137 long start = System.currentTimeMillis();
138 //循环原表,从原表中读取数据
139 while (srcRs.next()) {
140 ++count;
141 System.out.print(".");
142 //System.out.println("读取第"+count+"条数据");
143 for (int i=1;i<= size;i++) {
144 destPstmt.setObject(i, srcRs.getObject(i));
145 }
146
147 //将预先语句存储起来,这里还没有向数据库插入
148 destPstmt.addBatch();
149 //当count 到达 20000条时 向数据库提交
150 if (count % 20000 ==0 ){
151 ++num;
152 destPstmt.executeBatch();
153 System.out.println("表【"+transTableName+"】数据传输第"+num+"次提交,耗时:"+(System.currentTimeMillis()-start)/1000.0+"s");
154 }
155 }
156 //防止有数据未提交
157 destPstmt.executeBatch();
158 //提交
159 destconn.commit();
160 System.out.println("本次完成【"+count+"】条数据,耗时:"+(System.currentTimeMillis()-start)/1000.0+"s");
161 //恢复事务
162 // mysqlconn.setAutoCommit(true);
163
164 //关闭资源
165 close(destconn,destPstmt,null);
166 close(srcConn,srcStmt,srcRs);
167
168 }
169
170
171 /**
172 * 根据源表名,在目的库中创建对应表
173 * @param srcTableName
174 */
175 public void createDestTable(String srcTableName) {
176 String tableName = srcTableName;
177 Connection src_conn = this.getSourceConn();
178 Connection dest_conn= this.getDestConn();
179 String sql = String.format("SHOW CREATE TABLE %s", tableName);//查询sql
180 //String sql = "SHOW CREATE TABLE ?";
181 PreparedStatement ps = null;
182 PreparedStatement ps_dest = null;
183 String dropTable="drop table "+srcTableName;
184 try {
185 System.out.println("如果表存在,先删除:"+srcTableName);
186 ps_dest=dest_conn.prepareStatement(dropTable);
187 ps_dest.execute();
188 ps_dest.close();
189 System.out.println("删除成功:"+srcTableName);
190
191 } catch (SQLException e1) {
192 System.err.println(e1.getMessage());
193 System.out.println("表原先不存在:"+srcTableName);
194
195 }
196
197 try {
198
199 ps = src_conn.prepareStatement(sql);
200 //ps.setString(1, tableName);
201 ResultSet resultSet = ps.executeQuery();
202 while (resultSet.next()) {
203 //System.out.println(resultSet.getString(1));//第一个参数获取的是tableName
204 String destTableName=resultSet.getString(1);
205 // System.out.println(resultSet.getString(2));//第二个参数获取的是表的ddl语句
206 String ddl=resultSet.getString(2);
207 ps_dest = dest_conn.prepareStatement(ddl);
208 ps_dest.execute();
209 System.out.println("目标库中创建表成功:" +destTableName);
210 ps_dest.close();
211
212 }
213 } catch (SQLException e) {
214 e.printStackTrace();
215 } finally {
216 if(null != ps){
217 try {
218 ps.close();
219 } catch (SQLException e) {
220 e.printStackTrace();
221 }
222 }
223 if(null != ps_dest){
224 try {
225 ps_dest.close();
226 } catch (SQLException e) {
227 e.printStackTrace();
228 }
229 }
230 if(null != src_conn) {
231 try {
232 src_conn.close();
233 } catch (SQLException e) {
234 e.printStackTrace();
235 }
236 }
237 if(null != dest_conn) {
238 try {
239 dest_conn.close();
240 } catch (SQLException e) {
241 e.printStackTrace();
242 }
243 }
244 }
245
246 }
247
248 //关闭数据库连接
249 public void close(Connection conn,Statement stmt,ResultSet rs){
250
251 if(rs!=null){
252 try {
253 rs.close();
254 } catch (SQLException e) {
255 e.printStackTrace();
256 }
257 }
258 if(stmt!=null){
259 try {
260 stmt.close();
261 } catch (SQLException e) {
262 e.printStackTrace();
263 }
264 }
265 if(conn!=null){
266 try {
267 conn.close();
268 } catch (SQLException e) {
269 e.printStackTrace();
270 }
271 }
272 }
273
274 }

执行过程中的日志输入:

用Java写了一个程序,将一个Mysql库中的表,迁移到另外一个server上的Mysql库中的相关教程结束。

《用Java写了一个程序,将一个Mysql库中的表,迁移到另外一个server上的Mysql库中.doc》

下载本文的Word格式文档,以方便收藏与打印。