1

我需要重命名 MySQL 表并同时创建一个新的 MySQL 表。

有大量记录的关键活动表。master_table总是从脚本中插入记录。

需要备份主表,同时创建另一个同名的主表。

一般的SQL是这样的。

RENAME TABLE master_table TO backup_table;

Create table master_table (id,value) values ('1','5000');

在执行上述查询期间是否有可能记录丢失的数据?

有什么办法可以避免丢失记录?锁定主表等...

4

2 回答 2

5

我要做的是以下。它不会导致停机,不会丢失数据,并且几乎可以立即执行。

CREATE TABLE mytable_new LIKE mytable;

...possibly update the AUTO_INCREMENT of the new table...

RENAME TABLE mytable TO mytable_old, mytable_new TO mytable;

通过在一个语句中重命名两个表,它们被原子交换。在没有表接收写入的情况下,没有机会在“中间”写入任何数据。如果您不以原子方式执行此操作,则某些写入可能会失败。

RENAME TABLE 几乎是即时的,无论表有多大。您不必等待数据被复制。

如果表有一个自增主键,我想确保新表以大于旧表中当前 id 的 id 值开始。在交换表名之前执行此操作。

SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='mydatabase' AND TABLE_NAME='mytable';

我喜欢为该值添加一些舒适的余量。您要确保插入旧表的 id 值不会超过您从 INFORMATION_SCHEMA 查询的值。

更改新表以将此新值用于其下一个自动增量:

ALTER TABLE mytable_new AUTO_INCREMENT=<increased value>;

然后立即执行 RENAME TABLE 来交换它们。一旦将新行插入到新的空表中,它将使用从增加的自动增量值开始的 id 值,如果您及时执行这些步骤,该值仍应大于插入旧表中的最后一个 id。

于 2018-03-13T17:12:42.923 回答
3

无需重命名 master_backup 表并重新创建它,您只需使用 master_table 中的数据创建一个 backup_table 以用于第一次备份运行。

CREATE TABLE backup_table AS
   SELECT * FROM master_table;

如果您必须向备份表添加主键,则只运行一次,即第一次备份:

ALTER TABLE backup_table ADD CONSTRAINT pk_backup_table PRIMARY KEY(id);

对于将来的备份,请执行以下操作:

INSERT INTO backup_table 
  SELECT * FROM master_table;

然后您可以删除 master_table 中找到的 backup_table 中的所有数据,例如:

DELETE FROM master_table A JOIN 
       backup_table B ON A.id=B.id;

然后,您可以使用以下查询将数据添加到 master_table:

INSERT INTO master_table (`value`) VALUES ('5000'); -- I assume the id field is auto_incrementable

我认为即使没有锁定主表并且没有丢失执行,这也应该可以完美地工作。

于 2018-03-13T05:21:43.003 回答