批量插入是原子的吗?

Posted

技术标签:

【中文标题】批量插入是原子的吗?【英文标题】:Is bulk insert atomic? 【发布时间】:2010-09-09 14:32:17 【问题描述】:

我有带有自动递增主键的表。我想在其中插入一堆数据并获取每个数据的键,而无需额外查询。

START TRANSACTION;
INSERT INTO table (value) VALUES (x),(y),(z);
SELECT LAST_INSERT_ID() AS last_id;
COMMIT;

mysql 能否保证所有数据都插入到一个连续的有序流中,以便我可以轻松计算每个元素的 id?

id(z) = last_id;
id(y) = last_id - 1;
id(x) = last_id - 2;

【问题讨论】:

last_insert_id() 将为您提供多个插入的第一个插入的 ID。所以你应该做 last_id + 1 和 last_id + 2 而不是减号。 【参考方案1】:

如果您开始一个事务,然后将数据插入到一个表中,则整个表将锁定到该事务(除非您开始使用事务隔离级别和/或锁定提示)。

这基本上是交易的重点。为了防止外部操作(无论如何)改变您正在操作的内容。

这种“表格锁定”是大多数情况下的默认行为。

在不寻常的情况下,您会发现 RDBMS 设置了某些选项,这意味着该特定安装不会发生“正常”默认(表锁定)行为。如果是这种情况,您应该能够通过指定您想要一个表锁作为 INSERT 语句的一部分来覆盖默认值。

编辑:

我在 MS-SQL Server 方面拥有丰富的经验,而在许多其他 RDBMS 方面的经验并不丰富。在那段时间里,我没有找到任何保证插入将以特定顺序发生。

其中一个原因是 INSERT 的 SELECT 部分可以并行计算。这意味着要插入的数据是乱序的。

同样,在插入特别大量的数据时,RDBMS 可能会识别出新数据将跨越几页内存或磁盘空间。同样,这可能会导致并行操作。

据我所知,MySQL 有一个 row_number() 类型的函数,您可以在 SELECT 查询中指定该函数,您可以将其结果存储在数据库中。然后,您将能够依赖该字段(由您构建),但不能依赖自动增量 id 字段(由 RDBMS 构建)。

【讨论】:

【参考方案2】:

据我所知,这几乎适用于所有 SQL 引擎。

【讨论】:

只是为了确定,有证据吗?官方文档什么的。 由于每个表只有最高的ID被存储为AUTOINCREMENT-value,因此某些SQL引擎不太可能再次使用已发布的ID。 并发插入的情况?那么 order 呢,它总是和查询中的一样吗? 因为它在事务中,所以不能有并发插入。至于顺序,我不确定。 @Elsuive:事实上,如果你开始一个事务,插入,然后回滚,在事务生命周期内生成的 ID 将被“丢失”并且不会被回收。至少在我曾经使用过的每个 RDBMS 中。 [我也相信 OP 正在寻找明确的答案,而不是“不太可能”。]

以上是关于批量插入是原子的吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何确保以原子方式完成 JDBC 批量插入?

为啥批量插入/更新更快?批量更新如何工作?

Set,Sorted Set相关命令操作,批量插入及管道,事务

批量插入数据

Java--MyBatis批量插入批量更新和批量删除

在实体框架中批量插入后批量插入记录并获取它们的 ID