2017-04-06 119 views
0

对不起,如果这是愚蠢的问题。 我有70多个表和使用事务的MySQL InnoDB应用程序。 一切工作正常,除了一件事(表):InnoDB交易原理

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 

中的所有表的主键用于SELECT和UPDATE(以下查询模式)。

除非我用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') 

难道那些行没有被锁定在这种情况下?

因为只有在这个表中,当有并发的SELECT - UPDATE查询时,我得到了不一致的值。查询执行时没有错误,但值不会更新,因为它们应该如此。

回答

2

不,它们没有锁定。如果您没有更改事务隔离级别,它仍然是默认的REPEATABLE-READ
这意味着幻影读取是可能的。我在this answer中写了一个简短的解释。

你应该做的是

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

了解更多关于SELECT ... FOR UPDATEhere

+0

我的疑惑得到证实。谢谢 – MiTja

1

INDEX(id_artikal), INDEX(id_pj)一样INDEX(id_artikal, id_pj)。加入后者;两个查询都会运行得更快。

是的,FOR UPDATE要求。这必须被添加为所有案件的START; SELECT...; UPDATE (same row)...; COMMIT。你可能有错误,你没有注意到!

我不用担心tx_isolation

+0

而这在我的mysql生活中开启了新的层次:-)请在http://mysql.rjweb.org/doc.php/index_cookbook_mysql阅读您的精彩文本谢谢 – MiTja

+0

欢迎您,并感谢您的好话。你并不孤单寻找有用的信息。阅读该博客的人越多,需要在此论坛上回答的“简单”问题就越少。 –