【问题标题】:Transaction with trigger that use a select max. It return wrong result使用最大选择触发器的事务。它返回错误的结果
【发布时间】:2017-11-05 02:19:58
【问题描述】:

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

表一:

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;

人可以运行这个测试:
第 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。

【问题讨论】:

  • 可能是所有线程都在同时运行insert,然后排队等待其余的“插入”?还是全部在 30-60 秒后“同时”完成?
  • 嗨瑞克。我在我的问题中添加了一些文字。谢谢。

标签: mysql transactions innodb mariadb


【解决方案1】:

将触发器中的SELECT更改为:

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

这告诉交易你打算改变价值;这会阻止其他事务对其进行更改。

这可能会导致您的 30-60 秒事务一个接一个地运行。并且可能由于超过lock_wait_timeout 而死亡。而不是增加该设置(这已经“太高了”),请解释更大的图景。或许我们可以设计一个变通方法来获得“正确”的值并且并行运行。

【讨论】:

  • 嗨 Rick:我运行 Step2 时出现错误:无法更新存储函数/触发器中的表 'a',因为它已被调用此存储函数/触发器的语句使用。跨度>
  • 我的目标是在执行提交语句之前查询 CalcUniqId 的值。无论是否执行回滚或提交。重要的是没有两条记录具有相同的值。
  • AUTO_INCREMENT为什么没有提供这样的功能?
  • 同时从 A 中选择 Max(CalcUniqId) 到 @MaxCalcUniqId;不只是一张桌子。在我的情况下是这样的: select max(GlobalCalcUniqId) from ( select Max(CalcUniqId) GlobalCalcUniqId from TABLE1 union select Max(CalcUniqId) from TABLE2 )A ;
  • 也许不能用触发器来完成。建议你写出所有的语句——没有例程或触发器。然后重新考虑应该将的结构移到例程/触发器中。您可能会发现不同的组织工作得更好。特别是,SELECT MAX... 可能必须是紧跟在BEGIN 之后的显式语句,而不是隐藏在触发器中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多