我有我的数据库,每天我必须在其中存储从API获取的新数据。问题是我必须每天截断表,然后在同一表中插入新获取的记录。记录数约为1万。插入新记录需要5-10秒。
因此,我担心的是,如果我截断该表并且某些用户一次请求,那么由于我将表截断,他将最终出现错误。那么,您能建议我该怎么做才能解决这个问题?我不是DBA,所以请提出更好的方法。
您可以使用2个具有相同结构的表,然后使用RENAME。 RENAME是原子的,因此不会被中断。
RENAME TABLE t1 TO tmp_table,
t2 TO t1,
tmp_table TO t2;
TRUNCATE Table t2;
表锁可能有效。获取表锁将导致其他用户等待或超时。但是,在5到10秒钟内,这可能太长了。
探索交易是否有效。使用BEGIN WORK
语句启动事务,完成后执行COMMIT
。
看来您正在截断记录,以便可以从API刷新数据。但是,这会引起问题,因为某些人正在使用这些记录。
一种更好的方法是使用DELETE
而不是TRUNCATE
,以便可以将其包装在事务中。我认为表截断会立即生效,因此您需要(较慢)删除。就像这样:
插入10K新记录的5-10秒可能很好-在此期间使用系统的用户将只看到旧记录。
使用MySQL的Exchanging Partitions and Subpartitions with Tables,您可以在自己的时间处理单独的相同表。准备就绪后,您可以将其交换为“真实”表中的分区。要注意的是,您必须创建表的分区,但是只需要一个分区。还要从提到的参考文献中找到(nt
这是您的表格):
表
nt
不包含外键引用,其他表也没有引用nt
的任何外键。
下面的示例与本文中的示例相似,但出于完整性考虑而给出:
这是“真实”表:
CREATE TABLE stackoverflow (
id INT PRIMARY KEY,
test VARCHAR(30)
);
创建新表之前对“真实”表进行分区。然后,您不必从副本中删除任何内容:
CREATE TABLE stackoverflow_workinprogess LIKE stackoverflow;
仅在“真实”表上创建一个分区:
ALTER TABLE stackoverflow PARTITION BY RANGE (id) (
PARTITION p VALUES LESS THAN (MAXVALUE)
);
为示例插入一些随机数据:
INSERT INTO stackoverflow VALUES
(1, "Test 1"),
(2, "Test 2"),
(3, "Test 3"),
(4, "Test 4"),
(5, "Test 5");
现在您可以处理stackoverflow_workinprogess表中的数据:
TRUNCATE TABLE stackoverflow_workinprogess;
INSERT INTO stackoverflow_workinprogess VALUES
(1, "Test a - new row"),
(2, "Test b - new row"),
(3, "Test c - new row"),
(4, "Test d - new row"),
(6, "Test e - new row"), -- skipping one on purpose
(7, "Test f - new row");
完成后,交换/交换分区:
ALTER TABLE stackoverflow EXCHANGE PARTITION p WITH TABLE stackoverflow_workinprogess;
结果:
select * from stackoverflow;
id | test
----|-----------------
1 | Test a - new row
2 | Test b - new row
3 | Test c - new row
4 | Test d - new row
6 | Test e - new row
7 | Test f - new row
全部包含在此dbfiddle.uk中
我没有尝试在stackoverflow_workinprogess
表上创建分区,但是如果结果有所不同,我会感到惊讶。