在MySQL中执行ALTER TABLE语句时,在语句执行期间,整个表都是读锁的(允许并发读取,但禁止并发写入)。如果是一个大表,INSERT或UPDATE语句可能会被阻塞很长一段时间。有没有一种“热修改”的方法,比如添加一列,这样表在整个过程中仍然是可更新的?
我主要对MySQL的解决方案感兴趣,但如果MySQL不能做到这一点,我也会对其他的关系数据库管理系统感兴趣。
为了澄清,我的目的只是为了避免在将需要额外表列的新特性推送到生产环境时出现停机。任何数据库模式都会随着时间的推移而改变,这只是生活中的一个事实。我不明白为什么我们应该接受这些变化必然会导致停机;这是软弱的。
发布于 2012-10-11 03:23:38
Percona开发了一个名为pt-online-schema-change的工具,可以实现这一点。
它本质上是制作一个表的副本并修改新的表。为了使新表与原始表保持同步,它使用触发器进行更新。这允许在后台准备新表的同时访问原始表。
这类似于上面建议的Dems方法,但它是以自动方式完成的。
他们的一些工具有一个学习曲线,即连接到数据库,但一旦你有了它,他们就是很好的工具。
例如:
pt-online-schema-change --alter "ADD COLUMN c1 INT" D=db,t=numbers_are_friends
发布于 2011-03-16 11:37:49
请参阅Facebook的在线模式更改工具。
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-mysql/430801045932
不是为胆小的人准备的;但它可以完成这项工作。
发布于 2009-01-21 05:52:59
既然您问到了其他数据库,这里有一些关于Oracle的信息。
向Oracle表添加空列是一个非常快速的操作,因为它只更新数据字典。这会在很短的一段时间内持有表上的独占锁。但是,它将使任何无效的存储过程、视图、触发器等失效。这些将被自动重新编译。
如果需要,可以从那里使用ONLINE子句创建索引。同样,只有非常短的数据字典锁。它将读取整个表以查找要索引的内容,但在执行此操作时不会阻塞任何人。
如果您需要添加外键,您可以这样做,并让Oracle信任您数据是正确的。否则,它需要读取整个表并验证所有的值,这可能会很慢(首先创建索引)。
如果需要将默认值或计算值放入新列的每一行,则需要运行大规模更新,或者可能运行一些实用程序来填充新数据。这可能会很慢,特别是当行变得更大并且不再适合它们的块时。在此过程中可以管理锁定。由于仍在运行的应用程序的旧versino不知道此列,因此您可能需要一个偷偷摸摸的触发器或指定一个默认值。
在此基础上,您可以在应用程序服务器上切换到新版本的代码,它将继续运行。放下你那偷偷摸摸的扳机。
或者,你也可以使用DBMS_REDEFINITION,它是一个黑盒,设计用来做这类事情。
所有这些都是如此麻烦的测试,等等,以至于当我们发布一个主要版本时,我们只是在周日一大早就停机了。
https://stackoverflow.com/questions/463677
复制相似问题