12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
ADADADADAD
mysql数据库 时间:2024-12-25 09:58:08
作者:文/会员上传
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
12-09
在基于MySQL逻辑复制原理的下的主从架构,经常会由于某些缘故产生主从数据不一致,从而导致主从复制进程报错中断。而基于定期去检查从库的show slave status\G的IO线程和SQL线
以下为本文的正文内容,内容仅供参考!本站为公益性网站,复制本文以及下载DOC文档全部免费。
在基于MySQL逻辑复制原理的下的主从架构,经常会由于某些缘故产生主从数据不一致,从而导致主从复制进程报错中断。而基于定期去检查从库的show slave status\G的IO线程和SQL线程的状态,只能确认当前replication是正常的,却无法确认当前主从数据是否一致。幸好percona公司提供pt工具包,其中的pt-table-checksum和pt-table-sync相互配合,在基于一定的前提条件下,可以较好的完成主从数据一致性校验和修复,而不会较大程度上影响线上数据库的性能。
pt-table-checksum的官方文档介绍如下:
pt-table-checksumperformsanonlinereplicationconsistencycheckbyexecutingchecksumqueriesonthemaster,whichproducesdifferentresultsonreplicasthatareinconsistentwiththemaster.TheoptionalDSNspecifiesthemasterhost.Thetool’s“EXITSTATUS”isnon-zeroifanydifferencesarefound,orifanywarningsorerrorsoccur.Thefollowingcommandwillconnecttothereplicationmasteronlocalhost,checksumeverytable,andreporttheresultsoneverydetectedreplica:pt-table-checksumThistoolisfocusedonfindingdatadifferencesefficiently.Ifanydataisdifferent,youcanresolvetheproblemwithpt-table-sync.
pt-table-checksum其实作为校验工具,只负责检测数据的不一致。至于差异数据的修复,而交由pt-table-sync去处理。
使用pt-table-checksum和pt-table-sync工具的前提条件:
1、表必须有主键or唯一索引
2、要求binlog格式为statement。如果线上数据库采用的是binlog日志格式是row的话,可以加 --no-check-binlog-format来规避。
3、不能有存储过程、触发器、event
4、不建议修复有外键约束的表
pt-table-checksum原理可以查阅官方文档或者在测试环境下开启general_log,执行一次pt-table-checksum后翻查其生成的日志即可。基本原理就是在主库创建一个checksums表,存放每个chunk的校验值。通过将表按照主键or唯一索引进行排序,按自适应的行记录数生成若干个chunk,将每个行记录串起来转成字符串,计算CRC32值,然后将该chunk的校验值记录到checksums表中。而这些SQL操作都会以statement的方式传送到从库从而执行相同的操作,如果表的数据有不一致的情况,相应的chunk的校验值也会不一致。
校验&修复的脚本如下:
#!/bin/sh##单向主从架构的话,master_ip是主库的ip地址,slave_ip是从库的ip地址;双向主从架构的话,master_ip是以本库数据为准的主库ip地址,slave_ip是数据被修正的备选主库ip地址。master_ip="192.168.124.131"slave_ip="192.168.124.132"port="3306"user="checksums"password="checksums"pt_sync="/usr/bin/pt-table-sync"pt_check="/usr/bin/pt-table-checksum"mysql="/usr/local/mysql/bin/mysql"mysql_master="$mysql-u$user-p$password-h$master_ip-P$port"mysql_slave="$mysql-u$user-p$password-h$slave_ip-P$port-N"table_file="/tmp/table.txt"diff_table="/tmp/diff.txt"sync_sql="/tmp/sync.sql"###清理环境###if[-e$table_file]thenrm-fr$table_filefiif[-e$diff_table]thenrm-fr$diff_tablefiif[-e$sync_sql]thenrm-fr$sync_sqlfi###初始化checksums表###$mysql_master<<EOF>/dev/null2>&1CREATEDATABASEIFNOTEXISTSPERCONA;USEPERCONA;CREATETABLEIFNOTEXISTSchecksums(dbchar(64)NOTNULL,tblchar(64)NOTNULL,chunkintNOTNULL,chunk_timefloatNULL,chunk_indexvarchar(200)NULL,lower_boundarytextNULL,upper_boundarytextNULL,this_crcchar(40)NOTNULL,this_cntintNOTNULL,master_crcchar(40)NULL,master_cntintNULL,tstimestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,PRIMARYKEY(db,tbl,chunk),INDEXts_db_tbl(ts,db,tbl))ENGINE=InnoDB;EOF###过滤出不包含外键约束、拥有主键or唯一索引的Innodb表。而触发器、存储过程和event需要人工自行过滤掉所涉及的表###$mysql_master<<EOF>/dev/null2>&1selectt.TABLE_SCHEMA,t.TABLE_NAMEfrominformation_schema.tablestinnerjoininformation_schema.statisticssont.TABLE_SCHEMA=s.TABLE_SCHEMAandt.TABLE_NAME=s.TABLE_NAMEinnerjoininformation_schema.key_column_usagekont.TABLE_SCHEMA=k.TABLE_SCHEMAandt.TABLE_NAME=k.TABLE_NAMEwheret.TABLE_TYPE='BASETABLE'andt.ENGINE='InnoDB'ands.NON_UNIQUE=0andk.POSITION_IN_UNIQUE_CONSTRAINTisnullandconcat(k.TABLE_SCHEMA,'.',k.TABLE_NAME)notin(selectconcat(k.TABLE_SCHEMA,'.',k.TABLE_NAME)frominformation_schema.key_column_usagekwherek.POSITION_IN_UNIQUE_CONSTRAINTisnotnull)andt.TABLE_SCHEMAnotin('mysql','percona','sys','information_schema','performance_schema')groupbyt.TABLE_SCHEMA,t.TABLE_NAMEintooutfile"$table_file"FIELDSTERMINATEDBY'|'LINESTERMINATEDBY'\n';EOF###调用pt-table-checksum,做数据差异比对,将结果写入percona.checksums表###foriin$(cat$table_file)dodb=$(echo$i|awk-F\|'{print$1}')tb=$(echo$i|awk-F\|'{print$2}')$pt_check--set-varsinnodb_lock_wait_timeout=120,binlog_format='statement'-u$user-p$password-h$master_ip-P$port--databases=$db--tables=$tb>/dev/null2>&1done###在slave端拼接生成修复的命令集,然后执行生成相应的SQL语句$mysql_slave<<EOF1>$diff_table2>/dev/nullSELECTconcat(db,'|',tbl)FROMpercona.checksumswhere(master_cnt<>this_cntormaster_crc<>this_crcorISNULL(master_crc)<>ISNULL(this_crc))GROUPBYdb,tbl;EOFforiin$(cat$diff_table)dodb=$(echo$i|awk-F\|'{print$1}')tb=$(echo$i|awk-F\|'{print$2}')$pt_sync--print--sync-to-masterh=$slave_ip,P=$port,u=$user,p="$password"--databases="$db"--tables="$tb">>$sync_sqldone###在master侧执行差异SQL,通过复制修复slave侧的数据差异###$mysql_master<<EOF>/dev/null2>&1settx_isolation="REPEATABLE-READ";setbinlog_format=statement;source$sync_sql;EOF##清理临时文件###rm-fr$sync_sql$table_file$diff_table
执行该脚本之前,需要满足几个前提:
1、创建专用的帐号用于校验和修复。
帐号创建语句:GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, PROCESS, FILE, SUPER, REPLICATION SLAVE ON *.* TO 'checksums'@'%'
PS:如果checksums用户的登录IP有限制的话,可以只配置主库和从库的IP即可。
2、目前脚本只能自动过滤出拥有唯一索引or主键、不带外键约束的innodb表,有触发器、存储过程和event所涉及的表,需要人工剔除。
3、该脚本只需部署在主库侧即可。不需要部署在从库侧。
11-20
11-19
11-20
11-20
11-20
11-19
11-20
11-20
11-19
11-20
11-19
11-19
11-19
11-19
11-19
11-19