我只是想在数据库中的表(main_table)中添加一个名为“location”的列。我运行的命令是
ALTER TABLE main_table ADD COLUMN location varchar (256);
main_table包含> 2,000,000行。它持续运行超过2小时仍未完成。
我尝试使用mytop
监视此数据库的活动,以确保查询未被其他查询过程锁定,但似乎没有。应该花那么长时间吗?实际上,我刚刚在运行此命令之前重启了机器。现在这个命令仍在运行。我不知道该怎么做。
答案 0 :(得分:166)
你的ALTER TABLE
语句暗示mysql必须重写表的每一行,包括新列。由于您有超过200万行,我肯定会花费大量时间,在此期间您的服务器可能主要受IO限制。您通常会发现执行以下操作更具效果:
CREATE TABLE main_table_new LIKE main_table;
ALTER TABLE main_table_new ADD COLUMN location varchar(256);
INSERT INTO main_table_new (fields_in_main_table) SELECT * FROM main_table;
RENAME TABLE main_table TO main_table_old, main_table_new TO main_table;
DROP TABLE main_table_old;
这样你就可以在空表上添加列,并且基本上在新表中写入数据,你确定没有其他人会在没有锁定太多资源的情况下查看。
答案 1 :(得分:22)
我认为适当的答案是使用pt-online-schema-change或gh-ost等功能。
我们已经完成了超过40亿行的迁移,但这可能需要长达10天,停机时间不到一分钟。
Percona的工作方式与上述非常相似
答案 2 :(得分:0)
Alter table需要花费很长时间来处理像你这样的大数据,所以在这种情况下避免使用它,并使用像这样的代码:
select main_table.*,
cast(null as varchar(256)) as null_location, -- any column you want accepts null
cast('' as varchar(256)) as not_null_location, --any column doesn't accept null
cast(0 as int) as not_null_int, -- int column doesn't accept null
into new_table
from main_table;
drop table main_table;
rename table new_table TO main_table;
答案 3 :(得分:0)
您可以通过暂时关闭唯一检查和外键检查来加快进程。您还可以更改使用的算法。
如果您希望新列位于表的末尾,则应使用 algorithm=instant
:
SET unique_checks = 0;
SET foreign_key_checks = 0;
ALTER TABLE main_table ADD location varchar(256), algorithm=instant;
SET unique_checks = 1;
SET foreign_key_checks = 1;
否则,如果您需要该列位于特定位置,请使用 algorithm=inplace
:
SET unique_checks = 0;
SET foreign_key_checks = 0;
ALTER TABLE main_table ADD location varchar(256) AFTER othercolumn, algorithm=inplace;
SET unique_checks = 1;
SET foreign_key_checks = 1;
作为参考,我的 PC 用了大约 2 分钟的时间使用就地算法更改一个包含 2000 万行的表。如果您使用的是 Workbench 之类的程序,那么您可能需要在开始操作之前增加设置中的默认超时时间。
如果您发现操作无限期挂起,那么您可能需要查看进程列表并杀死表上有锁定的任何进程。您可以使用以下命令执行此操作:
SHOW FULL PROCESSLIST;
KILL PROCESS_NUMBER_GOES_HERE;
答案 4 :(得分:-1)
DB2 z/OS 立即对列进行虚拟添加。并将表置于咨询重组状态。在重组之前运行的任何内容都将获得默认值,如果没有默认值,则为 null。更新完成后,它们会展开更新的行。插入已完成扩展。下一次重组将展开每个未展开的行,并为其展开的任何内容分配默认值。
只有真正的数据库才能很好地处理这个问题。 DB2 z/OS。