5分钟了解MySQL5.7的Online DDL雷区
Part1:写在最前
Online DDL,当新手听到这个名字的时候,非常高兴,以为无论什么情况下,修改表结构都不会锁表,理想很丰满,现实很骨感!读完本文,教你如何避开这些雷区,安全的修改表结构。话不多说,我们分别来看下MySQL5.6和MySQL5.7在修改表结构上的相同和异同。
Part2:5.6.25的表现
①首先我们构造数据并进行测试
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
mysql> create database helei;Query OK, 1 row affected (0.01 sec)mysql> use helei;Database changedmysql> create table helei( -> id int(10) unsigned NOT NULL AUTO_INCREMENT, -> c1 int(10) NOT NULL DEFAULT '0', -> c2 int(10) unsigned DEFAULT NULL, -> c5 int(10) unsigned NOT NULL DEFAULT '0', -> c3 timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -> c4 varchar(200) NOT NULL DEFAULT '', -> PRIMARY KEY(id), -> KEY idx_c1(c1), -> KEY idx_c2(c2) -> )ENGINE=InnoDB ;Query OK, 0 rows affected (0.02 sec)mysql> delimiter $$mysql> drop procedure if exists `insert_helei` $$mysql> create procedure `insert_helei`(in row_num int ) -> begin -> declare i int default 0; -> while i < row_num do -> insert into helei(c1, c2, c5,c3, c4) values( floor(rand()*row_num),floor(rand()*row_num),floor(rand()*row_num),now(),repeat('su', floor(rand()*20))); -> set i = i+1; -> END while; -> end$$Query OK, 0 rows affected (0.00 sec)mysql> delimiter ;mysql> call insert_helei(1000000);Query OK, 1 row affected (18 min 52.88 sec)mysql> desc helei;+-------+------------------+------+-----+-------------------+-----------------------------+| Field | Type | Null | Key | Default | Extra |+-------+------------------+------+-----+-------------------+-----------------------------+| id | int(10) unsigned | NO | PRI | NULL | auto_increment || c1 | int(10) | NO | MUL | 0 | || c2 | int(10) unsigned | YES | MUL | NULL | || c5 | int(10) unsigned | NO | | 0 | || c3 | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP || c4 | varchar(200) | NO | | | |+-------+------------------+------+-----+-------------------+-----------------------------+6 rows in set (0.01 sec)mysql> alter table helei add c6 varchar(60) not null default '';Query OK, 0 rows affected (9.66 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> select count(*) from helei;+----------+| count(*) |+----------+| 1000000 |+----------+1 row in set (0.14 sec)mysql> alter table helei ALGORITHM=INPLACE,modify c6 varchar(80) not null default '';ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.mysql> alter table helei modify c6 varchar(80) not null default '';Query OK, 1000000 rows affected (9.44 sec)Records: 1000000 Duplicates: 0 Warnings: 0 |
Tips:心得
可以看出5.6.25这里并不支持ALGORITHM,而直接对表进行修改的话用了9.44s。
②接下来我们测试下变更varchar长度是否锁表
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
mysql> alter table helei modify c6 varchar(40) not null default '';Query OK, 1000000 rows affected (9.26 sec)Records: 1000000 Duplicates: 0 Warnings: 0mysql> update helei set c1=9999 where id=1;Query OK, 0 rows affected (7.77 sec)Rows matched: 1 Changed: 0 Warnings: 0mysql> show processlist;+----+------+-----------+-------+---------+------+---------------------------------+-------------------------------------------------------------+| Id | User | Host | db | Command | Time | State | Info |+----+------+-----------+-------+---------+------+---------------------------------+-------------------------------------------------------------+| 6 | root | localhost | helei | Query | 2 | copy to tmp table | alter table helei modify c6 varchar(40) not null default '' || 7 | root | localhost | helei | Query | 1 | Waiting for table metadata lock | update helei set c1=9999 where id=1 || 8 | root | localhost | NULL | Query | 0 | init | show processlist |+----+------+-----------+-------+---------+------+---------------------------------+-------------------------------------------------------------+3 rows in set (0.00 sec) |
可以看到在对c6字段修改表结构时,对c1字段无法更新,被锁
|
1
2
3
4
5
6
7
|
mysql> alter table helei add c7 varchar(60) not null default '';Query OK, 0 rows affected (8.30 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> update helei set c1=9999 where id=1;Query OK, 0 rows affected (0.00 sec)Rows matched: 1 Changed: 0 Warnings: 0 |
Tips:心得
经测试,增加、删除字段或索引不锁全表,变更字段长度,锁表。
Part3:5.7.15的表现
|
1
2
3
4
5
6
7
8
9
10
|
mysql> select count(*) from helei;+----------+| count(*) |+----------+| 1000000 |+----------+1 row in set (0.11 sec)mysql> alter table helei ALGORITHM=INPLACE,modify c6 varchar(80) not null default '';Query OK, 0 rows affected (0.01 sec)Records: 0 Duplicates: 0 Warnings: 0 |
Tips:心得
可以看到,这里用时0.01sec,和5.6的9.44sec效率差了相当多吧~
Warning:警告1
不过,ALGORITHM用法只对varcahr类型有效哦,比如我们对c1列int型进行变更:
c1原为int(10) 变更为int(11) unsigned则无效
|
1
2
|
mysql> alter table helei ALGORITHM=INPLACE,modify c1 int(11) unsigned not null;ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY. |
Tips:心得
只变更int的位数,是可以的,不过这没什么意义,因为无论你int多少,最多都只能存10位,这也就是为什么我们生产库开发规范要定义所有的int都用int(10)。
生产库开发规范详见:
http://suifu.blog.51cto.com/9167728/1792604
Warning:警告2
如果字段属性大于并等于varchar(256)(这里的256是指字节(UTF8占用3字节)或者把varchar(80)减少到varchar(70)或者更少),则仍需要拷贝数据且锁全表。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
mysql> alter table helei ALGORITHM=INPLACE,modify c6 varchar(84) not null default '';Query OK, 0 rows affected (0.01 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> alter table helei ALGORITHM=INPLACE,modify c6 varchar(85) not null default '';Query OK, 0 rows affected (0.01 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> alter table helei ALGORITHM=INPLACE,modify c6 varchar(86) not null default '';ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.mysql> alter table helei ALGORITHM=INPLACE,modify c6 varchar(40) not null default '';ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.mysql> alter table helei ALGORITHM=INPLACE,modify c6 varchar(70) not null default '';ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY. |
Warning:警告3
添加字段alter table时,对该表的增删改查均不会锁表。而在这之前,当该表被访问时,需要等其执行完毕后才可以执行alter table。
——总结——
在varchar变更字段长度方面,5.7的新特性ALGORITHM参数可以快速调整varchar类型的字段长度。5.7同5.6一样,增加,删除字段或索引不锁全表,删除主键锁全表。因此,在上线时,一定要执行show processlist命令并观察,此刻是否有某个慢SQL对该表进行操作,以免alter table表时出现锁表现象。由于笔者的水平有限,编写时间也很仓促,文中难免会出现一些错误或者不准确的地方,不妥之处恳请读者批评指正。
本文出自 “岁伏” 博客,请务必保留此出处http://suifu.blog.51cto.com/9167728/1855872
5分钟了解MySQL5.7的Online DDL雷区的更多相关文章
- MySQL5.7之在线DDL不会锁表
MySQL5.7在线修改varchar字段不在锁表,测试过程如下: mysql> select version(); +------------+ | version() | +-------- ...
- 一分钟完成MySQL5.7安装部署
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://suifu.blog.51cto.com/9167728/1855415 Part ...
- 5分钟了解MySQL5.7的undo log在线收缩新特性
Part1:写在最前 在MysQL5.6版本中,可以把undo log 回滚日志分离到一个单独的表空间里:其缺点是不能回收空间大小,until MysQL5.7,but MariadDB10.1暂不支 ...
- MySQL5.7 慢查询+DDL操作堵塞查询
数据库版本: mysql> select @@version; +------------+ | @@version | +------------+ | 5.7.26-log | +----- ...
- MySQL DDL方案测试及选型.
性能测试 一.测试背景 1.机器配置和版本 机器配置(下面测试qps数据都是以本机器配置为准) 型号:Dell s3710 磁盘:SSD 3T CPU:32 内存:128G MySQL版本:5.7.2 ...
- Mysql在线DDL
1. Mysql各版本DDL方式 1.1 MysqlDDL演进 当mysql某个业务表上有未提交的活动事务的时候,你去执行在线DDL,这相当危险,直接会被卡住,show processlist里面会 ...
- MySQL主从数据库同步延迟问题解决(转)
最近在做MySQL主从数据库同步测试,发现了一些问题,其中主从同步延迟问题是其中之一,下面内容是从网上找到的一些讲解,记录下来以便自己学习: MySQL的主从同步是一个很成熟的架构,优点为:①在从服务 ...
- MySQL主从同步的延迟原理
1. MySQL数据库主从同步延迟原理. 答:谈到MySQL数据库主从同步延迟原理,得从mysql的数据库主从复制原理说起,mysql的主从复制都是单线程的操作,主库对所有DDL和DML产生binlo ...
- MYSQL主从不同步延迟原理
1. MySQL数据库主从同步延迟原理. 要说延时原理,得从mysql的数据库主从复制原理说起,mysql的主从复制都是单线程的操作, 主库对所有DDL和DML产生binlog,binlog是 ...
随机推荐
- Android 自定义 SpinnerButton(转)
Android 自定义 SpinnerButton 模仿Android4.0的Spinner Button写的一个MySpinnerButton.这样在1.6~4.0.4版本都可以实现这种下拉框的效果 ...
- HDU 2897 邂逅明下(巴什博奕变形)
巴什博奕的变形,与以往巴什博奕不同的是,这里给出了上界和下界,原先是(1,m),现在是(p,q),但是原理还是一样的,解释如下: 假设先取者为A,后取者为B,初始状态下有石子n个,除最后一次外其他每次 ...
- thinkphp 5.0 模块设计
模块设计 5.0版本对模块的功能做了灵活设计,默认采用多模块的架构,并且支持单一模块设计,所有模块的命名空间均以app作为根命名空间(可配置更改). 目录结构 标准的应用和模块目录结构如下: ├─ap ...
- sencha touch环境搭建
引入touch文件,包括resources和sencha-touch-debug.js文件 index.html文件内容如下: <!DOCTYPE HTML> <html> & ...
- ajax跨域实现api 接口调用
背景: 想实现跨域去调用接口, 然后同时支持下次调用,能够带cookie信息过来,同时支持来自多个源头的域名的跨域调用. 1.这样支持来自所有域名的跨域调用: 不支持跨域是,浏览器报错: 在api接口 ...
- Spring--注入类型--setter
setter注入: package com.bjsxt.service; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.User; publ ...
- runtime - associated(关联)
category和associative作为objective-c的扩展机制的两个特性,category用来扩展类的方法,associative可以用来扩展类的属性.使用associative需要导入 ...
- memcache数据组织
转自:原链接 使用命令 set(key, value) 向 memcached 插入一条数据, memcached 内部是如何组织数据呢 一 把数据组装成 item memcached 接受到客户端的 ...
- 【转】VS2013动态库文件的创建及其使用详解
一.VS2013动态库文件的创建 1.新建项目,win32,win32项目,输入项目名称,例如MakeDll. 2.”确定“——”下一步“,选择”DLL“选项,再点”完成“: 3.菜单栏选择”项目“— ...
- [vue最新实战] gank客户端(vue2 + vue-router2 + vuex +webpace + es6)新手福利,干货多多
vue-meizi 本项目是基于vue2最新实战项目,是适合新手进阶的绝佳教程.代码简单易懂,注释多多.实现了移动端使用最多的 无限滚动,图片加载,左右滑动,等待.先发布预览版本,后面更多更全的功能和 ...