如何知道未提交的事务是否尝试将特定的唯一键插入 SQL

How to know if an uncommitted transaction tries to insert a specific unique key into SQL

我正在编写一个程序,将数据插入 MariaDB-Server 并可供不同的人同时使用。事务需要一些时间,因此可能会出现以下问题:A 开始事务时使用主键 "c",事务尚未提交时,B 想使用相同的主键 "c" 插入数据.如何防止 B 使用 A 已在其未提交事务中使用的主键开始其事务?

我使用 MariaDB 作为数据库,使用 InnoDB 作为引擎。

我检查了隔离级别,但不知道如何使用它们来解决我的问题。

谢谢!

主键是确保行唯一性的内部值,并不意味着暴露给外部世界。

使用 IDENTITY 列或使用 SEQUENCE 生成主键。他们将优雅地处理多个同时插入,并将为每个分配不同的值。

使用 IDENTITY:

CREATE TABLE house (
  id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  address VARCHAR(40) NOT NULL
);

INSERT INTO house (address) VALUES ('123 Maple Street');

使用序列:

CREATE SEQUENCE myseq1;

CREATE TABLE house (
  id INTEGER NOT NULL PRIMARY KEY,
  address VARCHAR(40) NOT NULL
);

INSERT INTO house (id, address) VALUES (NEXT VALUE FOR myseq1, '123 Maple Street');

每个 table 应该有一个 PRIMARY KEY。在 MySQL 中,根据定义,PRIMARY KEYUNIQUE

您还可以在 table 上声明 UNIQUE 个键。

每个连接都应该这样做来标记事务:

BEGIN;
various SQL statements
COMMIT;

如果这些 SQL 语句中的任何一个插入一行,它会使用唯一键来阻止其他人将相同的唯一值插入到 table 中。这将导致某种形式的错误——死锁(对事务来说是致命的),"lock wait timeout"——它可能会从中恢复,等等。

注意:如果您在交易中有任何SELECTs,您可能需要在它们的末尾贴上FOR UPDATE。这表明您 可能 在事务中更改哪些行,从而提醒其他连接不要挡路。

可以查明这是否正在发生吗?并不真地。但是为什么要打扰呢?只需努力向前,做你需要做的事。但是检查错误以查看是否有其他连接阻止您这样做。

想到是"optimistic"编码。

不用管隔离级别;它只会给 典型 任务增加混乱。

它与事务隔离级别无关。这是关于锁定。

对索引中特定条目的任何 insert/update/delete 都会锁定该条目。锁被授予先到先得。尝试对同一索引条目执行 insert/update/delete 的下一个会话将被阻止。

你可以自己演示这个。并排打开两个 MySQL 客户端 windows。

第一个window:

mysql> START TRANSACTION;
mysql> INSERT INTO mytable SET c = 42;

那就先不要提交。

第二个window:

mysql> INSERT INTO mytable SET c = 42;

注意它此时挂起,等待锁定。

第一个window:

mysql> commit;

第二个window最后returns:

ERROR 1062 (23000): Duplicate entry '42' for key 'PRIMARY'