从官方的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 语句不阻塞。