原标题:如何在数据库迁移中保证数据一致性?

作者 | 王斌

译者 | 平川

策划 | 万佳

在分布式系统中,保持数据一致非常困难,而且很容易出错。在本文中,我们将探索一种在迁移期间保持数据一致性的方法,并且这种方法的停机时间较短。

当一个系统存在很长一段时间后,经常会使用更新的技术来提高性能、可维护性或添加新特性。其中一个变化可能会是使用哪个数据库。这可能是最困难的改变。在迁移过程中,有两个数据源,这使得该系统成为一个分布式系统。在分布式系统中,保持数据一致非常困难,而且很容易出错。在本文中,我们将探索一种在迁移期间保持数据一致性的方法,并且这种方法的停机时间较短。

1前提条件

为了使用本文描述的方法,需要满足一些要求:

源数据库支持捕获数据更改(CDC)的方法,如 MySQL 的 bin log。

源数据库可以导出一致的数据,并且可以在数据更改日志中标记位置。

目标数据库支持 ACID 事务。

源和目标数据库都支持读写权限控制。

2步骤

制定以下迁移步骤的两个基本想法:

在给定的时间点上,客户端只向其中一个数据库写入,从而避免了分布式事务易出错、处理速度慢的问题。

通过设置数据库权限来实现数据库切换。这比从客户端代码切换要快,而且更容易确保所有客户端都切换。

下面是具体步骤。

1. 将源数据库转储到目标数据库

首先,我们需要源数据库可以导出一致的数据。标记好已转储的位置。例如,在 MySQL 中,可以在使用 mysqldump 转储数据库时带上 --master-data 选项,这样生成的文件中就会记录 bin log 日志的位置(使用文档)。从源数据库获得所有数据后,可以将它们插入目标数据库。

https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html#option_mysqldump_master-data

因为这是第一步,所以即使失败了也很容易处理:重新开始即可。因此,重要的是,在导入转储数据时,任何错误都要捕获。

2. 捕获源数据库的更改

下一步是捕获源数据库的更改。例如,在 MySQL 中,可以使用 bin log 捕获更改并将其插入到目标数据库中。因为上一步记录了开始位置,所以我们知道从哪里开始解析和导入更改。

在导入时保持更改顺序非常重要。所以最好是只使用一个进程来解析和导入更改。这个步骤非常具有挑战性:这一步性能很重要。同步所有更改的时间就是迁移所需的停机时间。

我们还需要确保,即使出现系统故障,也不会错过任何更改或多次导入任何更改。因此,记录更改日志的位置非常重要。我们可以使用与导入数据相同的事务将位置写入目标数据库,这非常方便。这样,位置就可以与我们导入的数据保持同步。

3. 拒绝客户端到目标数据库的写操作

使用单一数据源是一种保持数据一致性的简单方法。到目前为止,我们使用源数据库作为单一数据源,并将更改同步到目标数据库。我们不想让其他写操作把目标数据库搞乱。因此,我们需要设置目标数据库的权限来拒绝来自客户端的所有写操作。例如,在 MySQL 中,只向客户端授予表的 select 权限,并拒绝其他操作。我们允许读取权限,这样在下一步中就可以比较读取结果。

4. 修改客户端,同时对两个数据库进行读取和写入

下一步是让客户端同时对源和目标数据库进行读取和写入。

我们希望首先读 / 写源数据库。如果没有权限错误,则使用此结果,否则使用来自目标数据库的读 / 写结果。

对目标数据库的读 / 写操作有两个目的:

在切换到目标数据库之前,我们可以通过比较读结果和写操作来验证目标数据库是否按预期工作。注意,目标数据库可能存在同步延迟,因此结果可能会不同。但是我们可以根据相同结果的百分比来理解其正确性。

在我们切换到目标数据库之后,读 / 写结果将被视为真实结果。

如果你想确保目标数据库能够处理这些负载,那么在一段时间内允许对目标数据库进行读 / 写操作是个好主意,但这只是作为一个验证,在那之后,目标数据库中的数据会不一致。因此,在我们验证了目标数据库能够处理系统流量之后,我们需要清理目标数据库,并再次从步骤 1 开始。(在这些步骤中,我们不需要修改客户端代码)。

对于错误处理,有两个关键点:

如果源数据库有权限错误,则只使用目标数据库的结果。抛出源数据库的其他错误。

如果没有使用这个结果,则忽略目标数据库的错误,但要确保记录这些错误,以便它不会影响当前操作,同时还要确保切换之前没有错误。

客户端代码如下:

db_operation{

2try {

3source_result = source_db_operation

4} catch (PermissionException e) {

5return target_db_operation

6}

7async {

8// 以下操作异步进行,这样不会影响性能

9try {

10target_result = target_db_operation

11compare_result(source_result, target_result)

12} catch (Exception e) {

13log_error(e)

14}

15}

16return source_result

17}

5. 拒绝客户端对源数据库的访问,并等待更改同步

在对目标数据库的读写操作有信心之后,就可以进行切换了。我们通过更改数据库权限来切换数据库。首先,我们拒绝客户端对源数据库的所有访问。然后等待更改完全同步到目标数据库。在此期间,系统是停机的。因此,从源数据库到目标数据库的更改同步速度决定了它的停机时间。

6. 允许写入目标数据库

在目标数据库完全同步之后,我们可以为所有客户端赋予目标数据库权限。在此之后,系统就再次在线了,数据库已完全切换。

7. 可选:如果出现任何错误,则回退到源数据库

如果到目前为止一切顺利,那就太好了。但情况并非总是如此。也许目标数据库无法处理新的流量(这就是我们说步骤 4 的测试很重要的原因),在这种情况下,我们就需要回退到源数据库。

如果是在迁移期间丢失了提交的数据,那不是什么大问题,回退也比较简单:

允许访问源数据库。在此之后,客户端应该再次使用源数据库。

清理目标数据库,并重新从头开始。

如果保存提交的数据并保持一致性非常重要,那么在第 5 步之前,我们应该设置一种机制来捕获从目标数据库到源数据库的更改,并在第 6 步之后标记更改位置。那么,回退步骤将是下面这样:

拒绝对目标数据库的所有写操作。

从目标数据库向源数据库同步(在同步完成之后停止同步程序)。

允许访问源数据库。

清理目标数据库并重新开始。

从目标数据库到源数据库的同步非常危险且难以测试,因此,在步骤 4 中测试目标数据库能否处理新的流量就非常重要。

8. 清理客户端代码

切换到目标数据库之后,我们就可以清除访问源数据库的代码了。这样,数据库迁移就大功告成了!

原文链接:

https://www.binwang.me/2020-11-29-Keep-Data-Consistency-During-Database-Migration.html返回搜狐,查看更多

责任编辑:

mysql数据迁移数据一致性检教6_如何在数据库迁移中保证数据一致性?相关推荐

  1. go 获得 mysql 实际运行 SQL,Golang实践录:一个数据库迁移的代码记录

    实现一个数据库迁移的案子.有些知识点值得记录. 技术框架 github.com/go-xorm/xorm:数据库操作 github.com/denisenkom/go-mssqldb:sqlserve ...

  2. yii 执行指定迁移文件_Web 云开发 · 云开发数据库迁移指南

    云开发数据库 云开发为我们提供了一个 JSON 文档型数据库(NoSQL),并集成了 「增删改查」 等 API,操作方便,简单易懂.并且相比传统数据库而言它具有「高性能的数据库读写服务」,「可以直接在 ...

  3. 数据库迁移_【干货分享】DM数据库迁移方法(物理迁移)

    在数据库的维护过程中,可能涉及换服务器,或者需要现网数据库环境测试的情况,这时,最简单快速的办法就是将源数据库相关的文件拷贝到目标主机,然后注册数据库实例服务.这就是数据库的物理迁移过程,可以是从wi ...

  4. mysql数据库存歌曲_教你如何爬取某音乐网站歌曲数据

    实现原理:跨站请求.伪装请求头.调用官方API接口. 1.首页打开目标网站,目标网站地址:http://autumnfish.cn/webmusic/index.html#/discovery 该网站 ...

  5. php foreach 为什么在if条件下多条数据只取出一条数据_微信大牛教你深入了解数据库索引...

    ​| 作者 刘国斌,腾讯微信事业群研发工程师,目前从事企业微信的后台研发工作,已经参与企业微信消息系统.群聊.客户联系等企业微信多个核心功能的迭代. 数据库查询是数据库的最主要功能之一.我们都希望查询 ...

  6. app怎么调用mysql数据_手机app怎么调用php操作数据库的接口?

    做毕设项目,现在需求很简单,php文件放在服务器上,作用是获取mysql数据库的数据. 服务器端php代码如下: header('Access-Control-Allow-Origin:*'); // ...

  7. 织梦网站 mysql,织梦(DEDECMS)网站程序及数据库迁移搬家教程

    对于新手来说,网站程序和数据库搬家是最件非常痛苦的事情,稍有不慎就导致数据丢失或数据库连接百试不灵.织梦的搬家,怎么才能做到最简单最安全呢?笔者将带着大家来解决完整搬家问题,以及搬家过程中需要注意的事 ...

  8. 加载mySQL数据到内存_【测试验证】数据库加载到内存占用大小

    介绍 数据库大小加载到内存占用是不是数据库的本身大小哪?今天忽然突发奇想于是就测试一下.首先我要说明的是我是在EF框架下进行测试的,不知道会不会与ado.net连接方式差生不同的结果,我仅仅是做记录, ...

  9. emqtt数据存储mysql,数据存储 - MongoDB 消息存储 - 《EMQ X Enterprise v3.0 中文文档》 - 书栈网 · BookStack...

    MongoDB 消息存储 配置 MongoDB 消息存储 配置文件: emqx_backend_mongo.conf 配置 MongoDB 服务器 支持配置多台 MongoDB 服务器连接池:## M ...

最新文章

  1. 一行命令实现录屏,支持热键和鼠标操作,区域、帧率、格式任你选择
  2. 告别2010,迎来2011
  3. 工业机器人 郝卫东_2020年第一季度工业技术(T类)馆配畅销榜TOP50
  4. 万物新生(爱回收)递交赴美上市招股书,平台服务收入年复合增长达627.7%
  5. python 列表写入excel_Python将MySQL表数据写入excel
  6. 大剑无锋之Spark中的Driver是什么?【面试推荐】
  7. ASP.NET Core文件上传、下载与删除
  8. A1107班拜年视频录制过程记录
  9. 计算机管理 没有适当的权限,提示没有合适的权限访问怎么办
  10. lesson6 DAAD转换与单片机接口
  11. c语言课程设计类层次图,C语言课程设计————写下流程图! 谢谢
  12. 教程——Wind Turbine Maintenance(Agents)
  13. STM32H750 开启 SAI 模块
  14. 2021年华为Java面经,顺利收获Offer
  15. bootstrap文件上传插件
  16. php中round(),PHP round( )用法及代码示例
  17. python求极限_数学——函数极限知识以及sympy库的limit
  18. 计算机保研面试题——操作系统
  19. 软考中项:常考知识点及案例分析要点总结
  20. 许家印投资FF,贾跃亭能否起死回生?

热门文章

  1. tcl脚本学习十一:proc应用 (带默认参数)
  2. 如何解决IIS7上传文件大小限制【转】
  3. Jquery中使用setInterval和setTimeout
  4. 用java程序将GBK字符转成UTF-8编码格式(转)
  5. AB1601低功耗时烧写代码注意事项
  6. 基于区块链的健康链系统设计与实现(4)系统实现
  7. 定时器Timer和Ticker
  8. 数据结构--双向链表
  9. 17-Translation (XLAT) Tables Library
  10. Sphinx文档的展示-个人学习笔记