数据库表合并场景实践

在实际场景中,我们见的比较多的是表拆分,正好遇到一个需要表合并的需求,下面来分析分析


背景

目前是线上有若干张表:a1 a2、b1 b2、c1 c2...,目前需要将这些表进行合并[将b1 c1等表数据都合并到a1,将b2 c2等表合并到a2],但是线上也会有业务在跑,不能停机更新还需要保证迁移的健壮性

因为c1 c2合并的本质与b1 b2一致,故下面以b1 b2合并为例来进行描述


表结构与关系

CREATE TABLE `a1` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `info` varchar(255) COLLATE utf8mb4_croatian_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_croatian_ci;

CREATE TABLE `a2` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `a_id` int(11) DEFAULT NULL COMMENT 'a表id',
  `info` varchar(255) COLLATE utf8mb4_croatian_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_croatian_ci;



CREATE TABLE `b1` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `info` varchar(255) COLLATE utf8mb4_croatian_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_croatian_ci;

CREATE TABLE `b2` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `b_id` int(11) DEFAULT NULL COMMENT 'a表id',
  `info` varchar(255) COLLATE utf8mb4_croatian_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_croatian_ci;

最初做法

性质冲冲完成了,SQL如下

insert into a1 (info) select info from b1;
insert into a2 (a_id,info) select b_id,info from b2;

那么来测试下,看结果是否准确,结果如下

select a1.id,a1.info a1info,a2.a_id,a2.info a2info from a1 left join a2 on a1.id = a2.a_id;

 很明显这个数据错乱了,b2迁移过来的数据与a1原来的数据关联上了,造成了数据混乱


方案改造

分析先前做法,其实是b2在做迁移时,没有考虑到b2中数据要同样与迁移过去的b1数据新的主键关联上,那么如何做呢?接着往下看

  • a1表新增一个old_id字段,在b1迁移到a1表后,将b1原本的主键id保存在a1中
  • a2表新增一个is_new字段,用来标识哪些是新插入到a2的数据,防止后续修数时将a2中旧数据关联上新迁移到a1中的数据
ALTER TABLE `a1` ADD COLUMN `old_id` int NULL COMMENT '旧表主键id';
ALTER TABLE `a2` ADD COLUMN `is_new` tinyint NULL COMMENT '是否新数据标记 1:正在迁移的数据 0:已迁移完的数据 null:线上在跑的数据' ;


insert into a1 (info,old_id) select info,id from b1;
insert into a2 (a_id,info,is_new) select b_id,info,1 from b2;


update a2,b1,a1 set a2.a_id = a1.id where a1.old_id is not null and a1.old_id = b1.id and a2.is_new = 1 and a2.a_id = a1.old_id;


-- 回滚SQL
ALTER TABLE `a1` DROP COLUMN `old_id`;
ALTER TABLE `a2` DROP COLUMN `is_new`;

然后再用同样的SQL来测试

select a1.id,a1.info a1info,a2.a_id,a2.info a2info from a1 left join a2 on a1.id = a2.a_id;

到此为止,需求已经实现,但是还不完美,因为这段SQL仅仅只能跑一次,那么如果执行到一半因为各种原因失败了呢?如何将迁移的数据清理掉重新再次迁移呢?

这样看来我们上面的SQL健壮性还是不够


迁移SQL健壮性改造

-- 第一步:新增三个辅助迁移字段
ALTER TABLE `a1` ADD COLUMN `old_id` int NULL COMMENT '旧表主键id';
ALTER TABLE `a1` ADD COLUMN `is_new` int NULL COMMENT '是否新数据标记 1:是 0:否';
ALTER TABLE `a2` ADD COLUMN `is_new` tinyint NULL COMMENT '是否新数据标记 1:正在迁移的数据 0:已迁移完的数据 null:线上在跑的数据' ;


-- 第二步:开始数据迁移
insert into a1 (info,old_id,is_new) select info,id,1 from b1;
insert into a2 (a_id,info,is_new) select b_id,info,1 from b2;


-- 第三步:修正a2新迁移数据与原数据关联关系
update a2,b1,a1 set a2.a_id = a1.id where a1.old_id is not null and a1.old_id = b1.id and a2.is_new = 1 and a2.a_id = a1.old_id;


-- 第四步:打扫战场,方便后续C表等的迁移
UPDATE a2 SET is_new = 0 where is_new = 1;


-- C表重复第二步~第四步
-- ...
-- ...

-- 第五步迁移结束SQL
ALTER TABLE `a1` DROP COLUMN `old_id`;
ALTER TABLE `a1` DROP COLUMN `is_new`;
ALTER TABLE `a2` DROP COLUMN `is_new`;


-- 迁移失败回滚SQL
delete from a1 where is_new = 1;
delete from a2 where is_new is not null;

结语 

希望此表合并场景能够为你提供一些思路,附件有提供SQL供测试使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/332493.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习】四大类监督学习_模型选择与模型原理和场景应用_第03课

监督学习中模型选择原理及场景应用 监督学习应用场景 文本分类场景: o 邮件过滤:训练模型识别垃圾邮件和非垃圾邮件。 o 情感分析:根据评论或社交媒体内容的情感倾向将其分类为正面、负面或中性评价。 o 新闻分类:将新闻文章自动…

中国联通助力吴江元荡生态岸线打造5G+自动驾驶生态长廊

吴江,素有“鱼米之乡”“丝绸之府”的美誉,其地理位置优越,地处太湖之滨。近年来,随着长三角生态绿色一体化发展示范区(以下简称“示范区”)的建立,元荡更是声名大噪,成为众多游客心…

PyTorch各种损失函数解析:深度学习模型优化的关键(1)

目录 详解pytorch中各种Loss functions binary_cross_entropy 用途 用法 参数 数学理论 示例代码 binary_cross_entropy_with_logits 用途 用法 参数 数学理论 示例代码 poisson_nll_loss 用途 用法 参数 数学理论 示例代码 cosine_embedding_loss 用途 …

mac PyCharm 使用conda环境

1 使用conda创建虚拟环境 conda create -n test6 python3.9 -y conda activate test62 选择conda环境 本地 选择已经存在的conda环境 右下角会显示现在的环境。

adb、monkey的下载和安装

adb下载 官网网址:Downloads - ADB Shell 尽量不要下载最新的ADB Kits,因为兼容性可能不太好。 点击下载 ADB Kits 作者下载的版本是1.0.36 解压adb 到指定的目录即可。 然后把adb配置 环境变量。 检查adb是否安装成功

骑砍2霸主MOD开发-作弊模式控制台模式

一.作弊模式开启 config文件路径:C:\Users\Administrator\Documents\Mount and Blade II Bannerlord\Configs\engine_config.txt 修改配置项:cheat_mode 0 → cheat_mode 1 启动游戏后,作弊按键: Ctrl Left Click—传送地图的任意点。Ctrl H—主角满血。CTRL Shift H—主角全…

C语言中的字符串操作函数自定义实现:标准版与限定长度版

目录 1. 标准字符串操作函数自定义实现 (a) 自定义strcpy函数 (b) 自定义strcat函数 (c) 自定义strcmp函数 2. 限定长度字符串操作函数自定义实现 (a) 自定义strncpy函数 (b) 自定义strncat函数 (c) 自定义strncmp函数 对字符串的操作是不可或缺的一部分。标准库提供了…

【.NET Core】 多线程之(Thread)详解

【.NET Core】 多线程之(Thread)详解 文章目录 【.NET Core】 多线程之(Thread)详解一、概述二、线程的创建和使用2.1 ThreadStart用于无返回值,无参数的方法2.2 ParameterizedThreadStart:用于带参数的方法 三、线程的…

REVIT二次开发生成三维轴网

步骤1 确定轴网 步骤2 生成3D轴网 using System; using System.Collections.Generic; using System.Linq; using System.Text;

C#winform上位机开发学习笔记2-串口助手的中文支持功能添加

分为两步: 1.串口接收支持中文显示 1.1.在软件初始化时写入此代码以支持汉字显示 //串口接收支持中文显示serialPort1.Encoding Encoding.GetEncoding("GB2312"); //串口1的解码支持GB2312汉字 2.串口发送支持中文输出 //支持中文输出Encoding Chine…

文心一言使用分享

ChatGPT 和文心一言哪个更好用? 一个直接可以用,一个还需要借助一些工具,还有可能账号会消失…… 没有可比性。 通用大模型用于特定功能的时候需要一些引导技巧。 import math import time def calculate_coordinate(c, d, e, f, g, h,…

【Origin绘图系列第3棒】箱型图:

Origin绘制箱型图 箱型图(Boxplots)案例1:基本绘制参考 箱型图(Boxplots) 案例1:基本绘制 选择箱型图后界面如下: 设置分组,如下设置, 图形如下所示: 根…

防火墙部署安全区域实验

目录 实验拓扑web登防火墙配置对象配置安全策略配置NAT配置安全策略测试抓包测试 实验拓扑 安全区域如下图: web登防火墙 按接口划分各区域,GE1/0/1为trust区域,内网是信任区域。 配置如下,可起别名方便操作,区域为t…

C++后端笔记

C后端笔记 资源整理一、高级语言程序设计1.1 进制1.2 程序结构基本知识1.3 数据类型ASCII码命名规则变量间的赋值浮点型变量的作用字符变量常变量 const运算符 二、高级语言程序设计(荣) 资源整理 C后端开发学习路线及推荐学习时间 C基础知识大全 C那…

ICCV2023 | PTUnifier+:通过Soft Prompts(软提示)统一医学视觉语言预训练

论文标题:Towards Unifying Medical Vision-and-Language Pre-training via Soft Prompts 代码:https://github.com/zhjohnchan/ptunifier Fusion-encoder type和Dual-encoder type。前者在多模态任务中具有优势,因为模态之间有充分的相互…

Docker部署Flask项目

Docker部署Flask项目 一、准备项目代码二、编写Dockerfile三、服务器部署 一、准备项目代码 这里写了一个简单的Flask的demo&#xff0c;源代码如下&#xff1a; from flask import Flaskapp Flask(__name__)app.route("/") def index():return "<h1 styl…

解决Windows下VSCode控制台乱码问题

我们在Windows使用VSCode编写C/C程序时&#xff0c;如果代码中的中文字符串使用的是UTF8编码&#xff0c;且代码内没有设置控制台的输出编码&#xff0c;或者编译时没有指定运行时编码&#xff08;GCC可以在编译时使用-fexec-charsetGBK来指定运行时的字符串编码&#xff1b;cl…

解决Uniapp插件市场试用原生插件项目 没有MD5签名安卓无法自定基座打包的情况

Uniapp插件市场中&#xff0c;有些插件是原生插件&#xff0c;必须使用自定义基座才能打包。但是传统keytool命令&#xff0c;已经无法看到安卓证书的MD5签名。现采用Android Studio查询signingReport的办法获取证书的MD5签名&#xff0c;并对插件的示例项目进行打包运行。一、…

c++基础3

一 、构造函数的初始化列表 可以指定成员对象的初始化方式 构造函数的初始化列表是在 C 中用于初始化成员变量的一种机制。它在构造函数的参数列表之后&#xff0c;构造函数的函数体之前使用&#xff0c;并使用冒号 : 分隔。初始化列表可以用于给成员变量赋初值&#xff0c;而不…

ycsb压测mongodb

下载解压 https://github.com/brianfrankcooper/YCSB/releases/download/0.17.0/ycsb-mongodb-binding-0.17.0.tar.gz tar -zxvf ycsb-mongodb-binding-0.17.0.tar.gzycsb提前已经在workload文件夹下准备好了几个压测场景分别对应workload[a:f] workloads/workloada 样例 …