不锁定整个表的情况下修改表结构

65

做什么呢?

ALTER TABLE sample ADD COLUMN `hasItem` tinyint(1) DEFAULT NULL

锁定整张表格?


8.0.12版本具有“ALGORITHM=INSTANT”功能;请参见https://dev59.com/p1QJ5IYBdhLWcg3wEBi-#54753562。 - Rick James
1个回答

97

简短回答:在 MySQL < 5.6 版本中需要锁。从 5.6 版本开始,并且使用 InnoDB 引擎,许多 ALTER TABLE 操作(包括添加列)不需要锁定


如果您使用的是MySQL 5.5或更早版本,则它将为整个操作获取读锁,然后在最后获取短暂的写锁。

来自ALTER TABLE的MySQL文档...

在大多数情况下,ALTER TABLE会创建原始表的临时副本... 在执行ALTER TABLE时,其他会话可以读取原始表(除了稍后注意到的例外)。开始于ALTER TABLE操作之后的对表格的更新和写入将被暂停,直到新表准备就绪...

前面提到的例外是ALTER TABLE在准备安装新版本的表.frm文件、丢弃旧文件并从表和表定义缓存中清除过时的表结构时阻止读取(不仅仅是写入)。此时,它必须获得独占锁。

也就是说,在添加列时,它会为大部分操作读锁定表,然后在最后获取写锁。


MySQL 5.6在InnoDB中添加了在线DDL,可以加速和改进很多事情,例如修改表和索引。向表中添加列将不再需要表锁除了可能在操作开始和结束时需要短暂的排他锁
应该自动发生,但为了确保,请在ALTER TABLE语句中设置ALGORITHM=inplaceLOCK=none
有一个例外...

在MySQL 5.6之前创建的InnoDB表不支持包含时间列(DATE、DATETIME或TIMESTAMP)且未使用ALTER TABLE ... ALGORITHM=COPY重建的表的ALTER TABLE ... ALGORITHM=INPLACE。


也就是说,当添加一列时,它会在大部分操作中读取锁定表,然后在最后获取写入锁定。根据前面的引用,我认为它应该在大部分操作中写入锁定表,然后在最后获取读取锁定。我有什么遗漏吗? - TanguyP
2
@TanguyP "在这个时候[当准备安装新版本的表.frm文件,丢弃旧文件...],它必须获取一个独占锁。" 独占锁是写锁,会阻塞读和写。读(共享)锁只会阻塞写。 - Schwern

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接