【问题标题】:InnoDB transaction principleInnoDB 事务原理
【发布时间】:2017-04-07 06:26:19
【问题描述】:

抱歉,这是个愚蠢的问题。 我的 MySQL InnoDB 应用程序有 70 多个表并使用事务。 除了一件事(表)之外,一切都运行良好:

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

在所有表中,PRIMARY 键用于 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 查询时,我才得到不一致的值。查询执行没有错误,但值没有按应有的方式更新。

【问题讨论】:

    标签: mysql transactions innodb


    【解决方案1】:

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

    你应该做的是

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

    阅读更多关于SELECT ... FOR UPDATEhere的信息。

    【讨论】:

    • 我的怀疑得到了证实。谢谢
    【解决方案2】:

    INDEX(id_artikal), INDEX(id_pj)INDEX(id_artikal, id_pj) 相同。添加后者;这两个查询都会运行得更快。

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

    我不会担心tx_isolation

    【讨论】:

    • 这是我 mysql 生活中打开的新水平 :-) 只需在 mysql.rjweb.org/doc.php/index_cookbook_mysql 阅读您的精彩文字,谢谢
    • 不客气,感谢您的好话。您不是唯一一个在那里找到有用信息的人。阅读该博客的人越多,该论坛需要回答的“简单”问题就越少。
    猜你喜欢
    • 2013-05-06
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    相关资源
    最近更新 更多