不停机修改线上 MySQL 主键字段 以及其带来的问题和总结思考
起因:
线上 user 数据库没有自增字段,数据量已经达到百万级。无论是给离线仓库还是数据分析同步数据,没有主键自增 id 都是杀手级的困难。所以在使用 create_time 痛苦了几次之后准备彻底来解决这个问题。
解决问题的思路:
当时理了两个思路,一个是直接找个夜生人静的夜晚,drop 掉目前的 primary key 。然后再 add 一个 id 字段做 primary key auto increament 。我觉得这个方法对于 100w 以下的数据表是一个不错的方法,首先简单,其次找个夜生人静的晚上也不会有非常长时间的锁表。当然最好使用 online ddl 进行操作就更好了。我们碰到的稍微现实一点问题是,目前线上表还会跟离线表进行同步。然后也想挑战一下不停机不锁表的切换。所以规划了一个思路是
1. 首先建一个变更 ddl 后的表,在这里表现为已经设置好自增 id 的情况。
2. 将线上数据导入该表。并且保持两张表同步。
- 方案1: 如果数据比较多 例如已经是1000w 插入了,而且插表频率高,那么建议使用类似于 maxwell 数据同步工具,读取 binlog 时时同步让两张表时刻保持一致。最后找一个表没那么热的时候,rename 表即可。 rename 操作可以在一个命令里面执行几乎是秒切,如果跟上线上没有延迟那么基本上不会有数据丢失,如果切换的时候表比较热,可能会有几条不一致可以手动修复即可。
- 方案2: 如果数据没有那么多 比如只是百万级别,而且也有表明显不热的时候比如说晚上 3 4 点的时候。那么你可以通过导入数据,然后根据 update_time 字段时时跟上线上表。然后最后再切换之前再执行一次 根据 update_time 的更新脚本,然后立即完成 rename 操作。这样的操作 在数据量不大表不热的时候甚至不会有数据的不一致。大家可以根据需求来选择具体的方案。
3. 找个夜深人静的时候 rename 表完成两张表的切换。
其实从流程上来看还是比较简单的,但是实际处理的时候还是遇到不少问题。
1. 我在线上进行两张表同步的时候发现 slave 明显跟不上 master,而且延迟的时间越来越大。后来查阅了一些资料发现是当 master 发生大量写入的时候, slave 是很有可能发生慢慢跟不上 master 的情况。引起这个情况有可能是 socket 网络通信上的跟不上,可能是 slave 机器的配置不行,更有可能是没有开启并行复制导致吞吐量跟不上。因为主库上可能是开启多进程在写,从库却是单进程在跟复制,慢慢落后是理所当然的,但是只要这种情况不长时间持续,可以发现离线库在主库完成大并发写入之后会慢慢恢复正常。
2. 切换方案跟太多别的业务交杂在一起,例如还去考虑同时兼容我们的离线分析库,把问题搞得十分复杂。下次在思考类似需求的解决方案的时候,一定要遵循最小优化原则。理论上来说离线分析库完全可以等切换完成之后全量重刷,由于已经有主键自增 id 了。刷新会变得比以前简单方便非常多,速度也会快很多。所以没有必要纠结同时兼容的问题。导致复制方案变得复杂最后导致出错。
3. 新键的表 ddl 一定不要随意改动上面的字段,理论上无论之前表字段有多不合理多恶心,如果没有在切换计划里面有比较全面的考量都不应该擅自删除字段。保持只增不减跟之前完全兼容。
最后这次切换虽然出了一些小岔子,但是总的来说比较顺利。目前已经正常跑了一周,应该稳定了。
Reference:
http://mysql.taobao.org/monthly/2016/04/08/ 常见的 MySQL slave 延迟问题
https://www.cnblogs.com/kevingrace/p/6065088.html MySQL binlog 总结
https://dev.mysql.com/doc/refman/5.6/en/rename-table.html 参考 MySQL 5.6 rename 文档
不停机修改线上 MySQL 主键字段 以及其带来的问题和总结思考的更多相关文章
- 线上Mysql数据库崩溃事故的原因和处理
前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(八)线上Mysql数据库崩溃事故的原因和处理
前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...
- 记一次排查线上MySQL死锁过程,不能只会curd,还要知道加锁原理
昨晚我正在床上睡得着着的,突然来了一条短信. 啥,线上MySQL死锁了,我赶紧登录线上系统,查看业务日志. 能清楚看到是这条insert语句发生了死锁. MySQL如果检测到两个事务发生了死锁,会回滚 ...
- MySQL主键设计
[TOC] 在项目过程中遇到一个看似极为基础的问题,但是在深入思考后还是引出了不少问题,觉得有必要把这一学习过程进行记录. MySQL主键设计原则 MySQL主键应当是对用户没有意义的. MySQL主 ...
- mysql主键问题
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_22314145/article/details/80824660 MySQL主键 一. MyS ...
- 不停机替换线上代码? 你没听错,Arthas它能做到
写在前边 有没有这样一种感受,自己写的代码在开发.测试环境跑的稳得一笔,可一到线上就抽风,不是缺这个就是少那个反正就是一顿报错,线上调试代码又很麻烦,让人头疼得很.阿里巴巴出了一款名叫Arthas的工 ...
- MySQL主键设计盘点
目录 主键定义 主键设计和应用原则 主键生成策略 自增ID UUID 自建的id生成器 Twitter的snowflake算法 @ 最近在项目中用了UUID的方式生成主键,一开始只是想把这种UUID的 ...
- 原创 记录一次线上Mysql慢查询问题排查过程
背景 前段时间收到运维反馈,线上Mysql数据库凌晨时候出现慢查询的报警,并把原始sql发了过来: --去除了业务含义的sql update test_user set a=1 where id=1; ...
- MYSQL主键自动增加的配置及auto_increment注意事项
文章一 原文地址: http://ej38.com/showinfo/mysql-202971.html 文章二: 点击转入第二篇文章 在数据库应用,我们经常要用到唯一编号.在MySQL中可通过字 ...
随机推荐
- Your kernel does not support swap limit capabilities.memory limit without swap
原因是:由于内核不支持限制内存的设置 解决办法是:vim /etc/default/grub 修改为: 或者:GRUB_CMDLINE_LINUX="cgroup_enable=memory ...
- vue快速入门
Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的.相比于Angular.js,Vue.js提供了更加简洁.更易于理解的API,使得我们能够快速地上手并使 ...
- js截取url参数
举例说明,比如http://localhost:2019/blog/getCommentListInfo?postId=1如何获取postId=1这个参数值呢?很简单通过下面代码即可获取,如: win ...
- SpringBoot + Shiro + shiro.ini 的踩坑记录
0.写在前面的话 好久没写博客了,诶,好多时候偷懒直接就抓网上的资料丢笔记里了,也就没有自己提炼,偷懒偷懒.然后最近参加了一个网络课程,要交作业的那种,为了能方便看下其他同学的作业,就写了个爬虫把作业 ...
- EF Core中,通过实体类向SQL Server数据库表中插入数据后,实体对象是如何得到数据库表中的默认值的
我们使用EF Core的实体类向SQL Server数据库表中插入数据后,如果数据库表中有自增列或默认值列,那么EF Core的实体对象也会返回插入到数据库表中的默认值. 下面我们通过例子来展示,EF ...
- UVA10838 The Pawn Chess
UVA好题没人写系列,感觉可以稍稍练习一下面向对象编程的形式(大雾) 题意很简单,在国际象棋的棋盘中有一些兵,走到对方底线即为胜利,问最优决策下谁能获胜.并输出最小步数. 首先这里的棋盘都只有\(4\ ...
- 【C#复习总结】dynamic
介绍 C# 4 引入了一个新类型 dynamic. 该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查. 大多数情况下,该对象就像具有类型 object 一样. 在编译时,将假定 ...
- python数据类型--set(集合)
博客地址:http://www.cnblogs.com/yudanqu/ 首先,简单介绍一下set,set就是我们中学时所学的集合,当时集合的性质就包括一点,集合里不能有重复的数字.我们现在所用到的集 ...
- flask登录插件 flask-login
Flask-Login为Flask提供了用户会话管理,它处理了日常的登入登出且长时间记住用户的会话 使用: 1.配置,初始化 LoginManager 创建实例 loginManger = Login ...
- Macaca初体验-Android端(Python)
前言: Macaca 是一套面向用户端软件的测试解决方案,提供了自动化驱动,周边工具,集成方案.由阿里巴巴公司开源:http://macacajs.github.io/macaca/ 特点: 同时支持 ...