MySql使用存儲(chǔ)過程進(jìn)行單表數(shù)據(jù)遷移的實(shí)現(xiàn)
前景
近期在進(jìn)行業(yè)務(wù)解耦,對(duì)冗余在一起切又屬于不同業(yè)務(wù)的代碼進(jìn)行分離,同時(shí)也將數(shù)據(jù)庫進(jìn)行分離存儲(chǔ),那么這時(shí)候就涉及到多個(gè)表的數(shù)據(jù)要進(jìn)行遷移,這里我們就來總結(jié)一下如何使用存儲(chǔ)過程進(jìn)行數(shù)據(jù)高效遷移。
設(shè)計(jì)思路
跨數(shù)據(jù)庫實(shí)例表數(shù)據(jù)遷移,無非就是把一個(gè)表完完整整的復(fù)制到另一個(gè)數(shù)據(jù)庫實(shí)例當(dāng)中,但是怎么做才能簡單易懂又高效呢?
首先我們寫一個(gè)腳本肯定也希望能夠多次使用,否則何必浪費(fèi)時(shí)間去研究寫大批量處理的腳本呢!我們先分析數(shù)據(jù)遷移的一些主要步驟:目標(biāo)實(shí)例創(chuàng)建表、數(shù)據(jù)分批處理、數(shù)據(jù)遷移記錄、數(shù)據(jù)遷移入庫
- 目標(biāo)實(shí)例創(chuàng)建表:我們需要根據(jù)個(gè)人所需,明確是否強(qiáng)制重新創(chuàng)建表,通常情況既然是全表遷移那都是要強(qiáng)制重新建表的(無論是否已有表數(shù)據(jù))。
- 數(shù)據(jù)分批處理:要對(duì)數(shù)據(jù)進(jìn)行分批處理,首先我們需要對(duì)數(shù)據(jù)進(jìn)行排序,那么排序最好我們是以自增主鍵id進(jìn)行排序,這樣方便我們進(jìn)行分批數(shù)據(jù)獲取。
- 數(shù)據(jù)遷移記錄:這里我們最好有個(gè)臨時(shí)表用來做實(shí)時(shí)數(shù)據(jù)遷移記錄,以免大數(shù)據(jù)遷移我們都不知道遷移到哪了,同時(shí)臨時(shí)表也有助于數(shù)據(jù)分批處理。
- 數(shù)據(jù)遷移入庫:對(duì)數(shù)據(jù)進(jìn)行排好序后,我們根據(jù)主鍵id對(duì)數(shù)據(jù)進(jìn)行過濾,避免在limit后面進(jìn)行分頁操作,limit只需要確認(rèn)遷移數(shù)據(jù)量即可。
下面我們就具體分析一下完整的遷移腳本。
遷移腳本
首先我們需要明確數(shù)據(jù)要遷移的目標(biāo)數(shù)據(jù)庫,最好要把這點(diǎn)寫在腳本里,方式跑錯(cuò)數(shù)據(jù)庫實(shí)例:
USE `test_db`;
臨時(shí)表創(chuàng)建:主要輔助記錄需要遷移的數(shù)據(jù)量、實(shí)時(shí)更新已遷移的數(shù)據(jù)量、遷移表名、遷移的數(shù)據(jù)最大主鍵id用來進(jìn)行數(shù)據(jù)過濾。
DROP TABLE IF EXISTS tmp_migrate_table_record; CREATE TABLE tmp_migrate_table_record( `id` INT PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '主鍵ID', `table_name` VARCHAR(50) COMMENT '遷移表名', `source_table_count` INT COMMENT '源表記錄數(shù)', `target_table_count` INT COMMENT '源表記錄數(shù)', `max_id` BIGINT COMMENT '已遷移最大主鍵id' );
全表遷移存儲(chǔ)過程實(shí)現(xiàn),主要包含以下幾個(gè)參數(shù):
- sourceSchema:數(shù)據(jù)源schema名稱
- tableName:需要遷移的表名(若需要遷移的目標(biāo)表名與源表名不一致,可自行添加參數(shù)做修改)
- primaryKey:表主鍵名,用于數(shù)據(jù)排序、過濾、分批處理
- batchSize:大數(shù)據(jù)遷移分批次大小
DROP PROCEDURE IF EXISTS p_migrate_full_table_data; DELIMITER $$ CREATE PROCEDURE p_migrate_full_table_data(IN sourceSchema VARCHAR(50), IN tableName VARCHAR(50), IN primaryKey VARCHAR(50), IN batchSize INT) BEGIN -- 判斷舊表是否存在,若存在則刪除舊表(強(qiáng)制重新建表) SET @dropTableSql = CONCAT('DROP TABLE IF EXISTS ', tableName, ';'); PREPARE dropTableSql FROM @dropTableSql; EXECUTE dropTableSql; -- 依賴源數(shù)據(jù),創(chuàng)建新表(這里可以根據(jù)需要更換表名) SET @craeteTable = CONCAT('CREATE TABLE ', tableName, ' LIKE `', sourceSchema, '`.', tableName, ';'); PREPARE craeteTable FROM @craeteTable; EXECUTE craeteTable; -- 清除當(dāng)前表遷移數(shù)據(jù)記錄數(shù),防止有舊數(shù)據(jù)影響 SET @deleteCountSql = CONCAT('DELETE FROM tmp_migrate_table_record WHERE table_name=''', tableName, ''';'); PREPARE deleteCountSql FROM @deleteCountSql; EXECUTE deleteCountSql; -- 初始記錄臨時(shí)表正在進(jìn)行數(shù)據(jù)遷移的表信息 SET @countSql = CONCAT('INSERT INTO tmp_migrate_table_record(table_name, source_table_count, target_table_count) SELECT ''', tableName, ''', COUNT(*), 0 FROM `', sourceSchema, '`.', tableName, ';'); PREPARE countSql FROM @countSql; EXECUTE countSql; -- 用于查看預(yù)編譯后的SQL腳本,若有需要可以打開注釋查看 -- SELECT @dropTableSql, @craeteTable, @deleteCountSql, @countSql; -- 數(shù)據(jù)源表記錄數(shù) SET @sourceCount = 0; -- 目標(biāo)表記錄數(shù) SET @targetCount = 0; -- 已導(dǎo)入最大id SET @maxId = 0; SELECT source_table_count, target_table_count, IFNULL(max_id, 0) INTO @sourceCount, @targetCount, @maxId FROM tmp_migrate_table_record WHERE table_name=tableName; -- 循環(huán)分批遷移數(shù)據(jù),根據(jù)已遷移數(shù)量與需要遷移數(shù)量進(jìn)行比較 WHILE @sourceCount <> @targetCount DO -- 開啟事務(wù) START TRANSACTION; -- 執(zhí)行數(shù)據(jù)分批遷移 SET @insertSql = CONCAT('INSERT INTO ', tableName, ' SELECT * FROM `', sourceSchema, '`.', tableName, ' WHERE ', primaryKey, ' > ', @maxId, ' ORDER BY ', primaryKey, ' ASC ', 'LIMIT ', batchSize, ';'); PREPARE insertSql FROM @insertSql; EXECUTE insertSql; -- 實(shí)時(shí)更新臨時(shí)表已遷移記錄數(shù) SET @updateCountSql = CONCAT('UPDATE tmp_migrate_table_record SET target_table_count = (SELECT COUNT(*) FROM ', tableName, ') WHERE table_name=''', tableName, ''';'); PREPARE updateCountSql FROM @updateCountSql; EXECUTE updateCountSql; -- 跟新臨時(shí)表以遷移數(shù)據(jù)最大主鍵id SET @updateMaxIdSql = CONCAT('UPDATE tmp_migrate_table_record SET max_id = (SELECT IFNULL(MAX(', primaryKey,'), 0) FROM ', tableName, ') WHERE table_name=''', tableName, ''';'); PREPARE updateMaxIdSql FROM @updateMaxIdSql; EXECUTE updateMaxIdSql; -- 刷新變量 SELECT target_table_count, max_id INTO @targetCount, @maxId FROM tmp_migrate_table_record WHERE table_name=tableName; -- 查看上面拼裝后的sql,需要排查問題可打開查看 SELECT @insertSql, @updateCountSql, @updateMaxIdSql, @sourceCount, @targetCount; -- 提交事務(wù) COMMIT; END WHILE; END $$ DELIMITER ;
存儲(chǔ)過程完成后,接下來就是執(zhí)行存儲(chǔ)過程進(jìn)行數(shù)據(jù)遷移了:
- CALL p_migrate_full_table_data('test_source_db', 't_student', 'student_id', 50000);
- CALL p_migrate_full_table_data('test_source_db', 't_student', 'student_id', 50000);
- CALL p_migrate_full_table_data('test_source_db', 't_student', 'student_id', 50000);
確認(rèn)數(shù)據(jù)沒有問題后,可以對(duì)臨時(shí)表進(jìn)行清理:
DROP TABLE IF EXISTS tmp_migrate_table_record;
遷移示例
創(chuàng)建測(cè)試表
DROP TABLE IF EXISTS t_student; CREATE TABLE t_student( id BIGINT, `name` VARCHAR(50), age INT(3), state CHAR(1), PRIMARY KEY (id) ); DROP TABLE IF EXISTS t_course; CREATE TABLE t_course( id BIGINT, `name` VARCHAR(50) );
使用存儲(chǔ)過程初始化數(shù)據(jù)
DROP PROCEDURE IF EXISTS init_student; DELIMITER $$ CREATE PROCEDURE init_student() BEGIN DELETE FROM t_student; SET @p = 1; -- 測(cè)試數(shù)據(jù)數(shù)量自己定 WHILE @p < 234567 DO INSERT INTO t_student VALUES(@p, CONCAT('user', @p * 1000000), 18, 'A'); SET @p = @p + 1; END WHILE; END $$ DELIMITER ; CALL init_student();
執(zhí)行遷移腳本
CALL p_migrate_full_table_data('test_source_db', 't_student', 'id', 50000); CALL p_migrate_full_table_data('test_source_db', 't_course', 'id', 50000);
總結(jié)
數(shù)據(jù)遷移的方式有很多,如果是大量的表都要遷移的情況,建議直接整個(gè)庫遷移,再刪掉不需要的表效果會(huì)更好,再大的困難都不是問題,關(guān)鍵是找對(duì)方法很重要。
到此這篇關(guān)于MySql使用存儲(chǔ)過程進(jìn)行單表數(shù)據(jù)遷移的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MySql 單表數(shù)據(jù)遷移內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql創(chuàng)建函數(shù)出現(xiàn)1418錯(cuò)誤的解決辦法
本篇文章是對(duì)在Mysql中創(chuàng)建函數(shù)報(bào)“ERROR 1418”的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06mysql數(shù)據(jù)庫如何實(shí)現(xiàn)億級(jí)數(shù)據(jù)快速清理
這篇文章主要介紹了mysql數(shù)據(jù)庫實(shí)現(xiàn)億級(jí)數(shù)據(jù)快速清理的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2018-04-04Windows系統(tǒng)下MySQL忘記root密碼的2種解決辦法
這篇文章主要介紹了Windows系統(tǒng)下MySQL忘記root密碼的2種解決辦法,一種是通過啟動(dòng)MySQL時(shí)跳過權(quán)限表驗(yàn)證,然后重置密碼,另一種是創(chuàng)建一個(gè)包含新密碼的文本文件,并通過MySQL的--init-file選項(xiàng)來應(yīng)用該文件中的密碼設(shè)置,需要的朋友可以參考下2024-11-11CentOS Mysql數(shù)據(jù)庫如何實(shí)現(xiàn)定時(shí)備份
這篇文章主要介紹了CentOS Mysql數(shù)據(jù)庫如何實(shí)現(xiàn)定時(shí)備份,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06MHA實(shí)現(xiàn)mysql主從數(shù)據(jù)庫手動(dòng)切換的方法
這篇文章主要介紹了MHA實(shí)現(xiàn)mysql主從數(shù)據(jù)庫手動(dòng)切換的方法,詳細(xì)的講述了主從數(shù)據(jù)庫切換的步驟與方法,非常實(shí)用,需要的朋友可以參考下2014-10-10