InnoDB事务原理

InnoDB transaction principle

抱歉,如果这是一个愚蠢的问题。 我有 MySQL InnoDB 应用程序和 70+ tables 并使用事务。 一切正常,除了一件事 (table):

CREATE TABLE IF NOT EXISTS `mag_pj_art_sums` (
`id` int(11) NOT NULL,  (primary key)
`id_pj` int(11) NOT NULL,   (index)
`id_artikal` int(11) NOT NULL,  (index)
`kol_stanje_knjig` decimal(18,2) DEFAULT NULL)

我对所有查询都使用相同的原则:

START TRANSACTION (query('set autocommit=0;'); query('START TRANSACTION;');)
SELECT … FROM table WHERE …
UPDATE TABLE SET …. WHERE ….
COMIT

在所有 table 中,主键用于 SELECT 和更新(在下面的查询模式中)。

除了 mag_pj_art_sums 我使用的地方:

SELECT … FROM mag_pj_art_sums WHERE (id_artikal='$id_artikal' AND id_pj='$id_pj')

UPDATE mag_pj_art_sums SET … WHERE (id_artikal='$id_artikal' AND id_pj='$id_pj')

在这种情况下,这些行是否可能未被锁定?

因为,只有在这个 table 并发 SELECT - UPDATE 查询时我得到了不一致的值。查询执行无误,但值未按应有的方式更新。

不,它们没有被锁定。当你没有更改事务隔离级别时,它仍然是默认的REPEATABLE-READ
这意味着幻读是可能的。我在 .

中写了一个简短的解释

你应该做的是

START TRANSACTION;
SELECT … FROM table WHERE … FOR UPDATE;
UPDATE TABLE SET …. WHERE …;
COMMIT;

详细了解 SELECT ... FOR UPDATE here

INDEX(id_artikal), INDEX(id_pj)INDEX(id_artikal, id_pj) 不同 。添加后者;两个查询都会 运行 快很多。

是的,FOR UPDATE必需的。对于 START; SELECT...; UPDATE (same row)...; COMMIT 所有 个案例,必须 添加此 。您可能有没有注意到的错误!

我不会担心 tx_isolation