pt-osc改表导致数据不一致案例分析

2016-06-10 李丹 dba流浪猫

我们平时除了解决自己问题外,有时候也会协助圈内人士,进行一些故障排查,此案例就是帮某公司DBA进行的故障分析,因为比较典型,特分享一下,但仅仅是分享发生的过程,不对该案例的产生以及如何避免做过多评价!

pt-online-schema-change:是对大表进行在线alter操作,并尽量避免影响线上业务,这是最优秀的mysql管理工作之一,在平时的工作中,帮助我们胜多。

环境说明

pt-osc 版本:percona-toolkit-2.2.14

mysql版本: percona-server-5.5

数据库架构:双主复制(本次pt-osc改表是在未在线主库上执行的)

问题描述

某天接到圈内朋友求助,反馈使用pt-online-schema-change 添加字段却意外产生了死锁的情况,并且数据可能有问题了,哥们百思不得骑姐希望我能帮忙分析分析。不过因线上环境没法测试复现,因此只给了死锁发生时的引擎日志(执行 SHOW ENGINE  innodb STATUS 查看)。

我们来看看当时存储引擎的日志情况,这里为了方便只截取了事务相关日志,其他日志信息略过,具体日志如下:

TRANSACTION1

*** (1) TRANSACTION:

TRANSACTION 107BF2CDD, ACTIVE 1 sec setting auto-inc lock

mysql tables in use 2, locked 2

LOCK WAIT 4 lock struct(s), heap size 1248, 1 row lock(s), undo log entries 2

MySQL thread id 6, OS thread handle 0x7fd210190700, query id 1080843123 Reading event from the relay log

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:

TABLE LOCK table `redcliff`.`_rider_new` trx id 107BF2CDD lock mode AUTO-INC waiting

这里我们能读懂两个信息:

1:事务是从relaylog 读取日志                                                      2:事务1(事务id为107BF2CDD)正在等待_rider_new表AUTO-INC锁

TRANSACTION2

*** (2) TRANSACTION:

TRANSACTION 107BF2CDC, ACTIVE 1 sec fetching rows

mysql tables in use 2, locked 2

253 lock struct(s), heap size 31160, 10864 row lock(s), undo log entries 10616

MySQL thread id 22433333, OS thread handle 0x7fc781b16700, query id 1080843120 127.0.0.1 dwbdba_mgr Sending data

INSERT LOW_PRIORITY IGNORE INTO `redcliff`.`_rider_new`

************************************(省略中)

`frozen_provision`, `bloc…. LOCK IN SHARE MODE  /*pt-online-schema-change 18153 copy nibble*/

*** (2) HOLDS THE LOCK(S):

TABLE LOCK table `redcliff`.`_rider_new` trx id 107BF2CDC lock mode AUTO-INC

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 636 page no 4599 n bits 112 index `PRIMARY` of table

`redcliff`.`rider` trx id 107BF2CDC lock mode S waiting

*** WE ROLL BACK TRANSACTION (1)

我们能读懂如下信息:

1、事务2(事务id 为107BF2CDC)持有表_rider_new 的auto-inc 自增锁

2、事务2等待rider表S锁

3、pt-osc工具通过LOCK IN SHARE MODE来实现读取当前读取之后还需要保证其他并发事务不能修改当前读取的记录,确保数据的新老数据的100%一致,故要对读取记录加S锁

通过上面读懂的信息我们分析如下:

事务1

1、Reading event from the relay log 要执行对rider表的修改

(这里事后通过解析relaylog确认是对rider表进行的修改)

故持有rider表记录上的x锁

2、等待_rider_new 表上的auto-inc lock

(注:pt-osc工具对表进行修改会在表上创建增删改三个触发器。故rider表上有已有三个触发器,并且对rider表的update,insert操作触发器触发后会转换为_rider_new表上的replace 操作,在有自增id的表上replace操作会产生新的自增id值)

事务2

1、INSERT LOW_PRIORITY IGNORE INTO `redcliff`.`_rider_new` (`id`, `city_id`,

该语句需要往_rider_new表批量写入数据,这里已经持有 _rider_new 表上的auto-inc lock, 从上面的分析可以看到事务需要等待rider 表上的共享读锁!

删繁就简

事务一:

持有:rider表记录上的x锁

等待:rider_new 表上的auto-inc lock

事务二:

持有:_rider_new 表上的auto-inc lock

等待:rider 表上的S锁

完美的死锁

最后回滚事务1(即复制更新操作被回滚,主从数据不一致)

我的观点

在以上的分析中,我们得出,pt-osc工具在某些情况下,可能会因为死锁回滚而导致数据的不一致,根据原理,我们无法避免,只能尽量缓解(例如: --chunk-size参数设置的更小,或者在TPS极大的线上不使用pt-osc),在mysql online ddl 发展尚不完善的情况下,相信当前mysql DBA 线上使用的改表工具主流还是pt-online-schema-change ,所以希望通过本次的分享让大家少踩点坑,早回家睡会好觉。

时间: 2024-10-12 21:08:31

pt-osc改表导致数据不一致案例分析的相关文章

你知道怎么解决DB读写分离,导致数据不一致问题吗?

目录 前言 为什么产生数据不一致 方案一:利用数据库自身特性 方案二:不解决 方案三:客户端保存法 方案四:缓存标记法 方案五:本地缓存标记 前言 在互联网中大型项目中,读写分离应该是我们小伙伴经常听说的,这个主要解决大流量请求时,提高系统的吞吐量.因为绝大部分互联网产品都是读多写少,大部分都是读请求,很小部分是写请求. 上图: 1.一个主库负责写请求,更新数据2.两个从库负责读请求,可以提高系统吞吐量3.主库和从库之间同步数据 为什么产生数据不一致 上图中业务流程 1.写请求A进行数据更新,但

演示stop暴力停止线程导致数据不一致的问题,但是有些有趣的发现 (2017-07-03 21:25)

如注释所言 /** * Created by weiwei22 on 17/7/3. * * 这里主要是为了演示stop导致的数据不一致的问题.stop会暴力的结束线程并释放锁,所以有可能在恰好写了一半数据的时候,就被stop并释放了锁. * 读线程此时获得锁就有可能读取到不一致的数据. * 但是发现几个有意思的现象: * 1.如果M<N,那么所有的Thread1线程实例都没有机会执行就被干掉了, * 因为新创建的Thread1的实例t1在执行到(1)处时,休息N毫秒,几乎同时主线程执行到(2)

MySQL Innodb表导致死锁日志情况分析与归纳

发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志 案例描述在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志.两个sql语句如下:(1)insert into backup_table select * from source_table(2)DELETE FROM source_table WHERE Id>5 AND titleWeight<32768 AND

MongoDB数据不一致导致的查询数据异常

我这里视查询的state为0,前面几条数据的state却不为1,解决办法是修复数据. db.repairDatabase() 至于导致数据不一致的原因,我还不太清楚,经过多方面资料查询 可能是在程序中,链接数据库是未在安全模式下操作数据库 下面是安全模式下链接数据库操作数据库 MongoClient client = new MongoClient(); client.setWriteConcern(WriteConcern.SAFE);

高并发场景下缓存+数据库双写不一致问题分析与解决方案设计

Redis是企业级系统高并发.高可用架构中非常重要的一个环节.Redis主要解决了关系型数据库并发量低的问题,有助于缓解关系型数据库在高并发场景下的压力,提高系统的吞吐量(具体Redis是如何提高系统的性能.吞吐量,后面会专门讲). 而我们在Redis的实际使用过程中,难免会遇到缓存与数据库双写时数据不一致的问题,这也是我们必须要考虑的问题.如果还有同学不了解这个问题,可以搬小板凳来听听啦. 一.数据库+缓存双写不一致问题引入 要讲数据库+缓存双写不一致的问题,就需要先讲一下这个问题是怎么发生的

MYSQL数据库表排序规则不一致导致联表查询,索引不起作用问题

Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题 表更描述: 将mysql数据库中的worktask表添加ishaspic字段. 具体操作:(1)数据库worktask表新添是否有图片字段ishaspic:新添字段时,报错 [SQL] alter table WorkTask add ishaspic int(10) Null;[Err] 1034 - Incorrect key file for table 'WorkTask'; try to repair it 解决方案:新建

由数据迁移至MongoDB导致的数据不一致问题及解决方案

本文是"我和MongoDB的故事"MongoDB征文比赛的二等奖得主杨庆麟的文章.下面我们一起来欣赏下. 故事背景 企业现状 2019年年初,我接到了一个神秘电话,电话那头竟然准确的说出了我的昵称:上海小胖. 我想这事情不简单,就回了句:您好,我是小胖,请问您是? "我就是刚刚加了你微信的 xxx 啊" 哦--他只是把我的微信昵称报出来了-- 随着深入沟通,了解到对方是某央企保密单位的大数据部门技术负责人,因为目前整个集团在进行数字化转型.在决策过程中,遇到了几个阻

EF里单个实体的增查改删以及主从表关联数据的各种增删 改查

本文目录 EF对单个实体的增查改删 增加单个实体 查询单个实体 修改单个实体 删除单个实体 EF里主从表关联数据的各种增删改查 增加(增加从表数据.增加主从表数据) 查询(根据主表找从表数据.根据从表找主表数据) 修改(修改从表的外键) 删除(删除主从表关系.删除主表数据.删除主从表数据.修改从表数据外键) 补充内容 SaveChanges方法提交多次操作 DbSet.Add方法返回当前实体 源码和系列文章导航 注:本章节多次演示了各种删除,要重复查看效果,需要解开注释初始化数据方法. 一.EF

MYSQL Truncate 引发数据表损坏案例分析

最近发布到市场的版本频繁出现数据库表损坏的情况,具体的现象是select表提示表不存在,但是查看data文件,对应表的ibd和frm文件都在. 通过对多个故障的统计,找到几个频繁出现损坏的表,在分析过程中,发现这些数据表都使用了truncate清除数据,所以怀疑是truncate操作的问题. 设计如下过程来验证这个分析结果: 1. 创建存储过程如下,对一张表模拟频繁调用TRUNCATE DROP PROCEDURE IF EXISTS prcTest5;CREATE PROCEDURE prcT