MySQL Online DDL(二)(r11笔记第88天)

对于Online DDL,之前简单分析了一些场景MySQL中的Online DDL(第一篇)(r11笔记第3天),其实有一个很关键的点没提到,那就是online DDL的算法,目前有三个操作选项,default,inplace,copy可选

具体可以参考  https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl.html

> select count(*) from newtest;
+----------+
| count(*) |
+----------+
| 22681426 |
+----------+
1 row in set (45.76 sec)表结构信息如下:

> show create table newtest\G
*************************** 1. row ***************************
       Table: newtest
Create Table: CREATE TABLE `newtest` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `game_type` int(11) NOT NULL DEFAULT '-1' ,
  `login_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',
  `login_account` varchar(100) DEFAULT NULL ,
  `cn_master` varchar(100) NOT NULL DEFAULT '' ,
  `client_ip` varchar(100) DEFAULT '' ,
  PRIMARY KEY (`id`),
  KEY `ind_tmp_account1` (`login_account`),
  KEY `ind_login_time_newtest` (`login_time`)
) ENGINE=InnoDB AUTO_INCREMENT=22681850 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

默认的copy选项

比如我们运行下面的SQL,添加一个字段,默认情况下是使用copy的算法,即数据是平行复制一份。

alter table newtest add column newcol varchar(10) default '';这个变更过程会生成两个临时的文件.frm,.ibd
-rw-r----- 1 mysql mysql       8840 Dec  5 18:13 newtest.frm
-rw-r----- 1 mysql mysql 4353687552 Dec  5 18:45 newtest.ibd
...
-rw-r----- 1 mysql mysql       8874 Feb 27 22:25 #sql-6273_2980ab.frm
-rw-r----- 1 mysql mysql   41943040 Feb 27 22:25 #sql-ib280-3638407428.ibd
...在这个变更的过程中,是运行DML操作的,而且没有任何阻塞。

> insert into
newtest(game_type,login_time,login_account,cn_master,client_ip)
values(1,'2017-02-27
16:22:10','150581500032','572031626','183.128.143.113');
Query OK, 1 row affected (0.05 sec)

因为使用了主键自增,所以我可以用同样的语句再插入一条记录,也是全然没有阻塞。

> insert into
newtest(game_type,login_time,login_account,cn_master,client_ip)
values(1,'2017-02-27
16:22:10','150581500032','572031626','183.128.143.113');
Query OK, 1 row affected (0.00 sec)这个时候查看show processlist的结果,相比就显得有些简单了。不像之前的版本中会有table metadata lock的字样了。

+---------+-----------------+-----------------------------+----------------+-------------+---------+--------------------------------
|Id      | User            | Host                        |
db             | Command     | Time    | State                          
+---------+-----------------+-----------------------------+----------------+-------------+---------+--------------------------------
| 2719915 | root            | localhost                   | test           | Query       |      75 | altering table

对比临时文件和现有配置文件

我们简单看看上面列举出来的配置文件.frm

可以通过strings的方式看到一个基本的结构信息。

# strings newtest.frm
PRIMARY
ind_tmp_account1
ind_login_time_newtest
InnoDB
)                                        
game_type
login_time
login_account
cn_master
client_ip
game_type
login_time
login_account
cn_master
client_ip
而查看临时创建的.frm文件

# strings "#sql-6273_2980ab.frm"
PRIMARY
ind_tmp_account1
ind_login_time_newtest
InnoDB
)                                        
game_type
login_time
login_account
cn_master
client_ip
newcol
game_type
login_time
login_account
cn_master
client_ip
newcol整个添加字段的操作持续时间为10分钟左右。

> alter table newtest add column newcol varchar(10) default '';
Query OK, 0 rows affected (10 min 31.64 sec)
Records: 0  Duplicates: 0  Warnings: 0可以看到修改后的.ibd文件大小相比要大了一些。

-rw-r----- 1 mysql mysql       8874 Feb 27 22:25 newtest.frm
-rw-r----- 1 mysql mysql 4047503360 Feb 27 22:34 newtest.ibd而如果我们换一个角度来看,我们删除一个字段。

--alter table newtest drop column newcol , ALGORITHM=INPLACE;  --这种方式是有问题的,采用如下的方式,我们声明使用inplace算法,而实际情况如何呢。

> alter table newtest drop column newcol , ALGORITHM=INPLACE;
Query OK, 0 rows affected (9 min 54.18 sec)
Records: 0  Duplicates: 0  Warnings: 0我们可以看到DML操作畅通无阻。

> insert into
newtest(game_type,login_time,login_account,cn_master,client_ip)
values(1,'2017-02-27
16:22:10','150581500032','572031626','183.128.143.113');
Query OK, 1 row affected (0.15 sec)这个过程可以看到效果和启用copy算法是一样的,为什么呢。因为添加字段,删除字段是一个数据重组的过程,所以相比而言,这个操作的代价也是昂贵的。

添加/删除索引

然后我们添加索引,启用inplace算法。

alter table newtest add index (client_ip) ,algorithm=inplace;这个过程就特别了,依旧会创建.frm的临时文件,但是数据文件不会复制,而是现改。
-rw-r----- 1 mysql mysql       8840 Feb 27 22:49 newtest.frm
-rw-r----- 1 mysql mysql 4018143232 Feb 27 23:06 newtest.ibd
...
-rw-r----- 1 mysql mysql       8840 Feb 27 23:06 #sql-6273_2980ab.frm这个过程中,DML依旧是畅通的。

> insert into
newtest(game_type,login_time,login_account,cn_master,client_ip)
values(1,'2017-02-27
16:22:10','150581500032','572031626','183.128.143.113');
Query OK, 1 row affected (0.04 sec)整个添加的过程相比而言,持续时间要短很多,大概是3分钟左右。

> alter table newtest add index (client_ip) ,algorithm=inplace;
Query OK, 0 rows affected (3 min 42.84 sec)
Records: 0  Duplicates: 0  Warnings: 0
而如果此时删除索引,这个过程就如同非一般的感觉,不到一秒即可完成。

> alter table newtest drop index  client_ip ,algorithm=inplace;
Query OK, 0 rows affected (0.13 sec)
Records: 0  Duplicates: 0  Warnings: 0整个过程中.frm和.ibd文件没有任何大小变化。

-rw-r----- 1 mysql mysql       8840 Feb 27 23:13 newtest.frm
-rw-r----- 1 mysql mysql 4785700864 Feb 27 23:13 newtest.ibd而如果我们为了对比同样的inpalce和copy操作场景下的代价,可以使用copy显示创建一个索引,即可得到一个基本的对比情况。

alter table newtest add index (client_ip) ,algorithm=copy;整个过程因为.ibd文件较大,持续时间也会放大很多,这个环境中执行时间是29分,差别已然非常明显。

> alter table newtest add index (client_ip) ,algorithm=copy;
Query OK, 22681430 rows affected (29 min 13.80 sec)
Records: 22681430  Duplicates: 0  Warnings: 0

小结

Online DDL还是存在着一些限定情况,很多场景还没有完全测试到,需要结合具体的场景和需求来考量。

时间: 2024-09-20 09:13:36

MySQL Online DDL(二)(r11笔记第88天)的相关文章

MySQL参数对比浅析(r11笔记第97天)

  今天按照计划,决定得总结下MySQL的参数了,说来想来,立即就做. 大体算了下,手头的环境主要还是使用了Percona分支,官方的相对较少,就暂且按照Percona的版本来统计参数的情况,可能和官方的会有一些出入.    数据版本会有一个较大的跨度,从5.0到5.7都有,这也能够间接反映出一个系统的变迁过程.   涉及的数据库版本如下,基本版本就是5.0, 5.5, 5.6, 5.7 5.0.67-percona-highperf-log 5.5.33-31.1-log 5.6.14-rel

使用sysbench压力测试MySQL(一)(r11笔记第3天)

今天用了下新版本的sysbench,发现和早期版本的差别还不小,确实有不少有趣的地方,是的,我们继续测试下MySQL. 如果大家看过<高性能MySQL>这本书,就会发现里面对于基准测试的描述非常全面和专业,里面的测试场景都是基于早期版本,这个版本有一个不太方便的地方就是无法抓取到更细节的数据,只有平均值,所以要不需要定制脚本,要不就需要更多的测试场景和时间来得到一个报告. sysbench目前最新的版本是1.0.3,里面的interval参数确实很赞,也是驱动我尝试的最大动力,因为能够得到一个

闪回原理测试(二)(r11笔记第23天)

    对于闪回部分,Oracle本身提供了非常多相关的特性,我个人对于闪回数据库这个特性最为喜爱,尤其是应用再Data Guard环境中,真是一大杀器.     而对于DML的闪回部分其实也相对比较容易理解,毕竟就是原操作的逆操作,之前通过logminer的方式来读取redo来间接得以印证.Oracle闪回原理-Logminer解读redo(r11笔记第17天)     但是对于DDL的闪回,这个特性真是非常强悍了.比如一个truncate操作,它的逆操作改怎么定义,就很难去界定了.当然这个里

用Oracle的眼光来学习MySQL 5.7的sys(下)(r11笔记第25天)

昨天写了篇分析sys的文章,用Oracle的眼光来学习MySQL 5.7的sys(上)(r11笔记第24天)收到了一些朋友的反馈,还不错,今天继续努力,再整理一篇. sys还是很有借鉴意义     今天还和同事偶然聊起sys schema的事情,我觉得有几个地方要值得借鉴. 1)原本需要结合information_schema,performance_schema查询的方式,现在有了视图的方式,显示更加直观 2)sys schema的有些功能在早期版本可能无从查起,或者很难查询,现在这些因为新版

复杂SQL性能优化的剖析(二)(r11笔记第37天)

    昨天的一篇文章复杂SQL性能优化的剖析(一)(r11笔记第36天) 分析了一个SQL语句导致的性能问题,问题也算暂时告一段落,因为这个语句的执行频率是10分钟左右,所以优化后(大概是2秒左右,需要下周再次确认)的提升很大.    对于优化是一个持续的改进,我们碰到的问题,最终的原因可能五花八门,但是正如柯南所说,真相只有一个.我把这个问题和前几天处理的一个问题结合起来,前几天处理了一个紧急问题,也是有一个SQL语句的执行计划发生改变,这个语句的业务比较关键,触发频率是每分钟一次,如果一旦

一个SQL性能问题的优化探索(二)(r11笔记第38天)

继续前几天的一个案例一个SQL性能问题的优化探索(一)(r11笔记第33天) 如下的SQL语句存在索引字段CARD_NO,但是执行的时候却走了全表扫描,因为这是一个核心表,数据量很大,导致数据库负载很高. SQL_FULLTEXT ---------------------------------------------------------------------------------------------------- SELECT ID,CN,CARD_NO,TO_CHAR(CHAR

Data Guard实现故障自动切换(二)(r11笔记第39天)

   今天下午我的一个朋友碰到了一个Data Guard的问题,大体是主备网络出现问题,因为环境中配置了自动切换,结果备库就自动切换为了主库,这样就成了"双主",我帮忙看了下,对备库做了闪回,然后直接转换主库为备库角色,一个看似繁琐的修复工作就完成了.    在一个一主多备的环境中,的确需要一个强大的工具来支持,所以最后朋友说DG Broker真是个好东西,我回了句 用好了DG Broker,手工管理Data Guard就是小米加步枪啊.    就如同我昨天文章Data Guard故障

RDS for MySQL Online DDL 使用

RDS for MySQL Online DDL 使用   Online DDL 的限制 Online DDL 建议的选项 异常处理 RDS for MySQL 5.6 支持 Online DDL 特性. Online DDL (在线 DDL)功能允许在表上执行 DDL 的操作(比如创建索引)的同时不阻塞并发的 DML 操作 和 查询(select)操作.  注: 从低版本(比如 RDS for MySQL 5.5)升级到 RDS for MySQL 5.6,第一次执行 DDL 时有可能会因为表

【OGG】OGG的单向复制配置-支持DDL(二)

[OGG]OGG的单向复制配置-支持DDL(二) 一.1  BLOG文档结构图       一.2  前言部分   一.2.1  导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① OGG的单向DDL实时复制功能     注意:本篇BLOG中代码部分需要特别关注的地方我都用黄色背景和红色字体来表示,比如下边的例子中,thread 1的最大归档日志号为33,thread 2的最大归档日志号为43是需要特别关注的地方.   List