Insert into select 批量同步数据

查看某数据库中表信息

SELECT * from information_schema.tables
WHERE table_schema not in ('information_schema', 'mysql', 'performance_schema')
and table_schema='zaip_xman_avatar'
ORDER BY table_schema, table_name;

根据表名查询所有表字段

select group_concat(COLUMN_NAME) from information_schema.COLUMNS where table_name = 'coupon' and table_schema='zaip_xman_activity'

id,ds_name,ds_desc,ds_type,ds_address,ds_cluster_name,access_id,access_key,second_level_code,creator,modifier,gmt_created,gmt_modified,is_deleted,tenant_code

防止字段名是关键字导致异常

select concat('`',group_concat(column_name separator '`,`'),'`') from information_schema.COLUMNS where table_name = 'coupon' and table_schema='zaip_xman_activity'

id,prize_code,parent_id,coupon_code,coupon_cdkey,expire_type,expire_time,expire_time_start,expire_time_end,expire_day,delivery_time,status,is_deleted,creator,gmt_created,modifier,gmt_modified

第二种方式,比上面一种方便

select group_concat(concat('`',column_name,'`') separator ',') from information_schema.COLUMNS where table_name = 'coupon' and table_schema='zaip_xman_activity'

id,prize_code,parent_id,coupon_code,coupon_cdkey,expire_type,expire_time,expire_time_start,expire_time_end,expire_day,delivery_time,status,is_deleted,creator,gmt_created,modifier,gmt_modified

直接将column_name替换为:

concat('`',column_name,'`')

根据字段类型写对应的表达式

select group_concat(case data_type when 'datetime' then concat('UNIX_TIMESTAMP(',column_name,')*1000') else column_name end separator ',') from information_schema.COLUMNS where table_name = 'coupon' and table_schema='zaip_xman_activity'

上面是datetime转换成时间戳对应的sql

id,prize_code,parent_id,coupon_code,coupon_cdkey,expire_type,expire_time,UNIX_TIMESTAMP(expire_time_start)1000,UNIX_TIMESTAMP(expire_time_end)1000,expire_day,UNIX_TIMESTAMP(delivery_time)1000,status,is_deleted,creator,UNIX_TIMESTAMP(gmt_created)1000,modifier,UNIX_TIMESTAMP(gmt_modified)*1000

直接将column_name替换为:

case data_type when 'datetime' then concat('UNIX_TIMESTAMP(',column_name,')*1000') else column_name end

防止字段名是关键字

select group_concat(case data_type when 'datetime' then concat('UNIX_TIMESTAMP(',concat('`',column_name,'`'),')*1000') else concat('`',column_name,'`') end separator ',') from information_schema.COLUMNS where table_name = 'coupon' and table_schema='zaip_xman_activity'

id,prize_code,parent_id,coupon_code,coupon_cdkey,expire_type,expire_time,UNIX_TIMESTAMP(expire_time_start)1000,UNIX_TIMESTAMP(expire_time_end)1000,expire_day,UNIX_TIMESTAMP(delivery_time)1000,status,is_deleted,creator,UNIX_TIMESTAMP(gmt_created)1000,modifier,UNIX_TIMESTAMP(gmt_modified)*1000

根据字段名称写对应表达式

select group_concat(case when column_name in ('gmt_created','gmt_modified') then concat('UNIX_TIMESTAMP(',column_name,')*1000') else column_name end separator ',') from information_schema.COLUMNS where table_name = 'coupon' and table_schema='zaip_xman_activity'

id,prize_code,parent_id,coupon_code,coupon_cdkey,expire_type,expire_time,expire_time_start,expire_time_end,expire_day,delivery_time,status,is_deleted,creator,UNIX_TIMESTAMP(gmt_created)1000,modifier,UNIX_TIMESTAMP(gmt_modified)1000

生成查询数据库sql脚本

delimiter $$
drop procedure if exists pro $$
create procedure pro(databaseName varchar(200))
begin 
   declare sqltext longtext default '';
   declare num,dataNum int default 0;
   set num=1;
	 
   set @rowNo=0;
	 drop table if exists temp;
	 create table temp as SELECT (@rowNO := @rowNo+1) AS id,table_name from information_schema.tables WHERE table_name<>'temp' and  table_schema=databaseName ORDER BY table_schema, table_name;
	 
	 while num<=@rowNo do
			 select concat(sqltext,'\n','select ',group_concat(COLUMN_NAME),' from ',table_name,';') into sqltext from information_schema.COLUMNS where table_name in (select table_name from temp where id=num);
			 set num=num+1;
	 end while;
	 drop table if exists temp;
	 select sqltext;
end $$
delimiter ;

-- 防止group_concat截断
SET SESSION group_concat_max_len = 999999999;

-- 执行存储过程
call pro('zaip_xman_avatar');

GROUP_CONCAT超长截断问题

ROUP_CONCAT拼接的最大长度默认为1024字节,超过这个长度则会被截断,可以通过SET [GLOBAL | SESSION] group_concat_max_len = val;进行修改。

比如修改GROUP_CONCAT长度为1个字节。

SET SESSION group_concat_max_len = 1;

生成Insert into select数据库sql脚本

初始版,只有查询的库名,必须在要新增数据的库中运行

delimiter $$
drop procedure if exists pro $$
create procedure pro(databaseName varchar(200),originDataBaseName varchar(200))
begin 
   declare sqltext longtext default '';
   declare num,dataNum int default 0;
   set num=1;
	 
   set @rowNo=0;
	 drop table if exists temp;
	 create table temp as SELECT (@rowNO := @rowNo+1) AS id,table_name from information_schema.tables WHERE table_name<>'temp' and  table_schema=databaseName ORDER BY table_schema, table_name;
	 
	 while num<=@rowNo do
			 select concat(sqltext,'\n','insert ignore into ',table_name,' (',group_concat(column_name),') \n','select',lpad(' ',length(table_name)+15,' '),group_concat(COLUMN_NAME),' from ',originDataBaseName,'.',table_name,';') into sqltext from information_schema.COLUMNS where table_schema=databaseName and table_name in (select table_name from temp where id=num);
			 set num=num+1;
	 end while;
	 drop table if exists temp;
	 select sqltext;
end $$
delimiter ;

-- 防止group_concat截断
SET SESSION group_concat_max_len = 999999999;

-- 执行存储过程
call pro('zaip_xman_avatar_new','zaip_xman_avatar');

新增insert库名

delimiter $$
drop procedure if exists pro $$
create procedure pro(databaseName varchar(200),originDataBaseName varchar(200))
begin 
   declare sqltext longtext default '';
   declare num,dataNum int default 0;
   set num=1;
	 
   set @rowNo=0;
	 drop table if exists temp;
	 create table temp as SELECT (@rowNO := @rowNo+1) AS id,table_name from information_schema.tables WHERE table_name<>'temp' and  table_schema=databaseName ORDER BY table_schema, table_name;
	 
	 while num<=@rowNo do
			 select concat(sqltext,'\n','insert ignore into ',databaseName,'.',table_name,' (',group_concat(column_name),') \n','select',lpad(' ',length(databaseName)+1,' '),lpad(' ',length(table_name)+15,' '),group_concat(COLUMN_NAME),' from ',originDataBaseName,'.',table_name,';') into sqltext from information_schema.COLUMNS where table_schema=databaseName and table_name in (select table_name from temp where id=num);
			 set num=num+1;
	 end while;
	 drop table if exists temp;
	 select sqltext;
end $$
delimiter ;

-- 防止group_concat截断
SET SESSION group_concat_max_len = 999999999;

-- 执行存储过程
call pro('zaip_xman_avatar_new','zaip_xman_avatar');

call pro('zaip_xman_multi_tenant_new','zaip_xman_activity');

每个字段用`标志,防止字段名是关键字

delimiter $$
drop procedure if exists pro $$
create procedure pro(databaseName varchar(200),originDataBaseName varchar(200))
begin 
   declare sqltext longtext default '';
   declare num,dataNum int default 0;
   set num=1;
	 
   set @rowNo=0;
	 drop table if exists temp;
	 create table temp as SELECT (@rowNO := @rowNo+1) AS id,table_name from information_schema.tables WHERE table_name<>'temp' and  table_schema=databaseName ORDER BY table_schema, table_name;
	 
	 while num<=@rowNo do
			 select concat(sqltext,'\n','insert ignore into ',databaseName,'.',table_name,' (',group_concat(concat('`',column_name,'`')),') \n','select',lpad(' ',length(databaseName)+1,' '),lpad(' ',length(table_name)+15,' '),group_concat(concat('`',column_name,'`')),' from ',originDataBaseName,'.',table_name,';') into sqltext from information_schema.COLUMNS where table_schema=databaseName and table_name in (select table_name from temp where id=num);
			 set num=num+1;
	 end while;
	 drop table if exists temp;
	 select sqltext;
end $$
delimiter ;

-- 防止group_concat截断
SET SESSION group_concat_max_len = 999999999;

-- 执行存储过程
call pro('zaip_xman_avatar_new','zaip_xman_avatar');

call pro('zaip_xman_multi_tenant_new','zaip_xman_activity');

将datetime转换成时间戳,自动生成语句

delimiter $$
drop procedure if exists pro $$
create procedure pro(databaseName varchar(200),originDataBaseName varchar(200))
begin 
   declare sqltext longtext default '';
   declare num,dataNum int default 0;
   set num=1;
	 
   set @rowNo=0;
	 drop table if exists temp;
	 create table temp as SELECT (@rowNO := @rowNo+1) AS id,table_name from information_schema.tables WHERE table_name<>'temp' and  table_schema=databaseName ORDER BY table_schema, table_name;
	 
	 while num<=@rowNo do
			 select concat(sqltext,'\n','insert ignore into ',databaseName,'.',table_name,' (',group_concat(concat('`',column_name,'`')),') \n','select',lpad(' ',length(databaseName)+1,' '),lpad(' ',length(table_name)+15,' '),group_concat(case data_type when 'datetime' then concat('UNIX_TIMESTAMP(',concat('`',column_name,'`'),')*1000') else concat('`',column_name,'`') end),' from ',originDataBaseName,'.',table_name,';') into sqltext from information_schema.COLUMNS where table_schema=databaseName and table_name in (select table_name from temp where id=num);
			 set num=num+1;
	 end while;
	 drop table if exists temp;
	 select sqltext;
end $$
delimiter ;

-- 防止group_concat截断
SET SESSION group_concat_max_len = 999999999;

-- 执行存储过程
call pro('zaip_xman_avatar_new','zaip_xman_avatar');

call pro('zaip_xman_multi_tenant_new','zaip_xman_activity');

call pro('zaip_xman_xflow_new','zaip_xman_xflow');

生成的sql语句:

insert ignore into zaip_xman_xflow_new.zatlas_request_log (`id`,`time`,`email`,`appkey`,`remote_addr`,`method`,`uri`,`response_time`,`token`,`status`,`gmt_created`,`gmt_modified`,`creator`,`modifier`,`is_deleted`) 
select                                                     `id`,UNIX_TIMESTAMP(`time`)*1000,`email`,`appkey`,`remote_addr`,`method`,`uri`,`response_time`,`token`,`status`,UNIX_TIMESTAMP(`gmt_created`)*1000,UNIX_TIMESTAMP(`gmt_modified`)*1000,`creator`,`modifier`,`is_deleted` from zaip_xman_xflow.zatlas_request_log;

根据字段名判断类型,自动生成语句

delimiter $$
drop procedure if exists pro $$
create procedure pro(databaseName varchar(200),originDataBaseName varchar(200))
begin 
   declare sqltext longtext default '';
   declare num,dataNum int default 0;
   set num=1;
	 
   set @rowNo=0;
	 drop table if exists temp;
	 create table temp as SELECT (@rowNO := @rowNo+1) AS id,table_name from information_schema.tables WHERE table_name<>'temp' and  table_schema=databaseName ORDER BY table_schema, table_name;
	 
	 while num<=@rowNo do
			 select concat(sqltext,'\n','insert ignore into ',databaseName,'.',table_name,' (',group_concat(concat('`',column_name,'`')),') \n','select',lpad(' ',length(databaseName)+1,' '),lpad(' ',length(table_name)+15,' '),group_concat(case when column_name in ('gmt_created','gmt_modified','attribution_begin_date','attribution_end_date','last_warning_time','effective_time','begin_date','end_date','analyze_begin_date','analyze_end_date','funnel_begin_date','funnel_end_date','bizdate_date') then concat('UNIX_TIMESTAMP(',concat('`',column_name,'`'),')*1000') else concat('`',column_name,'`') end),' from ',originDataBaseName,'.',table_name,';') into sqltext from information_schema.COLUMNS where table_schema=databaseName and table_name in (select table_name from temp where id=num);
			 set num=num+1;
	 end while;
	 drop table if exists temp;
	 select sqltext;
end $$
delimiter ;

-- 防止group_concat截断
SET SESSION group_concat_max_len = 999999999;

call pro('zaip_xman_xflow_new','zaip_xman_xflow');

将字段名'gmt_created','gmt_modified','attribution_begin_date','attribution_end_date','last_warning_time','effective_time','begin_date','end_date','analyze_begin_date','analyze_end_date','funnel_begin_date','funnel_end_date','bizdate_date'字段当成时间戳类型查出

校验mysql

校验mysql库里面表数量

SELECT table_schema,count(1) as num from information_schema.tables
WHERE table_schema in ('zaip_xman_activity_new','zaip_xman_avatar_new','zaip_xman_cms_new','zaip_xman_common_mgt_new','zaip_xman_lang_new','zaip_xman_markting_new','zaip_xman_multi_tenant_new','zaip_xman_push_new','zaip_xman_xflow_new')
GROUP BY table_schema;

校验对比迁移数据量是否一致

delimiter $$
drop procedure if exists testMigrate $$
create procedure testMigrate(databaseName varchar(200),originDataBaseName varchar(200))
begin 
	 SELECT 
    a.table_name, 
		a.table_rows as newTableRows,
    b.table_rows as oldTableRows
FROM
    information_schema.tables a 
		join information_schema.tables b 
		on a.table_name=b.table_name
WHERE
    a.table_schema = databaseName
		and b.table_schema = originDataBaseName
		and a.table_type = 'BASE TABLE'
		and b.table_type = 'BASE TABLE'
		and a.table_rows<>b.table_rows;
end $$
delimiter ;

call testMigrate('zaip_xman_xflow_new','zaip_xman_xflow');

为什么mysql没有nolock

  • SQLSERVER 默认情况下,一个事务修改了某个值,在这个事务提交前,是阻塞其他连接来读取这个修改中的值的,如果加nolock,那么读取到的可能是修改后未提交的值(也就是脏读,因为可能这个值最终会回滚)
  • MySQL 一个事务修改了某个值,在这个事务提交前,不阻塞其他连接来读取这个修改中的值,并且读取到的是修改前的值。

根据上面的对比,发现mysql使用nolock没有意义,因为mysql本身就不阻塞查询。

参考

Insert into select语句引发的生产事故

insert into ... select 由于SELECT表引起的死锁情况分析

关于MySQL和nolock的小知识

利用 force index优化sql语句性能

mysql - 索引/fulltext index/force index/use force /ignore index/索引失效

posted @ 2022-10-25 21:06  hongdada  阅读(491)  评论(0编辑  收藏  举报