提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
表结构可预先存在或不存在
mysql5.7
快速复制A库表数据前10000行到B库
/* 设置自定义分隔符以处理存储过程中的分号 */
DELIMITER $$
/* 删除已存在的同名存储过程 */
DROP PROCEDURE IF EXISTS sync_database_data$$
/* 创建存储过程(带参数) */
CREATE PROCEDURE sync_database_data(
IN source_db VARCHAR(64), -- 源数据库名称
IN target_db VARCHAR(64) -- 目标数据库名称
)
BEGIN
/* 声明变量 */
DECLARE done BOOLEAN DEFAULT FALSE; -- 循环控制标志
DECLARE tb_name VARCHAR(64); -- 存储表名
DECLARE err_msg TEXT; -- 错误信息存储
/* 声明游标(必须放在 HANDLER 之前) */
DECLARE cur CURSOR FOR
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = source_db
AND TABLE_TYPE = 'BASE TABLE'; -- 仅处理物理表,排除视图
/* 声明处理器 */
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 游标结束处理
DECLARE EXIT HANDLER FOR SQLEXCEPTION -- 异常处理
BEGIN
GET DIAGNOSTICS CONDITION 1 err_msg = MESSAGE_TEXT; -- 获取错误详情
SET @full_err = CONCAT('表 ', tb_name, ' 同步失败: ', LEFT(err_msg, 64));
RESIGNAL SET MESSAGE_TEXT = @full_err; -- 抛出带表名的错误
ROLLBACK; -- 回滚事务
END;
/*----------- 前置校验 -----------*/
-- 验证源数据库是否存在
IF NOT EXISTS (
SELECT 1
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = source_db
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '源数据库不存在';
END IF;
/*----------- 主逻辑 -----------*/
-- 打开表游标
OPEN cur;
-- 开始循环处理每张表
read_loop: LOOP
FETCH cur INTO tb_name;
IF done THEN
LEAVE read_loop; -- 退出循环
END IF;
/* 动态生成SQL语句 */
-- 创建表结构(如果不存在)
SET @create_sql = CONCAT(
'CREATE TABLE IF NOT EXISTS `', target_db, '`.`', tb_name,
'` LIKE `', source_db, '`.`', tb_name, '`'
);
-- 全部数据
SET @insert_sql = CONCAT(
'INSERT INTO `', target_db, '`.`', tb_name,
'` SELECT * FROM `', source_db, '`.`', tb_name ,'`'
);
-- 插入前10000条数据
-- SET @insert_sql = CONCAT(
-- 'INSERT INTO `', target_db, '`.`', tb_name,
-- '` SELECT * FROM `', source_db, '`.`', tb_name,
-- '` LIMIT 10000'
-- );
/*----------- 性能优化配置 -----------*/
-- 设置批量插入缓存(仅当前会话有效)
SET bulk_insert_buffer_size = 256 * 1024 * 1024; -- 256MB
-- 禁用约束检查(加速插入)
SET unique_checks = 0; -- 关闭唯一性校验
SET foreign_key_checks = 0; -- 关闭外键校验
/*----------- 事务执行块 -----------*/
START TRANSACTION;
-- 执行建表操作
PREPARE stmt FROM @create_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 执行数据插入
PREPARE stmt FROM @insert_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT; -- 提交事务
/*----------- 恢复配置 -----------*/
-- 启用约束检查(保证后续操作安全)
SET unique_checks = 1;
SET foreign_key_checks = 1;
END LOOP;
-- 关闭游标
CLOSE cur;
END$$
/* 恢复默认分隔符 */
DELIMITER ;
– 完整同步示例
CALL sync_database_data(‘target_db’, ‘target_db’);
将代码分为清晰的逻辑区块,使用注释分隔验证、主逻辑、配置等部分
-- 在插入前禁用约束检查
SET unique_checks = 0;
SET foreign_key_checks = 0;
-- 在插入后恢复设置
SET unique_checks = 1;
SET foreign_key_checks = 1;
该配置对InnoDB引擎有效,可使插入速度提升2-3倍
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
…
RESIGNAL SET MESSAGE_TEXT = @full_err; – 显示具体报错表
ROLLBACK; – 确保事务回滚
END;
CREATE TABLE IF NOT EXISTS – 避免表已存在时报错
完整同步示例
CALL sync_database_data('source_db', 'target_db');