目前我们线上统一用的MySQL 5.1系列,每次大表升级做DDL操作时,都会花费大量的时间,同时也会影响宕机时间,MySQL 5.6在这方面做了很大的改进,大大的缩短了DDL操作时间,详情见如下实验:
MySQL 5.6.16
窗口一:添加一个索引
mysql> ALTER TABLE task_new add key idx_company_id(company_id);
Query OK, 0 rows affected (15.65 sec)
Records: 0 Duplicates: 0 Warnings: 0
窗口二:update 该表中数据
mysql> update task_new set task_priority =125 where id = 4047015;
Query OK, 0 rows affected (11.30 sec)
Rows matched: 0 Changed: 0 Warnings: 0
update没有等待,也没有被锁。正常的update
窗口一:删除一个索引
mysql> alter table task_new drop key idx_user_id;
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0
drop index 在新版本中执行时间特别短,原因在于不用建表,只需要在原表中做drop index即可。
MySQL 5.1.57
窗口一:添加一个索引
root@mediawise 03:31:02>ALTER TABLE task_new add key idx_company_id(company_id);
Query OK, 1336140 rows affected (1 min 16.12 sec)
Records: 1336140 Duplicates: 0 Warnings: 0
窗口二:Update 该表中数据
root@mediawise 03:26:21>update task_new set task_priority = 126 where id = 5518630;
Query OK, 5 rows affected (1 min 11.34 sec)
Rows matched: 5 Changed: 5 Warnings: 0
存在lock现象,等alter结束才会做update操作
root@mediawise 05:34:15>alter table task_new drop key idx_status;
Query OK, 1336140 rows affected (1 min 6.21 sec)
Records: 1336140 Duplicates: 0 Warnings: 0
drop index 在老版本中相当慢,原因在于要新建临时表
综上所述:MySQL 5.6系列在DDL操作上做了新的更改,由原来的新建临时表,再把数据插入,再rename表的方式改变成直接在原表alter,最后时刻加锁,加快执行时间,不影响其他update,delete,select,insert 操作。
备注:MySQL 5.6 DDL 主要受old_alter_table控制,默认情况下参数为OFF
mysql> show global variables like '%old_alter_table%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| old_alter_table | OFF |
+-----------------+-------+
1 row in set (0.12 sec)
mysql> alter table task_new add index user_id(user_id);
Query OK, 0 rows affected (12.19 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show global variables like '%old_alter_table%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| old_alter_table | ON |
+-----------------+-------+
1 row in set (0.01 sec)
mysql> alter table task_new add index user_id(user_id);
Query OK, 1603368 rows affected (8 min 25.63 sec)
Records: 1603368 Duplicates: 0 Warnings: 0
思考题:
1.为什么删除index如此快速?
答:删除index时只是在辅助索引的空间上做个可用标志。并删除该表的索引定义,没有新建表。
2.innodb中index存哪里
分析innodb会发现,索引是存在于新的page中,不与数据一起存储在同一pageh中。辅助索引page中存的是索引行的值以及主键的值。
3.通过什么来保证在线添加index和update数据双方不受影响?
答:MySQL5.6中通过row_log来保证数据的一致性,且双方不受影响。
Online Add Index处理流程
1.判断DML是否可以用inplace进行(不新建表)
2.开始进行online操作前期准备
(1.修改表的数据字典信息
(2.等待后台所有线程停止操作此表
(3.online过程中,原表允许读写,所以需要将DML操作的数据记录到row_log中,不在索引上进行更新
3.开始进行真正的online add index操作
(1.读取聚簇索引、排序、并插入到新建索引中,并且将row log中的记录变化,更新到新建索引中
(2.插入新索引完成后,将这期间记录在row_log的记录变化重新运用
(3.新建索引短暂加锁