结论:
缩小字段长度不能使用inpalce,会锁表。
放大字段长度:取决于变化前和变化后是否跨越255这个长度。以UTF8编码为例,一个字符占3个字节。
字段变化1:varchar(50)--》varchar(80),不锁表。
字段变化2:varchar(100)->varcahr(130),不锁表。
字段变化3:varchar(50)--》vachar(130),会锁表;50*3=150个字节,130*3=390字节,这个变化跨越了255长度,会锁表。
缩小字段长度示例
本文实验的mysql版本是5.7
本文操作的t_customer_copy1表的数据量有1000w+。
缩小phone字段的长度由varchar(512)修改长度至varchar(256).
alter table t_customer_copy1 modify column phone varchar(256), algorithm=copy;
改小字段的长度algorithm不能选择inplace。
进行上述操作后,耗时情况:1047.06s,大概18分钟
在这个操作的过程中,不能对表里的数据进行修改,查询不受影响。
扩大数据库字段长度示例
使用t_customer_copy1表,数据量有1000万。
将字段phone varchar(256)扩大到varchar(512)
alter table t_customer_copy1 modify column phone varchar(512);
耗时0.73s。
将字段 relate_id varchar(64)扩大到varchar(90),耗时1044s,17min。
大家可能印象中有256的概念,这个256并不是指定义的字符串的长度,而是这个字段存储占的字节个数.
字段的长度是以字节为单位存储,utf8一个字符需要三个字节。0~255字节以内的长度可以使用一个byte存储。
大于255个字节的长度则需要使用2个byte存储。大家可能印象中有256的概念,这个256并不是指varchar(256).
**online ddl **
algorithm={copy|inplace}
LOCK={NONE|SHARED|DEFAULT|EXCLUSIVE} 表的锁定方式
NONE:允许并发查询和DML(数据库操作语言,INSERT、UPDATE、DELETE)操作;
SHARED:允许并发查询;
DEFAULT:允许尽可能的并发查询和DML操作;
EXCLUSIVE:不允许并发查询和DML操作。
COPY方式:
这是InnoDB最早期支持的方式,主要实现步骤:
- 创建与原表结构定义一致的临时表;
- 对原表加锁,不允许执行DML,但允许查询;
- 在临时表上执行DDL语句;
- 逐行拷贝原表数据到临时表;
- 原表与临时表进行RENAME操作,此时会升级原表上的锁,不允许读写,直至完成DDL操作;
in-place方式:
只支持字段的字节长度变化在0~255和256到更大值这两个区间内变化。扩大字段长度跨越上述这个区间,就会使用copy。
执行alter table t_customer_copy1 modify column phone varchar(512), algorithm=inplace,LOCK=NONE;不支持inplace,执行语句会提示不支持。
缩小字段长度不支持inplace.
MDL
所有方式做 DDL 均会产生 MDL(metadata lock)。除了 copy 模式会有持续性的锁(DDL 的整个过程期间无法向该表写入任何数据)之外,其他方式的 MDL 均为短暂的锁。
除了 copy 模式之外的所有模式,MDL 如下:
在 DDL 的开始阶段,申请该表的 EXCLUSIVE-MDL 锁,禁止读写
降级 EXCLUSIVE-MDL 锁,允许读写
在 DDL 的最终 COMMIT 阶段,升级 EXCLUSIVE-MDL 锁,禁止读写
其中的阶段一和阶段三,其 MDL 的持续时间都是非常短暂的,也就是申请到了 MDL 锁之后会在很快的时间(一般小于一秒)处理完成相关操作并释放锁,一般情况下是不会影响业务的。只有阶段二是真正在处理数据,持续时间一般较长。
但是,有可能出现在阶段一和阶段三,无法申请到 MDL 的情况。这是因为 MDL 和所有的读写语句都可能会产生冲突,如果是在申请 MDL 的时候,之前有读写的事务一直没有执行完成(或者执行完成之后一直没有 COMMIT),MDL 就会无法立刻申请到,这个时候,DDL 语句,以及所有在该 DDL 语句之后的读写事务,都会阻塞并等待之前的读写事务完成,导致整个实例处于不可用状态。这个时候 SHOW PROCESSLIST 看到的语句状态为 waiting for metadata lock。
由于目前所有的 DDL 语句都会产生 MDL,无法避免,因此,在执行 DDL 操作期间,尽可能确保不要有未执行完成的长事务。如果发生了 warting for metadata lock 导致的阻塞,一般有以下三种处理方法:
耐心等待之前的事务全部执行完成
将之前未执行完成的事务全部 kill 掉
kill 掉 DDL 语句
参考博客:https://www.cnblogs.com/zmc60/p/14533123.html