触发器交易使用 select 最大值。结果return错误

Transaction with trigger that use a select max. It return wrong result

我有一个复杂的数据库。我可以这样简化它:

table一个:

CREATE TABLE a
(
Id int(10) unsigned NOT NULL AUTO_INCREMENT,
A int(11) DEFAULT NULL,
CalcUniqId int(11) DEFAULT NULL,
PRIMARY KEY (Id)     
) ENGINE=InnoDB;

CREATE TRIGGER a_before_ins_tr before INSERT on a
FOR EACH ROW
BEGIN
  select Max(CalcUniqId) from A into @MaxCalcUniqId;
  set new.CalcUniqId=IfNull(@MaxCalcUniqId,1)+1;
END $

它是这样工作的:

start transaction
insert into A(A)
... insert in other tables. It take between 30 and 60 seconds
commit;

问题是,同时 运行 的所有事务触发 returns 相同的 CalcUniqId。

是否有任何解决方案或解决方法。

这是解决方案吗:

start transaction;
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
insert into A(A) values(10);
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
....
commit;

男人可以运行这个测试:
第 1 节:

Step1: start transaction;
Step2: insert into A(A) values(1);
Step3: commit;

第 2 节:

Step1: start transaction;
Step2: insert into A(A) values(2);
Step3: commit;

运行 在会话 1 中执行步骤 1,2,在会话 2 中执行步骤 1,2。两者都比第 3 步。之后做

select Id, A, CalcUniqId from a;

两者具有相同的 CalcUniqId=2。

将触发器中的 SELECT 更改为:

select Max(CalcUniqId) from A into @MaxCalcUniqId
    FOR UPDATE;   -- add this

告诉交易你打算改变价值;阻止其他事务更改它。

这可能会导致您的 30-60 秒交易一个接一个 运行。并且可能因为超过lock_wait_timeout而死亡。不要增加该设置(已经是 "too high"),请解释大局。或许我们可以想出一个解决方法,并行获取 'correct' 值 运行s。