Answers:
好吧... 多年来,没有人提到一件微妙的事情。
尽管DROP TABLE IF EXISTS `bla`; CREATE TABLE `bla` ( ... );
看似合理,但仍会导致旧表已经消失而新表尚未创建的情况:此时某些客户端可能会尝试访问主题表。
更好的方法是创建一个全新的表并将其与旧表交换(表内容丢失):
CREATE TABLE `bla__new` (id int); /* if not ok: terminate, report error */
RENAME TABLE `bla__new` to `bla`; /* if ok: terminate, report success */
RENAME TABLE `bla` to `bla__old`, `bla__new` to `bla`;
DROP TABLE IF EXISTS `bla__old`;
CREATE ...
并且在出现错误的情况下不要继续,因为失败意味着其他线程没有完成相同的脚本:要么是因为它在中间崩溃了,要么就是还没有完成-这是一个好主意自己检查东西。RENAME ...
,则不要继续:整个操作成功完成;更重要的是,如果另一个线程已经按相同的顺序启动了,则next运行可能(并且将会)是不安全的(覆盖这种情况要比不覆盖这种情况更好,请参见下面的锁定说明)。RENAME ...
RENAME ...
原子替换表定义,
有关详细信息,请参见
MySQL手册。DROP ...
,显然是清理了旧表。用类似的包装所有语句SELECT GET_LOCK('__upgrade', -1); ... DO RELEASE_LOCK('__upgrade');
允许只依次调用所有语句而不进行错误检查,但是我认为这不是一个好主意:复杂性增加,并且MySQL中的锁定函数对于基于语句的复制并不安全。
如果表数据应该在表定义升级后仍然存在...对于一般情况,有关比较表定义以找出差异并产生正确的ALTER ...
语句的故事要复杂得多,这并非总是可以自动进行的,例如在重命名列时。
旁注1:
您可以使用相同的方法处理视图,在这种情况下,CREATE/DROP TABLE
只需变换为即可,CREATE/DROP VIEW
而RENAME TABLE
保持不变。实际上,您甚至可以将桌子变成视图,反之亦然。
CREATE VIEW `foo__new` as ...; /* if not ok: terminate, report error */
RENAME TABLE `foo__new` to `foo`; /* if ok: terminate, report success */
RENAME TABLE `foo` to `foo__old`, `foo__new` to `foo`;
DROP VIEW IF EXISTS `foo__old`;
旁注2:
MariaDB用户应该对感到满意CREATE OR REPLACE TABLE/VIEW
,它已经在乎主题问题了,这很不错。
我需要删除一个表并使用视图中的数据重新创建。我是根据视图创建表的,这就是我所做的:
DROP TABLE <table_name>;
CREATE TABLE <table_name> AS SELECT * FROM <view>;
以上使用MySQL MariaDb为我工作。
CREATE OR REPLACE <table_name> AS SELECT * FROM <view>;