数据迁移方案

article/2025/10/25 9:48:35

 一、数据迁移背景

问题场景:

现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态切换到分库分表上?

1.1 停机迁移方案

我先给你说一个最 low 的方案,就是很简单,大家伙儿凌晨 12 点开始运维,网站或者 app 挂个公告,说 0 点到早上 6 点进行运维,无法访问。

接着到 0 点停机,系统停掉,没有流量写入了,此时老的单库单表数据库静止了。然后你之前得写好一个导数的一次性工具,此时直接跑起来,

然后将单库单表的数据哗哗哗读出来,写到分库分表里面去

导数完了之后,就 ok 了,修改系统的数据库连接配置啥的,包括可能代码和 SQL 也许有修改,那你就用最新的代码,然后直接启动连到新的分库分表上去。

验证一下,ok了,完美,大家伸个懒腰,看看看凌晨 4 点钟的北京夜景,打个滴滴回家吧。

但是这个方案比较 low,谁都能干,我们来看看高大上一点的方案。

1.2 双写迁移方案 

简单来说,就是在线上系统里面,之前所有写库的地方,增删改操作,除了对老库增删改,都加上对新库的增删改,这就是所谓的双写,同时写俩库,老库和新库

然后系统部署之后,新库数据差太远,用之前说的导数工具,跑起来读老库数据写新库,写的时候要根据 gmt_modified 这类字段判断这条数据最后修改的时间,

除非是读出来的数据在新库里没有,或者是比新库的数据新才会写。简单来说,就是不允许用老数据覆盖新数据

导完一轮之后,有可能数据还是存在不一致,那么就程序自动做一轮校验,比对新老库每个表的每条数据,接着如果有不一样的,就针对那些不一样的,从老库读数据再次写。

反复循环,直到两个库每个表的数据都完全一致为止。

接着当数据完全一致了,就 ok 了,基于仅仅使用分库分表的最新代码,重新部署一次,不就仅仅基于分库分表在操作了么,还没有几个小时的停机时间,很稳。

所以现在基本玩儿数据迁移之类的,都是这么干的。

二、数据迁移扩展

项目初始,是单库,分了2个表 就可以满足业务数据需求。

随着时间推移,多年后,数据越来越多,当前的数据库设计已经不能满足当前设计。

于是,需要如上图一样,进行分库再分表。

 2.1 同步双写方案

 如上图所示

1. 应用还是保持从旧库中读写数据

2. 编写个应用,通过canal将增量数据通过新的分库分表规则也同时写入新库

3. 同时 编写个旧数据的迁移的工具,通过新的分库分表规则写入新库。

4. 旧数据迁移完成后,验证新旧库中数据是否一致,一致后,既可切换位新库。

三、具体的迁移方案

双写方案,也是一个高可用的平滑迁移方案,这个方案主要分为四个步骤。

数据迁移前,上游业务应用通过旧的服务访问旧的数据

3.1 步骤一

双写,写旧库,同时写新库

服务进行升级,对“旧库上的数据修改”(这里的修改,为数据的insert, delete, update),在新库上进行相同的修改操作,这就是所谓的“双写”

主要修改操作包括:

(1)旧库与新库的同时insert;

(2)旧库与新库的同时delete;

(3)旧库与新库的同时update;

由于新库中此时是没有数据的,所以双写旧库与新库中的affect rows可能不一样,不过这完全不影响业务功能,只要不切库,依然是旧库提供业务服务

这个服务升级风险较小:

(1)写接口是少数接口,改动点较少;

(2)新库的写操作执行成功与否,对业务功能没有任何影响

3.2 步骤二

数据迁移工具

研发一个数据迁移工具,进行数据迁移。这个数据迁移工具,把旧库中的数据转移到新库中来。

这个小工具的风险较小:

1. 整个过程依然是旧库对线上提供服务;

2. 小工具的复杂度较低;

3. 任何时间发现问题,都可以把新库中的数据干掉重来;

4. 可以限速慢慢迁移,技术同学没有时间压力;

数据迁移完成之后,就能够切到新库提供服务了么?

答案是肯定的,因为前置步骤进行了双写,所以理论上数据迁移完之后,新库与旧库的数据应该完全一致。

由于迁移数据的过程中,旧库新库双写操作在同时进行,怎么证明数据迁移完成之后数据就完全一致了呢?

 

如上图所示:

1. 左侧是旧库中的数据,右侧是新库中的数据;

2. 按照primary key从min到max的顺序,分段,限速进行数据的迁移,假设已经迁移到now这个数据段,

数据迁移过程中的修改操作分别讨论:

1. 假设迁移过程中进行了一个双insert操作,旧库新库都插入了数据,数据一致性没有被破坏

2. 假设迁移过程中进行了一个双delete操作,这又分为两种情况

情况一:假设这delete的数据属于[min,now]范围,即已经完成迁移,则旧库新库都删除了数据,数据一致性没有被破坏;

情况二:假设这delete的数据属于[now,max]范围,即未完成迁移,则旧库中删除操作的affect rows为1,新库中删除操作的affect rows为0,

但是数据迁移工具在后续数据迁移中,并不会将这条旧库中被删除的数据迁移到新库中,所以数据一致性仍没有被破坏;

3. 假设迁移过程中进行了一个双update操作,可以认为update操作是一个delete加一个insert操作的复合操作,所以数据仍然是一致的。

除非,在一种非常极限的情况下:

1. 数据迁移工具刚好从旧库中将某一条数据X取出;

2. 在X插入到新库中之前,旧库与新库中刚好对X进行了双delete操作;

3. 数据迁移工具再将X插入到新库中;

这样,会出现新库比旧库多出一条数据X。

但无论如何,为了保证数据的一致性,切库之前,还是需要进行数据校验的

3.3 步骤三

数据校验工具

在数据迁移完成之后,需要使用数据校验的小工具,将旧库和新库中的数据进行比对,完全一致则符合预期,如果出现步骤二中的极限不一致情况,则以旧库中的数据为准

这个小工具的风险依旧很小:

1. 整个过程依然是旧库对线上提供服务;

2. 小工具的复杂度较低;

3. 任何时间发现问题,大不了从步骤二开始重来;

4. 可以限速慢慢比对数据,技术同学没有时间压力;

 3.4 步骤四

切到新库

数据完全一致之后,将流量切到新库,完成平滑数据迁移

至此,升级完毕,整个过程能够持续对线上提供服务,不影响服务的可用性。

3.5 总结

双写方案,四个步骤:

1. 服务进行升级,记录“对旧库上的数据修改”进行新库的双写;

2. 研发一个数据迁移小工具,进行数据迁移;

3. 研发一个数据比对小工具,校验数据一致性;

4. 流量切到新库,完成平滑迁移;

数据迁移方案、同步双写方案、数据迁移


http://chatgpt.dhexx.cn/article/heapC4AU.shtml

相关文章

数据迁移工具

1.Kettle Kettle是一款国外开源的ETL工具,纯Java编写,绿色无需安装,数据抽取高效稳定 (数据迁移工具)。 Kettle 中有两种脚本文件,transformation 和 job,transformation 完成针对数据的基础转换,job 则完成整个工作流的控制。 Kettle 中文名称叫水壶,该项目的主程序…

数据迁移工具,用这8种就够了!!!

前言 最近有些小伙伴问我,ETL数据迁移工具该用哪些。 ETL(是Extract-Transform-Load的缩写,即数据抽取、转换、装载的过程),对于企业应用来说,我们经常会遇到各种数据的处理、转换、迁移的场景。 今天特地给大家汇总了一些目前…

数据迁移工具,用这8种就够了

前言 最近由于工作需要需要进行数据迁移,那么ETL数据迁移工具该用哪些呢? ETL(是Extract-Transform-Load的缩写,即数据抽取、转换、装载的过程),对于企业应用来说,我们经常会遇到各种数据的处理、转换、迁移的场景。…

电脑文件软件搬家迁移十大工具

10 大适用于 Windows 的数据迁移软件。 数据迁移至关重要,几乎所有组织都依赖于此。如果您认为数据传输不是一件容易的事,那么数据迁移软件可以帮上忙。 1、奇客电脑迁移 将现有操作系统、软件、文件迁移到 新电脑的最佳方法之一是使用名为奇客电脑迁移…

如何将旧电脑数据迁移到新电脑?10 款数据迁移软件工具分享

最好的数据迁移软件可以自动完成将数据从一个系统传输到另一个系统的过程。人们使用数据迁移软件的最常见原因是当他们从一个应用程序切换到另一个应用程序时。 10 款数据迁移软件 公司或个人出于各种原因移动数据。也许他们已经向他们的技术堆栈添加了新的资产或应用程序&…

‘v-model‘ directives require the attribute value which is valid as LHS.

哈喽,大家好啊。最近写vue项目的时候遇到这样的问题 最后才知道:v-modle指令要求属性值必须与LHS一样有效 原因就是:v-model 将始终把Vue实例的data视为数据真实的来源。应该在组件的Js里面打data中声明初始值,不能要求v-model一次…

【小知识】linux下ls与ll的区别

在 Linux 系统中,ls 和 ll 命令都是用来列出目录内容的命令,它们的区别如下: ls 命令:是一个简单的文件列表命令,它会列出目录下的文件和子目录的名称,并显示它们的属性和权限等信息。 ll 命令:…

LHS与RHS查询

本文基于《你不知道的Javascript》编写。 JavaScript中在预编译后执行代码时对变量的查询分为LHS(Left-Hand-Side)查询和RHS(Right-Hand-Side)查询。 是一个赋值操作的左侧和右侧的意思; (一)看一个转换后的例子&…

JavaScript中的LHS和RHS查询

文章是本人大三期间的学习笔记,一些论断取自书籍和网上博客,碍于当时的技术水平有一些写得不够好的地方,可以在评论处理智讨论~ 问题来源于《你不知道的JavaScript(上卷)》,文章部分论述截自原书。 简述编译…

drools rule (二) LHS语法详解

1.什么是LHS? 左手边(LHS)是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素,并且在创建新的WorkingMemory会话时将激活一次。 rule "no CEs" when…

ls -lh

ls -lh 可以在列出文件的同时查看文件的大小

拉丁超立方体抽样(LHS)研究(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜…

linux查看端口和pid

一.查看进程常用操作 netstat说明: netstat命令参数: -t : 指明显示TCP端口   -u : 指明显示UDP端口   -l : 仅显示监听套接字(所谓套接字就是使应用程序能够读写与收发通讯协议(protocol)与资料的程序)   -p : 显示进程标识符和程序名称&#xf…

Linux 查看已使用的端口

指定端口 已开放: 未开放: 查看所有端口 完!

Linux查看端口使用情况并开启端口

一、查看端口是否被使用 方法一: lsof -i:8050 方法二 telnet测试命令: telnet ip地址 端口 方法三: netstat -tlnp|grep 8050 方法四:如果是防火墙已开启的状态查看已经开放的端口 firewall-cmd --list-ports 查看防火墙状…

linux查看端口TCP连接情况

netstat -ano | grep 19833 #查看19833端口的连接情况 从上图结果可以分析出一些信息: 1、第一个为服务器的监听套接字,其监听队列中存在两个连接未处理,而整个服务器连接到19833端口的连接才3个。 2、其中源主机端口为37534和37532的…

Linux查询端口命令

一、使用netstat 检查端口 netstat是一个命令行工具,可以提供有关网络连接的信息。 显示所有已开放端口,请使用以下命令:netstat -anp 要列出正在侦听的所有 TCP 或 UDP端口,包括使用端口和套接字状态的服务,请使用以下…

linux 端口号查看

用netstat检查监听端口 sudo netstat -tunlp 此命令中使用的选项具有以下含义: -t-显示TCP端口。 -u -显示UDP端口。 -n -显示数字地址而不是解析主机。 -l -仅显示监听端口。 -p -显示侦听器进程的PID和名称。仅当你以root用户或 sudo 用户身份运行命令时&#xf…

Linux查看端口是否开放

linux查看开放端口的方法: 1. 使用rpm安装nmap工具,执行 "nmap 127.0.0.1" 命令查看本机开放的端口 2. 执行 "netstat -anp" 命令进行查看开放的端口 3. 使用rpm安装slof工具,执行 "lsof -i:8085" 命令查看…

linux如何查看端口被哪个进程占用

亲测可用,若有疑问请私信 本文介绍linux如何查看端口被哪个进程占用的方法: 1、lsof -i:端口号 2、netstat -tunlp|grep 端口号 都可以查看指定端口被哪个进程占用的情况 【步骤一】lsof -i lsof -i 用以显示符合条件的进程情况,lsof(l…