触发器交易使用 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。
我有一个复杂的数据库。我可以这样简化它:
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。