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. E.g.
我想交换表并将new table_a的auto_increment设置为table_b的MAX(id)+1。例如。
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?
1 个解决方案
#1
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. Would that work?
我的另一个想法是你可以为插入创建一个MERGE表,将合并方法更新为FIRST或LAST而不是(连同?)交换表。那会有用吗?
- 12.1.7. ALTER TABLE Syntax
- B.1.7.1. Problems with ALTER TABLE
- 12.4.3. Statements That Cause an Implicit Commit
- 12.4.5.1. Interaction of Table Locking and Transactions
12.1.7。 ALTER TABLE语法
B.1.7.1。 ALTER TABLE的问题
12.4.3。导致隐含提交的语句
12.4.5.1。表锁定和事务的交互
#1
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. Would that work?
我的另一个想法是你可以为插入创建一个MERGE表,将合并方法更新为FIRST或LAST而不是(连同?)交换表。那会有用吗?
- 12.1.7. ALTER TABLE Syntax
- B.1.7.1. Problems with ALTER TABLE
- 12.4.3. Statements That Cause an Implicit Commit
- 12.4.5.1. Interaction of Table Locking and Transactions
12.1.7。 ALTER TABLE语法
B.1.7.1。 ALTER TABLE的问题
12.4.3。导致隐含提交的语句
12.4.5.1。表锁定和事务的交互