我有一个复杂的数据库。我可以这样简化:
表a:
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;
问题是,触发器为同时运行的所有事务返回相同的CalcUniqId。
是否有任何解决方案或工作。
这是一个解决方案:
start transaction;
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
insert into A(A) values(10);
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
....
commit;
男人可以进行这个测试:
第一节:
Step1: start transaction;
Step2: insert into A(A) values(1);
Step3: commit;
第二节:
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.
答案 0 :(得分:2)
将触发器中的SELECT
更改为:
select Max(CalcUniqId) from A into @MaxCalcUniqId
FOR UPDATE; -- add this
告诉交易你打算改变价值;阻止其他交易改变它。
这可能会导致您的30-60秒交易一个接一个地运行。并且可能因超过lock_wait_timeout
而死亡。请注意更大的图片,而不是增加设置(已经“太高”)。也许我们可以编写一个解决方法,使得“正确”值和并行运行。