当前位置: 首页 > news >正文

MySQL数据库如何线上修改表结构

一、MDL元数据锁

在修改表结构之前,先来看下可能存在的问题。

1、什么是MDL锁

MySQL有一个把锁,叫做MDL元数据锁,当对表修改的时候,会自动给表加上这把锁,也就是不需要自己显式使用。

  • 当对表做增删改查的时候,加的是MDL读锁
  • 当对表结构做变更修改的时候,加的是MDL写锁

读与读之间不互斥,读与写,写与写之间互斥,因此

  • 当有一个线程对表执行增删盖茶的时候,会阻塞掉别的线程对表结构修改的请求
  • 当有一个线程对表结构修改的时候,会阻塞掉别的线程对表增删改查的请求

2、MDL锁的问题

并且MDL一旦上锁之后,只有当前请求的事务提交才会释放,如果是一个长事务,或者是线上数据量很大,修改表结构默认上了MDL写锁,会很耗时一直阻塞掉后边其他请求。

想象一种场景,A(select),B(alter), C(select),D(select).....分别为按照顺序对MySQL同一张表的请求,这些请求会形成一个队列。

当A(select)获取表的MDL读锁之后,就会阻塞掉B(alter),因为B要加的是MDL写锁,B被阻塞掉之后,就会导致后边等待队列中的其他请求都被阻塞掉,最终造成Mysql的可用连接耗尽,请求超时等问题。

二、如何线上修改MySQL表结构

鉴于以上MDL锁,得知对表做alter修改结构很会阻塞掉其他的正常请求,所以修改操作要放在非业务高峰期来做,一般是放到凌晨2-4点。

具体步骤:

  • 对表加读写锁,使得此时表只读、
  • 复制原表的物理结构
  • 修改新表的物理结构,包括增加新字段或者修改其他表结构
  • 把表结构导入新表,数据同步完成,锁住中间表,删除原表
  • 将新表rename为原表名
  • 释放锁

以上方案的问题是,数据量很大的时候,数据都导入需要时间,这个过程中,服务是不可访问的。

改进:

新建一张表 A_new,其比原表多了几个字段,通过数据订阅的方式订阅原表A,把线上的表A中的数据同步到这个新建的表A_new中,这个过程会一直持续,并且这个过程中表A是可以增删改查的,总有一个时刻,这两张表的数据是完全同步的,数据上是没有任何差异的,这个时候把原表表名A给修改掉,把新表A_new修改为原表A,这个操作是一个短暂操作,可以瞬间完成,不会有很大影响。

优缺点:

  • 好处是同步的过程不会影响原有的业务正常。
  • 缺点是过程中需要额外一倍的存储空间去存储这个新表,当rename完成之后,可以把老表删掉。

 

相关文章:

  • Python利用pandas获取每行最大值和最小值
  • C++设计模式之装饰者模式(结构型模式)
  • 数据结构中,索引存储和散列存储区别较为详细的介绍
  • 基于ssm+vue的邮票收藏鉴赏系统 elementui
  • 去中心化标志符在DID中的核心地位
  • C++设计模式之适配器模式(结构型模式)
  • 3-面试官:说说线程池的 7 大参数
  • 猿创征文|HCIE-Security Day50:网络攻击介绍
  • 一个基于NetCore开发的前后端分离CMS系统
  • centos7安装docker和docker-compose
  • 子查询与内联结分别应该怎么写?
  • Shell编程之第一讲——基础知识认识
  • Java-基于SSM的校园点餐管理系统
  • WLAN与WiFi各是什么意思有什么区别
  • Linux基础-常见问题 xrandr屏幕操作命令详解
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • Apache的80端口被占用以及访问时报错403
  • Computed property XXX was assigned to but it has no setter
  • gcc介绍及安装
  • laravel5.5 视图共享数据
  • 从重复到重用
  • 多线程 start 和 run 方法到底有什么区别?
  • 飞驰在Mesos的涡轮引擎上
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • ​io --- 处理流的核心工具​
  • #前后端分离# 头条发布系统
  • $jQuery 重写Alert样式方法
  • (Note)C++中的继承方式
  • (WSI分类)WSI分类文献小综述 2024
  • (附源码)php新闻发布平台 毕业设计 141646
  • (十八)SpringBoot之发送QQ邮件
  • (四)模仿学习-完成后台管理页面查询
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转) Face-Resources
  • (转)ObjectiveC 深浅拷贝学习
  • (转)拼包函数及网络封包的异常处理(含代码)
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .NET下ASPX编程的几个小问题
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @KafkaListener注解详解(一)| 常用参数详解
  • [100天算法】-二叉树剪枝(day 48)
  • [acwing周赛复盘] 第 94 场周赛20230311
  • [BZOJ2208][Jsoi2010]连通数
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [CVPR 2023:3D Gaussian Splatting:实时的神经场渲染]
  • [HarmonyOS]第一课:从简单的页面开始
  • [IE9] IE9 Beta崩溃问题解决方案