目前,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设计的校验和算法很复杂。最后,由于校验和sql是分别在主库和备库上面执行,存在一定的时差,若在这个时间段,有新的数据写入,就会造成误判。所以哪位同学有兴趣,还可以对其进行进一步优化。

最后,我简单介绍下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,通过这个聚合函数,将分块中每一行每一列的纳入计算对象,理论上保证了通过一个校验和可以判断主备分块数据是否一致。

mysql集群数据一致性校验的更多相关文章

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

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

  2. MySQL集群的可行方案

    如果单MySQL的优化始终还是顶不住压力时,这个时候我们就必须考虑MySQL的高可用架构(很多同学也爱说成是MySQL集群)了,目前可行的方案有: 一.MySQL Cluster优势:可用性非常高,性 ...

  3. 【MySQL大系】《Mysql集群架构》

    原文地址(微信):[技术文章]<Mysql集群架构> 本文地址:http://www.cnblogs.com/aiweixiao/p/7258444.html 点击关注微信公众号 1.主要 ...

  4. Galera Cluster——一种新型的高一致性MySQL集群架构

    原文链接:https://www.sohu.com/a/147032902_505779,最近被分配定位mysql的问题,学习下. 1. 何谓Galera Cluster 何谓Galera Clust ...

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

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

  6. 2-20 MySQL集群搭建实现高可用

    MySQL集群概述和安装环境 MySQL Cluster是MySQL适合于分布式计算环境的高实用.高冗余版本.Cluster的汉语是"集群"的意思.它采用了NDB Cluster ...

  7. MySQL Cluster(MySQL 集群) 初试

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

  8. mysql 集群+主从同步

    SQL节点: 给上层应用层提供sql访问. 管理节点(MGM):  管理整个集群. 启动,关闭集群. 通过ndb_mgmd命令启动集群 存储/数据节点: 保存cluster中的数据.  数据节点,可以 ...

  9. MySQL集群之五大常见的MySQL高可用方案(转)

    1. 概述 我们在考虑MySQL数据库的高可用的架构时,主要要考虑如下几方面: 如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中 ...

随机推荐

  1. WCF在tcp通道下启用httpget

    关于tcp通道下,启用httpget,必须启用一个http的基地址,如果要启用元数据交换,host中必须开启服务描述. //01 create host Uri tcpBaseAddress = ne ...

  2. 4.1 pair类模板

    在学习关联容器之前,首先先要了解一下STL中的pair类模板,因为关联容器的一些成员函数返回值都是pair对象,而且map 和multimap中的元素都是pair对象. 1)pair类模板定义 pai ...

  3. WinFrom下连接字符串的数据库文件路径问题

    一直以为连接字符串中的系统变量|DataDirectory|就是在ASP.NET中代替App_Data的绝对路径.原来在WinForm程序中也能用|DataDirectory|,不过指代的是exe文件 ...

  4. iOS UIKit:CollectionView之设计 (1)

    collection view(UICollectionView对象)使用灵活和可扩展的布局来描述有序的数据项,其一般情况下以网格的形式来展示内容,但并非一定如此. 1 基础 为了将数据展示在屏幕中, ...

  5. SGU 194. Reactor Cooling(无源汇有上下界的网络流)

    时间限制:0.5s 空间限制:6M 题意: 显然就是求一个无源汇有上下界的网络流的可行流的问题 Solution: 没什么好说的,直接判定可行流,输出就好了 code /* 无汇源有上下界的网络流 * ...

  6. 总结:整理 oracle异常错误处理 .

    5.1 异常处理概念 5.1.1 预定义的异常处理 5.1.2 非预定义的异常处理 5.1.3 用户自定义的异常处理 5.1.4  用户定义的异常处理 5.2 异常错误传播 5.2.1 在执行部分引发 ...

  7. Unity3D游戏开发之小地图的实现

    今天我们来讲一下在Unity3D中怎样实现小地图.首先,我们来一起看看终于实现的效果: 要实现小地图效果,须要实现对于小地图和角色的绘制,所以这里须要用到OnGUI()方法,我们一起来看代码: [cs ...

  8. nginx是什么nginx安装与配置之windows版

    1.nginx是什么 为了快速了解nginx我们先引用网上的nginx介绍: Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP ...

  9. 云如何让App开发更简单?

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 互联网"下半场",移动App开发对于质量.速度的要求更加苛刻.4月初,腾讯云正式上线移动开发平台MobileLine,借 ...

  10. Golang 语言的单元测试和性能测试(也叫 压力测试)

    Golang单元测试对文件名和方法名,参数都有很严格的要求. 例如: 1.文件名必须以xx_test.go命名 2.方法必须是Test[^a-z]开头(T必须大写),func TestXxx (t * ...