间歇性地从 mysql innodb 查询中获取旧数据

Intermittently getting old data from mysql innodb queries

我们有各种 table 来表示各种类型的数据。每个 table 都有相应的修订 table 来跟踪此数据的历史记录。每个修订版(修订版 table 中的条目)都有一个唯一的编号。此数字存储在更改元数据 table 中。这些 table 中的每一个都引用了一个 parent_id。在我们对 table 进行任何更改之前,我们将父行锁定为 SELECT ... FOR UPDATE.

在进行 update/insert 之后,我们还会增加更改编号并将该编号写入更改元数据 table。为此,我们对更改元数据编号执行 SELECT MAX,然后递增。

我们看到的问题是,交易以某种方式从 select max 语句中获取旧的更改编号。举例说明:

交易 1:

开始交易

锁定更新

做事...

获取最新更改编号 (9)

插入编号为 10 的修订

提交

交易 2:

开始交易

锁定更新

做事...

获取最新更改编号 (7)

插入编号为 8 的修订本

提交

这会导致事务 2 的修订插入失败,因为更改编号是唯一键。我倾向于它是 repeatable 读取的问题,但我不确定旧数据如何以这种方式跨事务持续存在。对于每个事务都有一个 START TRANSACTION 语句,然后立即使用 FOR UPDATE 锁定父 ID。我们有一个具有多个并发事务的高流量站点。任何时候都可能有很多人在等待锁。我很乐意澄清任何一点,并感谢任何人提供的任何见解。

SELECT MAX on the change metadata number

那也需要 FOR UPDATE

另一种方法:

有一个"sequence number generator"table.

CREATE TABLE Sequence (
    pk TINYINT NOT NULL,
    seq INT UNSIGNED NOT NULL AUTO_INCREMENT,
    PRIMARY KEY(pk),   -- For ON DUPLICATE KEY UPDATE
    INDEX(seq)         -- Sufficient for AUTO_INCREMENT
);

唯一的动作(一旦初始化)应该是

INSERT INTO Sequence (pk, seq) VALUE (1, 0)
    ON DUPLICATE KEY UPDATE seq := LAST_INSERT_ID(seq+1);

这将自动更新一行。然后(在同一连接中)执行此操作以获得新的 seq:

SELECT LAST_INSERT_ID();

该声明与连接相关联,因此其他人不可能获得您的号码。