1. 程式人生 > 其它 >用Java寫了一個程式,將一個Mysql庫中的表,遷移到另外一個server上的Mysql庫中

用Java寫了一個程式,將一個Mysql庫中的表,遷移到另外一個server上的Mysql庫中

用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 [email protected] 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 }

執行過程中的日誌輸入: