目前,mysql在互联网行业使用地如火如荼,很多大型网站都在使用MySQL数据库,通过搭建mysql主备集群,实现高性能,高可用的存储方案。mysql集群的共同特性是通过复制来实现主备间的同步,保证主备数据的一致性。这样才能保证读写分离,备库为主库分担压力,提高整个集群的可用性和性能。

为什么需要数据一致性校验?由于大部分搭建mysql服务的都是PC集群,尤其是在集群达到一定规模后,硬件出故障几乎是必然的。mysql复制是异步复制,当主机出现故障时,就会出现丢数据的可能,造成主备数据不一致,无法正常对外提供服务。另外,当现有的PC集群容量不足时,需要对集群扩容,扩容就涉及到数据迁移。迁移一般都包括全量和增量,在不停服务的情况下,当迁移完数据后,需要校验数据的一致性,保证迁移后不对业务造成影响。

什么是数据一致性?这里仅仅针对mysql,或是关系型数据库,一致性主要包括两方面,表结构一致和数据内容一致。一般情况下,表结构变更相对是少的,而且不一致的概率也很小,即使检查,也相对容易;而导致数据内容不一致的情况很多,所以我们更关心的数据内容的一致性。

如何实现数据一致性校验?一种思路就是逐行逐字段比较主库和备库的表;另外一种思路是,不逐行逐字段比较,取而代之的是分别对主库和备库计算校验和,通过判断校验和是否相同,确定主备库数据是否一致。两种思路都很简单,第一种思路正确性高,但性能比较差,因为返回大量的结果集导致大量的网络IO和磁盘IO;而第二种思路则恰好相反,性能会更好,少了IO,多消耗了一些CPU资源(计算校验和),正确性不如第一种思路。但是考虑到生产环境下,数据时时刻刻都是动态变化的,就没那么简单了。通过对表加锁,可以保证我们在校验时,数据是静态的,待我们顺利完成校验后,再解锁。mysql自带命令CHECKSUM TABLE,就是通过锁表方式来保证数据是静态的。这种方式对于小表,访问量小的表还好,若表非常大,校验需要很长时间,生产环境是不能容忍的。既然要保持静态就需要锁表,可不可以缩短锁表时间呢?pt-table-checksum通过将表分片,每次只对一部分行上锁,这样在校验过程中,一时刻只有部分行被锁住,减少对业务的影响。

目前业界使用比较广泛的是percona公司的pt-table-checksum,下文我将详细介绍该工具的使用和原理,并分析其不足以及可以改进的地方。

pt-table-checksum工具通过在主库上执行一个校验和的sql语句,然后通过复制,相同语句会在从库执行(pt-table-checksum要求复制工作在语句级复制模式下)。通过replace...select语句将校验和结果存储在结果表,然后对比主库和从库的相同块的记录数目和校验和,判断主备库数据是否一致。这里要注意的是,  pt-table-checksum 不是对一个表仅作一个校验和,因为如果表特别大,将会对DB造成很大的负载,影响正常业务。一个表一个校验和就退化到mysql自带命令CHECKSUM TABLE了,不仅需要锁表,而且不准确。pt-table-checksum将表按用户设置的块大小,将表分成若干份,然后对每个块计算一个校验和。这样即使表特别大,分块后也只会锁住部分记录,对DB的负载压力也大大降低。由于多个表校验可以并发,可以大大提高校验效率,通过参数-max-load可以防止load过大。

pt-table-checksum基本能满足我们的日常需求,但是它还有一些需要完善的地方,首先,仅仅支持表粒度的并发,当检查一个大表时,需要耗费大量的时间,另外多表并行执行时,并行度也不能通过参数的设置,而是通过--max-load间接设置。其次,通过分块生成校验和虽然加快了校验速度,但1000行算一个4字节的校验值(默认是一个块1000行),产生冲突的可能性很大,即使pt-table-checksum设计的校验和算法很复杂。最后,仅仅块粒度的不一致还不够,我们需要精确的知道到底是哪一条记录,甚至哪一列不一致,并且给出订正语句,所以哪位同学有兴趣,还可以对其进行进一步优化。

最后,我简单介绍下pt-table-checksum的使用,关于里面的参数的配置我就不一一列举了,感兴趣的同学可以参考http://www.percona.com/doc/percona-toolkit/2.2/pt-table-checksum.html

1.创建用于校验的用户,并授权

grant all privileges on *.* to ptcheck@'%' identified by 'ptcheck';

2.测试table_pt_check表结构

Create Table: CREATE TABLE `table_pt_check` (

`c1` int(11) NOT NULL AUTO_INCREMENT,

`c2` int(11) DEFAULT NULL,

PRIMARY KEY (`c1`)

) ENGINE=InnoDB AUTO_INCREMENT=26672747 DEFAULT CHARSET=utf8

3.校验chuck库中 table_pt_check表

pt-table-checksum --host='127.0.0.1' --user='ptcheck' --password='ptcheck' --port=3306 --databases='chuck' --tables='table_pt_check' --replicate=test.checksums

--replicate=test.checksums,指定校验结果存储在test库中的checksums中。通过上述3个步骤就能检查主备库的数据是否一致了。

校验结果存储表结构如下:

Create Table: CREATE TABLE `checksums` (

`db` char(64) NOT NULL, //库名

`tbl` char(64) NOT NULL,  //表名

`chunk` int(11) NOT NULL,  //分块号

`chunk_time` float DEFAULT NULL, //分块执行时间

`chunk_index` varchar(200) DEFAULT NULL, //分块使用的索引,主键索引或唯一索引

`lower_boundary` text,  //分块的下界值

`upper_boundary` text, //分块的上界值

`this_crc` char(40) NOT NULL, //分块的哈希值

`this_cnt` int(11) NOT NULL, //分块的记录数目

`master_crc` char(40) DEFAULT NULL, //master上分块的哈希值

`master_cnt` int(11) DEFAULT NULL, //master上分块的记录数目

`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

PRIMARY KEY (`db`,`tbl`,`chunk`),

KEY `ts_db_tbl` (`ts`,`db`,`tbl`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

校验主备是否一致的SQL如下:

SELECT db,

tbl,

Sum(this_cnt) AS total_rows,

Count(*) AS chunks

FROM test.checksums

WHERE ( master_cnt <> this_cnt

OR master_crc <> this_crc

OR Isnull(master_crc) <> Isnull(this_crc) )

GROUP BY db, tbl;

通过--explain参数可以展示pt-table-checksum在执行过程的SQL:

replace INTO `test`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc)

select 'chuck', 'table_pt_check', '7', 'PRIMARY', '21685456', '26100570', COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `c1`, `c2`, CONCAT(ISNULL(`c2`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `chuck`.`table_pt_check` FORCE INDEX(`PRIMARY`) WHERE ((`c1` >= '21685456')) AND ((`c1` <= '26100570'))

注意:计算校验和的关键函数BIT_XOR,通过这个聚合函数,将分块中每一行每一列的纳入计算对象,理论上保证了通过一个校验和可以判断主备分块数据是否一致。

转载于:https://www.cnblogs.com/cchust/p/3521650.html

mysql集群数据一致性校验相关推荐

  1. mysql集群保证数据一致性

    mysql集群配置在网站负载均衡中是必不可少的: 首先说下我个人准备的负载均衡方式: 1.通过nginx方向代理来将服务器压力分散到各个服务器上: 2.每个服务器中代码逻辑一样: 3.通过使用redi ...

  2. MySQL Cluster(MySQL 集群) 初试(转)

    作/译者:叶金荣(imysql#imysql.com>),来源:http://imysql.com,欢迎转载. 作/译者:叶金荣(Email: ),来源:http://imysql.cn,转载请 ...

  3. MySQL Cluster(MySQL 集群) 初试

    MySQL Cluster 是MySQL适合于分布式计算环境的高实用.高冗余版本.它采用了NDB Cluster 存储引擎,允许在1个 Cluster 中运行多个MySQL服务器.在MyQL 5.0及 ...

  4. paxos整合mysql_微信开源PhxSQL:高可用、强一致的MySQL集群(转载)

    作者: 陈俊超(junechen@tencent.com),微信后台高级工程师,主要负责微信后台核心模块的分布式架构设计和开发.早期负责微信附近的人,摇一摇,朋友圈,群聊等基础架构.现专注于PhxSQ ...

  5. MySQL集群节点宕机,数据库脑裂!如何排障?

    作者介绍 王晶,中国移动DBA,负责"移动云"业务系统的数据库集成架构设计.运维.优化等工作:擅长技术领域MySQL,获Oracle颁发的"MySQL DBA" ...

  6. mysql 集群_MySQL之PXC集群搭建

    一.PXC 介绍 1.1 PXC 简介 PXC 是一套 MySQL 高可用集群解决方案,与传统的基于主从复制模式的集群架构相比 PXC 最突出特点就是解决了诟病已久的数据复制延迟问题,基本上可以达到实 ...

  7. mysql集群初始化配置_集群Cluster MySQL的安装配置和使用

    集群Cluster MySQL的安装配置和使用 发布时间:2020-05-28 14:20:03 来源:亿速云 阅读:233 作者:鸽子 MySQL Cluster MySQL集群 基本概念: &qu ...

  8. ABP 框架 数据库底层迁移 Mysql 集群

    技术交流,请加QQ群:538327407 我的各种github 开源项目和代码:https://github.com/linbin524 背景 笔者 目前架构的IOT 项目是使用abp 框架作为后台, ...

  9. Mysql 集群双主双从安装使用详细讲解

    文章目录 下载Mysql 安装单机Mysql 配置Mysql集群 双Master配置 master1配置 master2配置 配置说明 双Slave配置 Slave1配置 Slave2配置 双 Mas ...

最新文章

  1. this is incompatible with sql_mode=only_full_group_by
  2. centos6.5 mysql 远程访问_centos6.5 mysql 设置支持远程ip访问
  3. 操作系统中,进程与线程怎么设计的?
  4. 提高c 语言的方法,提高C程序效率的方法
  5. Logistic 回归(sigmoid函数,手机的评价,梯度上升,批处理梯度,随机梯度,从疝气病症预测病马的死亡率...
  6. Linux 命令简单介绍第一课笔记
  7. 【PID优化】基于matlab粒子群和遗传算法PID控制器优化设计【含Matlab源码 1311期】
  8. 远程文件传输工具Filezilla
  9. ASO优化教程:产品预热与应用提交aso主要优化,ASO优化
  10. 微信支付退款 升级版 【码云gvp 】
  11. U大师U盘装系统——启动U盘制作(V1.2.0版)
  12. 动物识别系统代码python_动物识别系统__代码
  13. 常用的几种集合(Map另写)
  14. 年度盘点丨2017十大最佳科技创新产品!
  15. mel频谱--学习笔记
  16. 计算机组原理ppt,计算机组原理1.ppt
  17. 自定义闪屏页广告倒计时view
  18. du命令 – 查看空间
  19. 耶稣有13个门徒,其中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个开始报号:1,2,3,1,2,3……,凡是报到“3”就退出圈子,最后留在圈内的人就是出卖耶稣的叛徒
  20. MES制造执行系统启动篇

热门文章

  1. 如何搭建一个会员网站?零基础用WordPress做一个会员网站视频教程
  2. 在键盘上输入两个int型数据,比较其大小,并输出其中较小的数
  3. pycharm IDEA专业版2016.3.2版本和 python3.5.0 win7 64位安装包 百度云资源共享 及安装和编辑器注册图录
  4. tipask 3.5 出错get_class() expects parameter 1 to be object 解决方案及说明
  5. 从 Google Play 下载 APK 文件
  6. Java:Java实现简单闹钟设计
  7. Flash在线文档阅读器::pdf、doc、docx、xls、xlsx、ppt、pptx、htm、txt、rtf、epub、csv、xdoc等
  8. 树莓派3b GPIO编号
  9. php 继承 父类使用子类,在PHP中使用 来 实现子类和父类之间的继承 。
  10. 2018年「编码美丽」公众号精华帖总结,建议收藏(文末赠书)!