Answers:
在MySQL 5.6和更高版本中,在创建或删除索引时,该表仍可用于读取和写入操作。CREATE INDEX或DROP INDEX语句仅在访问表的所有事务完成后才完成,因此索引的初始状态反映了表的最新内容。以前,在创建或删除索引时修改表通常会导致死锁,从而取消表上的INSERT,UPDATE或DELETE语句。
从上面的答案:
“如果在数据库联机时使用的版本大于5.1索引,则创建该版本。因此不必担心不会中断生产系统的使用。”
这是**** FALSE ****(至少对于MyISAM / InnoDB表而言,这是在那里使用的99.999%的人使用的功能。群集版则有所不同。)
在表上执行更新操作将BLOCK正在创建索引时。MySQL对此确实(以及其他一些东西)非常愚蠢。
测试脚本:
(
for n in {1..50}; do
#(time mysql -uroot -e 'select * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
(time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'
我的服务器(InnoDB):
Server version: 5.5.25a Source distribution
输出(注意第六个操作如何阻塞约400ms来完成索引更新):
1 real 0m0.009s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.012s
5 real 0m0.009s
Index Update - START
Index Update - FINISH
6 real 0m0.388s
7 real 0m0.009s
8 real 0m0.009s
9 real 0m0.009s
10 real 0m0.009s
11 real 0m0.009s
与不阻塞的读取操作(交换脚本中的行注释):
1 real 0m0.010s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.010s
5 real 0m0.009s
Index Update - START
6 real 0m0.010s
7 real 0m0.010s
8 real 0m0.011s
9 real 0m0.010s
...
41 real 0m0.009s
42 real 0m0.010s
43 real 0m0.009s
Index Update - FINISH
44 real 0m0.012s
45 real 0m0.009s
46 real 0m0.009s
47 real 0m0.010s
48 real 0m0.009s
到目前为止,我所知道的只有一种方法可以更新MySql模式,而不会出现可用性中断的情况。通函大师:
不是一种简单的更新架构的方法。在恶劣的生产环境中可行;是的。拜托,拜托,拜托,如果有一种更简单的方法可以在不阻止写入的情况下向MySQL表添加索引,请告诉我。
谷歌搜索使我引向这篇文章,它描述了类似的技术。更好的是,他们建议在手术过程中的同一时间喝酒(请注意,在阅读本文之前,我已经写了答案)!
我上面链接的文章讨论了一种工具pt-online-schema-change,其工作方式如下:
我从未亲自尝试过该工具。青年汽车
我目前正在通过Amazon的RDS使用MySQL 。这是一个非常漂亮的服务,用于包装和管理MySQL,使您可以通过一个按钮添加新的只读副本,并跨硬件SKU透明地升级数据库。真的很方便 您没有对数据库的超级访问权限,因此无法直接破坏复制(这是福还是祸?)。但是,您可以使用只读副本升级在只读从属服务器上更改架构,然后将其升级为新的主服务器。与我上面描述的技巧完全相同,但执行起来却非常容易。他们仍然没有为您提供帮助。您必须重新配置并重新启动您的应用程序。
MySQL 5.6更新(2013年2月):现在,即使在使用InnoDB表创建索引时,您也可以执行读写操作-http: //dev.mysql.com/doc/refman/5.6/en/innodb-create-index -overview.html
在MySQL 5.6和更高版本中,在创建或删除索引时,该表仍可用于读取和写入操作。CREATE INDEX或DROP INDEX语句仅在访问表的所有事务完成后才完成,因此索引的初始状态反映了表的最新内容。以前,在创建或删除索引时修改表通常会导致死锁,从而取消表上的INSERT,UPDATE或DELETE语句。
和:
在MySQL 5.6中,此功能变得更加通用:您可以在创建索引的同时对表进行读写,并且可以执行多种ALTER TABLE操作,而无需复制表,不阻塞DML操作或同时执行这两种操作。因此,在MySQL 5.6和更高版本中,我们通常将此功能集称为在线DDL,而不是快速索引创建。
来自http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_fast_index_creation
如果您确实要确保迁移不会导致站点崩溃,那么可以进行pt-online-schema-change。
正如我在上述评论中所写的那样,我在生产中进行pt-online-schema-change方面有一些经验。我们有20M +条记录的主表和一个主目录-> 2个只读复制从属目录。从添加新列,更改字符集到添加多个索引,我至少完成了pt-online-schema-change的数十次迁移。在迁移期间,我们也为大量的流量提供服务,而且我们没有遇到任何麻烦。当然,在生产上运行之前,您必须非常彻底地测试所有脚本。
我试图将更改批量添加到1个脚本中,以便pt-online-schema-change只需要复制一次数据。并且更改列名时要非常小心,因为这会丢失数据。但是,添加索引应该没问题。
pt-online-schema-change
。很好,但是在许多情况下,MySQL 5.6+的在线DDL功能已经可以正常工作了,这是过分的。它还有局限性(例如不能很好地使用触发器),并且在进行模式更改时,每次插入原始表所需的写入量加倍。与普通的在线模式更改相比,它将给您的磁盘增加更多的负担,因此,在仅运行模式更改即可正常运行的情况下,就有可能“破坏您的站点”。
pt-online-schema-change
是有用的工具,但在许多情况下,普通的在线DDL既好又少数,它更好。因此,对它的任何建议都应谨慎考虑,而不是通用。