关于Inception默认配置的一个坑
本文地址:https://www.cnblogs.com/ajiangg/p/9850902.html
约半年前上线了去哪儿的开源审核工具Inception(最近发现已经闭源了.....)以及基于Inception的SQL审核平台Yearning。
一直都用得很爽...直到昨天踩坑。
昨天晚上某个表A新加了一个字段,今早收到业务告警。最后从日志中发现类似如下报错(B表的外键指向了不存在的表_A_old):
Cannot add or update a child row: a foreign key constraint fails (db.B, CONSTRAINT B_ibfk_2 FOREIGN KEY (A_id) REFERENCES _A_old (id))
至于为啥会有外键...这属于历史遗留问题。
第一反应,昨天加字段的时候Inception调用pt-osc出问题了,导致外键没有链接到新表上去。
既然pt-osc会有问题,那就老老实实直接删除外键,重加吧
alter table B drop foreign key B_ibfk_2,add constraint new_key FOREIGN KEY (A_id) REFERENCES A(id)
悲剧的是B表实在是太大,线上跑了一个小时也无果,于是Kill回滚。
回过头来研究为毛B表会指向利用pt-osc进行字段增加时的旧表_A_old呢?
先看看pt-osc关于外键的参数--alter-foreign-keys-method:
(1)auto
自动决定采用哪个方法,如果可以就采用rebuild_constraints,如果不可以就采用drop_swap
(2)rebuild_constraints
该方法采用alter table来drop并re-add链接新表的外键。除非相关的子表太大使得alter过程花费时间过长,一般都采用该方法。这里的花费时间是通过比较子表中的行数和该工具将原始表数据拷贝到新表中的拷贝速率来评估的,如果评估后发现子表中数据能够在少于--chunk-time的时间内alter完成,就会采用该方法。另外,因为在MySQL中alter table比外部拷贝数据的速率快很多,所以拷贝速率是按照--chunk-size-limit来决定的
因为MySQL的限制,外键在改表前后的名字会不一样,改表后新表中的外键名前会加一个下划线,同样,会自动的更改外键相应的索引名字
(3)drop_swap
该方法禁止外键检查(FOREIGN_KEY_CHECKS=0),然后在rename新表之前就将原始表drop掉,这个方法更快而且不会被阻塞,但是风险比较大,风险有二:
在drop掉原始表和rename新表之间有一个时间差,在这段时间里这个表是不存在的,这会导致查询报错
如果rename新表时发生了错误,那问题就大了,因为原始表已经被drop掉了,只能呵呵了
(4)none
这个方法类似没有"swap"的drop_swap,原始表中的所有外键都会被指定到一个不存在的表上
因为原始表(database.tablename)会被rename为database.tablename_old然后drop掉。这种处理外键的方法可以让DBA在需要时取消该工具的这种内置功能
以下是我关于这些参数的测试结果(参数auto略过了):
1.有子表的表A使用最安全的--alter-foreign-keys-method=rebuild_constraints来进行线上更新时,
在copy完父表之后,子表进行更改的方式是alter table B drop foreign key old_key,add constraint new_key FOREIGN KEY (A_id) REFERENCES A(id)。如果子表B比较大,或者A表有好几个子表,那么我还有使用pt-osc的必要么?(对线上的影响可能远远大于直接alter table A带来的影响)
2.有子表的表A使用--alter-foreign-keys-method=none来进行线上更新时,
在copy完父表之后,数据库是直接执行set FOREIGN_KEY_CHECKS=0,然后drop旧表_A_old,然后rename新表_A_new为A。然后就收工了。
所以子表B的外键指向的仍然是pt-osc运行过程中的那张原始父表_A_old
很显然,Inception针对pt-osc的默认配置就是使用--alter-foreign-keys-method=none。
3.有子表的表A使用--alter-foreign-keys-method=drop_swap来进行线上更新时,
在copy完父表之后,数据库是直接执行set FOREIGN_KEY_CHECKS=0,然后drop旧表_A_old,然后rename新表_A_new为_A_old,最后再rename为A。
这样弄完之后父子表的关系仍然存在。(在rename_A_new为_A_old之后,drop旧表_A_old产生的错误指向就被带回来了)
--------------------------------------------------------------------------------------解决方法-----------------------------------------------------------------------------------------------
既然rename表之后,子表的外键关系能跟着变,那么最后线上问题的修正方法也就有了:
现在子表B的外键指向是一个不存在的表_A_old,那么我把现在的A表rename成_A_old,外键关系联系上了之后再重新rename回A表,不就好了么:
alter table A rename _A_old;
alter table _A_old rename A;
经测试没问题,秒恢复正常,然后线上执行OK。
最后回过头来检查Inception关于pt-osc对外键的配置发现:
inception_osc_alter_foreign_keys_method的默认配置是none(即它调用pt-osc的默认参数为--alter-foreign-keys-method=none),所以出现了外键指向不存在的表。
在这里我将配置改成了drop_swap
--------------------------------------------------------------------------------------华丽丽的分割线-----------------------------------------------------------------------------------------------
最后的反省:
数据库有变更的时候,变更完成后需要对相关的业务进行检查。这次虽然我们业务告警系统也在变更之后立即告警了,但却当成“狼来了”给略过了,此处需向老板好好反省......
关于外键,一直都是抵制的。对于新表,新需求一直都禁止使用外键。但旧的系统,很难推动去改掉它。
以前对于外键的一些细节,总是想着反正不会用到,所以遇到这样的细节直接就跳过了。
现在看来,虽然可能一般不会碰到,但这些细节还是需要好好的去理解掌握。
本文地址:https://www.cnblogs.com/ajiangg/p/9850902.html
关于Inception默认配置的一个坑的更多相关文章
- 关于win7+VS2017环境下的opencv-contirb配置的一个坑
问题出现背景: 由于课题需要用到SURF detector, 我依照网上的一下教程,把opencv-contrib的配置了一遍.但是,当我写了一个小demo来测试模块是否能正常使用的时候,程序能正常编 ...
- python的默认参数的一个坑
前言 pass 正文 在 https://docs.python.org/3/tutorial/controlflow.html#default-argument-values 中,有这样一段话 Im ...
- Druid连接池默认配置和坑
一.公司默认配置 ds_0: !!com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: ...
- 关于fastjson的一个坑:输出json时,bean对象属性首字母默认被小写
fastjson 是一个性能很好的 Java 语言实现的 JSON 解析器和生成器,来自阿里巴巴. 主要特点: 快速FAST: 比其它任何基于Java的解析器和生成器更快,包括jackson 强大:支 ...
- dubbox注解的一个坑
我和我同事Daniel排查的一个问题,原文是我同事Daniel写的,我做了些修改了补充. 我们dubbox的provider端有很多service开发时没有考虑到幂等问题,于是只能暂时关掉dubbo的 ...
- CentOS 7下升级MySQL5.7.23的一个坑
发现CentOS 7下升级MySQL5.7.23的一个坑,以前面升级到MySQL 5.7.23的一个集群为例 在我们环境下打开文件描述符个数的参数open_files_limit在MySQL 5.6. ...
- 关于props default 数组/对象的默认值应当由一个工厂函数返回
export default {props: { xAxisData: { type: Array, default: [] }, },这是我的代码 报错是Invalid default va ...
- SpringBoot整合log4j2进行日志配置及防坑指南
写在前面 最近项目经理要求将原先项目中的日志配置logBack,修改为log4j2,据说是log4j2性能更优于logback,具体快多少,网上有说快10多倍,看来还是很快的,于是新的一波挑战又开始了 ...
- 记前端状态管理库Akita中的一个坑
记状态管理库Akita中的一个坑 Akita是什么 Akita是一种基于RxJS的状态管理模式,它采用Flux中的多个数据存储和Redux中的不可变更新的思想,以及流数据的概念,来创建可观察的数据存储 ...
随机推荐
- git版本管理规范
一.基本开发流程: 二.分支命名 2.1主分支 ① master :随时可供在生产环境中部署的代码 ② dev: 保存当前稳定并且最新的开发分支(多人开发同一分支) 2.2辅助分支 主要用于新功能的并 ...
- 使用 Mutex 实现进程间同步
我们知道 Mutex 互斥量是可以用在线程间同步的,线程之间共享进程的数据,mutex 就可以直接引用.而进程有自己独立的内存空间,要怎样将它应用在进程间同步呢?为了达到这一目的,可以在 pthrea ...
- @property详解,@property修饰符以及各个修饰符区别(上)
相信很多参加过面试的人员很多都会被问到:weak与assign的区别,copy与strong的区别.如果你仅仅说一点点copy一般对NSString,weak对于控件的修饰,assign对于基本类型, ...
- [转]OmniLayer / omnicore API 中文版
本文转自:https://www.codetd.com/article/1692438 JSON-RPC API Omni Core是Bitcoin Core的一个分支,其Omni协议功能支持作为顶层 ...
- 【转载】C#工具类:Json操作帮助类
Json序列化和反序列化在程序开发中时常会遇到,在C#中可以使用很多种方法实现对数据的Json序列化和反序列化,封装一个Json操作工具类来简化相应的操作,该工具类中包含以下功能:对象转JSON.数据 ...
- [MySQL] INFORMATION_SCHEMA 数据库包含所有表的字段
sql注入后可以通过该数据库获取所有表的字段信息 1. COLLATIONS表 提供有关每个字符集的排序规则的信息. COLLATIONS表包含以下列: COLLATION_NAME 排序规则名称. ...
- 解决org.hibernate.HibernateException: identifier of an instance of com.ahd.entity.Order was altered from2 to 0
错误信息 严重: Servlet.service() for servlet [springmvc] in context with path [/order] threw exception [Re ...
- 买or不买?如何测试博彩公司赔率是否合理?
世界杯期间,烧烤店.酒吧都热闹起来了,柔柔我的朋友圈也热闹起来了,有酱紫的: 还有酱紫的: 然后还有酱紫的: 酱紫的: 当然天台也是一如既然的热闹: 似乎人人都在输钱,那真正的赢家在哪里呢?博彩业的真 ...
- Hibernate(十四)抓取策略
抓取策略: 抓取策略是当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候,Hibernate如何获取关联对象的策略.Hibernate的抓取策略是Hibernate提升性能的一 ...
- 带你使用JS-SDK自定义微信分享效果
前言 想必各位在写wap端时都遇到过这样的场景吧 ----自定义分享标题.图片.描述 接下来小编给大家讲解下分享相关操作 预期效果 原始的分享效果: 使用微信JS-SDK的分享效果: 可以看出缩略图, ...