全部产品
云市场

不锁表结构变更

更新时间:2019-08-28 10:00:30

需求背景

  • 在MySQL数据库类型越来越多使用的今天,随着业务的发展需要对已在线上运行的大表进行结构修改(增加字段、修改字段属性、增加索引、修改索引等)是一个非常普遍的需求。但对于OLTP系统,变更期间业务尤其是高并发的业务是非常不愿意看到结构变更造成锁表而对业务有损的。
    • MySQL官方在5.6及以后的版本提供了InnoDB引擎部分操作的OnlineDDL能力,具体可参考官方文档:innodb-online-ddl
      • 部分场景虽然官方支持online,但实际执行时还会有一定的概率遇到如 Duplicate entry之类的错误
  • 在这种情况下,MySQL5.6以前的版本、MySQL5.6版本官方支持操作之外的其他变更、InnoDB之外的引擎,也希望能得到不锁表变更的能力。
  • 基于此,DMS企业版本次提供了自研的不锁表结构变更功能。

支持能力

  • 版本:MySQL所有版本、POLARDB
  • 引擎:InnoDB、Rocksdb
  • 实例来源:经典网络的RDS、VPC网络的RDS、经典网络的ECS自建数据库、VPC网络的ECS自建数据库、公网自建数据库

典型应用场景

  • 1.不锁表结构变更,规避数据库变更锁表阻塞业务的现象发生
  • 2.不锁表结构变更,规避原生OnlineDDL带来的主备延迟现象发生
  • 3.不锁表结构变更,取代原有optimize table锁表变更回收表空间、降低碎片率的方案为不锁表回收;最佳实践-不锁表结构变更回收碎片空间
  • 4.不锁表结构变更,修改表的字符集、校验集
  • 5.不锁表结构变更,调整时区

使用方法

  • 【系统管理】-【实例管理】,选中目标MySQL类型的实例开启参数开关不锁表结构变更

  • 普通用户在【结构设计】工单、【库表同步】工单、【数据变更】工单(需要安全规则开启支持DDL提交)提交的满足支持能力范围的SQL脚本均会保障使用不锁表的方式进行已有表的表结构变更

  • DBA、管理员在【系统管理】-【任务管理】直接部署的DDL脚本满足支持能力范围的SQL脚本均会保障使用不锁表的方式进行已有表的表结构变更

主要原理

  • 1、创建临时表:CREATE TABLE tmp_table_table LIKE table_name
  • 2、变更临时表结构: ALTER TABLE tmp_table_table XXXX
  • 3、全量拷贝数据:INSERT IGNORE INTO tmp_table_table (SELECT %s FROM table_name FORCE INDEX (%s) WHERE xxx
  • 4、增量数据binlog同步: UPDATA/INSRT/DELETE tmp_table_name
  • 5、切换新旧表: RENAME TABLE table_name to old_tmp_table_table, tmp_table_name to table_name

变更依赖表上必须有主键、唯一键,用于全量拷表分段操作以及后续的增量更新依据(被依赖的主键、唯一键不支持进行数据更新,若有更新则任务会失败退出)

全程无触发器等逻辑,且变更期间不影响并行复制为串行,不会产生主备延迟(MySQL自带onlineddl会造成备库并行复制变成串行复制,导致主备延迟的可能)

选项说明

  • 关闭
    • 原生语句下发给MySQL执行,不进行任何处理
  • 开启(MySQL原生OnlineDDL优先)
    • 优先使用MySQL原生的OnlineDDL执行,如果源生会锁表的话会转用DMS自研的不锁表结构变更执行,以保障不锁表
  • 开启(DMS无锁表结构变更优先)
    • 直接使用DMS自研的无锁表结构变更执行,以保障不锁表

选项区别

  • MySQL原生OnlineDDL:执行时间相对比较快,但有可能导致实例的并行复制降为串行复制,从而可能产生主备延迟现象
  • DMS无锁表结构变更:执行时间相对原生行为会慢一些,但不影响复制行为,不会产生延迟现象

使用限制

  • 账号权限
    • 若RDS实例未开启高权限账号,可配置RDS控制台上新建的”读写”账号
    • 若RDS实例已开启高权限账号,则在录入DMS企业版保存实例时的数据库账号的权限与自建账号权限一致。若当前非此账号则需要进行调整维护,账号创建详见:RDS-MySQL创建高权限账号
      • 自建账号需满足以下权限:REPLICATION CLIENT, REPLICATION SLAVE,ALTER , CREATE , DELETE , DROP , INDEX , INSERT , LOCK TABLES , SELECT , UPDATE on *.*
  • 磁盘空间:由于需要在目标数据库新建表拷贝数据,大表变更时需要注意磁盘剩余空间避免空间用满导致RDS实例锁定
  • 日志格式:需要开启row模式binlog复制,当前默认POLARDB未开启binlog,如有需要可按手册提示进行操作 POLARDB-如何开启Binlog
  • 不支持主键、唯一键存在更新的场景
    • 如果表上有主键,主键不能存在update 更新
    • 如果表上没有主键,只有唯一键,唯一键不能存在update 更新
    • 如果表上没有主键、没有唯一键,当前尚不支持使用不锁表变更逻辑。需要在实例上关闭此开关或先添加主键、唯一键后重新提交任务