简体   繁体   English

如何交换MySQL表并自动更改auto_increment?

[英]How to swap MySQL table and change auto_increment atomically?

I have two tables: 我有两个表:

CREATE TABLE table_a (
    id SERIAL
);
CREATE TABLE table_b (
    id SERIAL
);

I want to swap the tables out and set the auto_increment of the new table_a to the MAX(id)+1 of table_b. 我想换出表并将新table_a的auto_increment设置为table_b的MAX(id)+1。 Eg 例如

SELECT @A:=MAX(id) FROM table_a;
SET @qry = CONCAT('ALTER TABLE table_b AUTO_INCREMENT =', @A+1);
PREPARE stmt FROM @qry;
EXECUTE stmt;
RENAME TABLE table_a TO table_b_tmp, table_b TO table_a, table_b_tmp TO table_a;

Unfortunately I can't lock the tables nor do this in a transaction as RENAME TABLE doesn't work on a locked table and ALTER TABLE implicitly commits. 不幸的是,我无法锁定表,也无法在事务中执行此操作,因为RENAME TABLE在锁定的表上不起作用,并且ALTER TABLE隐式提交。

The only solution I can think of to avoid overlapping ids is to set the auto_increment + 50, but as this process is happening frequently I'd rather not have loads of holes in my ids. 我唯一想到的避免重叠id的解决方案是设置auto_increment + 50,但是由于此过程频繁发生,所以我宁愿在id中不要有很多漏洞。

Any ideas? 有任何想法吗?

As long as the server is not on a version of MS Windows and you stick with non-transactional tables, you should be able to use table locks and ALTER TABLE table_name RENAME TO new_table_name statements. 只要服务器不在MS Windows版本上并且坚持使用非事务处理表,就应该能够使用表锁和ALTER TABLE table_name RENAME TO new_table_name语句。

LOCK TABLES table_a WRITE, table_b WRITE;
SELECT @A:=MAX(id)+1 FROM table_a;
ALTER TABLE table_a RENAME TO table_a_tmp;
LOCK TABLES table_b WRITE, table_a_tmp WRITE;
PREPARE stmt FROM 'ALTER TABLE table_b RENAME TO table_a, AUTO_INCREMENT = ?';
EXECUTE stmt USING @A;
ALTER TABLE table_a_tmp RENAME TO table_b;
UNLOCK TABLES;

The second lock worries me. 第二把锁让我担心。 If there are any other pending sessions, will they get a chance at the tables before the lock? 如果还有其他挂起的会话,那么在锁定之前,他们是否有机会在桌子旁? I could also easily be wrong about the above working. 对于上述工作,我也很容易出错。 I'm basing the above on the pages below about locks, transactions and ALTER statements. 我将以上内容基于以下有关锁,事务和ALTER语句的页面。

My other thought is you could create a MERGE table for inserts, updating the merge method to FIRST or LAST instead of (along with?) swapping the tables. 我的另一个想法是,您可以为插入创建MERGE表,将merge方法更新为FIRST或LAST,而不是(以及?)交换表。 Would that work? 那行得通吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM