2017-04-06 154 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

歡迎您,並感謝您的好話。你並不孤單尋找有用的信息。閱讀該博客的人越多,需要在此論壇上回答的「簡單」問題就越少。 –