我需要在大型 InnoDB 生产表上创建索引,并且希望在不以任何方式锁定表的情况下执行此操作。我正在使用 MySQL 5.6 (.38-83.90)。
我试过
create index my_index on my_table(col1, col2);
Run Code Online (Sandbox Code Playgroud)
两列都不是主键。col1 是外键。
好吧,这完全锁定了桌子。其他查询因“等待表元数据锁定”而陷入停滞,导致我的网站瘫痪。我不得不终止创建索引查询。
从这个https://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html我认为它不会锁定表:“...不需要语法更改.. .在创建或删除索引时,该表仍可用于读写操作。”
我看到我可以设置 LOCK=NONE 或 LOCK=SHARED,但我不认为它应该是必要的,或者如果有的话,我需要使用哪一个。
“您可以指定 LOCK=NONE 来断言在 DDL 操作期间允许并发 DML。MySQL在可能的情况下自动允许并发 DML。 ”
“您可以指定 LOCK=SHARED 来断言在 DDL 操作期间允许并发查询。如果可能,MySQL 会自动允许并发查询。 ”
所有限制https://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-limitations.html似乎都不适用于我的情况。
我缺少什么?
我的猜测(只是猜测)是您错过了声明ALGORITHM=INPLACE中的条款CREATE INDEX。
CREATE INDEX my_index ON my_table(col1, col2) ALGORITHM=INPLACE ;
^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
还要注意事务获取和持有元数据锁。
https://dev.mysql.com/doc/refman/5.6/en/metadata-locking.html
任何已引用的事务my_table将继续持有该表上的元数据锁,直到该事务被提交或回滚。我建议检查输出TRANSACTIONS部分SHOW ENGINE INNODB STATUS。