在确保非主键列(即 wid)唯一且自动递增的同时处理并发 SQL 插入的正确实现是什么?

What is the correct implementation of handling concurrent SQL inserts while ensuring a non-primary key column (i.e. wid) unique and auto-incremental?

在确保非主键列(即 wid)唯一且自动递增的同时处理并发 SQL 插入的正确实现是什么?

注意:存在导致此字段(即 wid)未成为主键的设计约束。名为 id 的列中包含一个单独的自动增量 PK。将 wid 更改为 PK 是不可行的,因为数据库设计现在与多个软件项目严重耦合。所以我需要设计一个解决方法。

我正在考虑 3 种可能的方法:

1.) 通过执行事务并继续执行本应包含在同一事务中的其他 SQL 语句来保留 wid。保留在单独的事务中执行,以使锁定尽可能短。但是,如果后续事务失败(例如由于数据库连接问题),则包含保留 wid 的无效行将保留在 table 中。

START TRANSACTION;
SET @wid_d = 0;
SELECT COALESCE(MAX(`wid`), 0) INTO @wid_d FROM table
WHERE `wid >= 0 AND `wid <= 1000 FOR UPDATE;
INSERT INTO table (`wid`) VALUES (IF (@wid_d = 0, 1, @wid_d+1) )
COMMIT;

2.) 包括在整个事务中保留wid,以消除插入无效行的问题,如果事务失败但这种做法会延长tables的锁定。

3.) 依赖事务调用失败重新执行事务,直至执行成功;如果事务由于插入相同的 MAX(wid) + 1 的竞争条件而失败。这种方法将防止插入无效的行,但问题是事务应该重新 运行 的次数。也没有区别知道是wid冲突导致的问题还是其他问题,所以,这是一个有问题的做法。

好吧,根据您的勇敢程度,您还有其他选择,例如创建单独的序列 table 以用于维护 WID 值:

CREATE TABLE wid_seq (wid INT PRIMARY KEY AUTO_INCREMENT);

在您的交易中:

START TRANSACTION;
INSERT INTO wid_seq VALUES (null);
INSERT yourtable (WID) values (LAST_INSERT_ID());
COMMIT;