mysql 5.6/5.7 online ddl的change column实验

从官方的Online DDL类型汇总表格看,对修改列的数据类型是不支持in-place方式,会阻塞DML语句,下面就做一个实验:

Session 1:

mysql> desc test_emp;
+-------+------------------+------+-----+-------------------+--------------- --------------+
| 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.13 sec)

mysql> alter table test_emp change c4 c4 varchar(100) null default ' ',algorithm=inplace; --不支持inplace
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
mysql> alter table test_emp change c4 c4 varchar(100) null default ' ';

alter没有结束之前,打开session2

Session 2:

mysql> update test_emp set c4='bb' where id=1;--出现等待

Session 3:

mysql> show processlist;
+----+------+-----------+------+---------+------+---------------------------------+-----------------------------------------------------------------+
| Id | User | Host      | db   | Command | Time | State                           | Info                                                            |
+----+------+-----------+------+---------+------+---------------------------------+-----------------------------------------------------------------+
| 43 | root | localhost | l5m  | Query   |    5 | Waiting for table metadata lock | update test_emp set c4='bb' where id=1                          |
| 44 | root | localhost | l5m  | Query   |    6 | copy to tmp table               | alter table test_emp change c4 c4 varchar(100) null default ' ' |
| 45 | root | localhost | NULL | Query   |    0 | starting                        | show processlist                                                |
+----+------+-----------+------+---------+------+---------------------------------+-----------------------------------------------------------------+

update操作正在等待alter后获得mdl锁,此时later在copy数据,从数据文件可以看到多出的2个临时文件。

[root@qht131 l5m]# ls -lth
total 201M
-rw-r-----. 1 mysql mysql  72M Mar 30 23:41 #sql-3330_2c.ibd
-rw-r-----. 1 mysql mysql 8.5K Mar 30 23:41 #sql-3330_2c.frm
-rw-r-----. 1 mysql mysql 128M Mar 30 05:45 test_emp.ibd
-rw-r-----. 1 mysql mysql 8.5K Mar 30 05:45 test_emp.frm

那如果session不是update,仅仅是select会不会阻塞呢?

Session 1:

mysql> alter table test_emp change c4 c4 varchar(80) null default ' ';

Session 2:

mysql> select * from test_emp limit 1;
+----+-------+-------+-------+---------------------+------+
| id | c1    | c2    | c5    | c3                  | c4   |
+----+-------+-------+-------+---------------------+------+
|  1 | 79861 | 85039 | 85614 | 2018-03-30 05:38:41 | bb   |
+----+-------+-------+-------+---------------------+------+
1 row in set (0.00 sec)

Session 3:

mysql> show processlist;
+----+------+-----------+------+---------+------+-------------------+----------------------------------------------------------------+
| Id | User | Host      | db   | Command | Time | State             | Info                                                           |
+----+------+-----------+------+---------+------+-------------------+----------------------------------------------------------------+
| 43 | root | localhost | l5m  | Sleep   |    2 |                   | NULL                                                           |
| 44 | root | localhost | l5m  | Query   |    3 | copy to tmp table | alter table test_emp change c4 c4 varchar(80) null default ' ' |
| 46 | root | localhost | NULL | Query   |    0 | starting          | show processlist                                               |
+----+------+-----------+------+---------+------+-------------------+----------------------------------------------------------------+
3 rows in set (0.00 sec)发

发现并没有对select阻塞,所以修改列的数据类型和长度会对DML阻塞,对select 语句不阻塞。


你可能感兴趣的:(MYSQL)