为什么将插入表格锁定?

时间:2019-03-14 18:29:37

标签: mysql isolation-level

我正在尝试使用mysql上的事务级别的东西。

我有会议S1和会议S2。 S1正在使用默认隔离堆可重复读取。对于S2,我将隔离级别设置为可序列化。

这是szenario:

S1:

set innodb_lock_wait_timeout = 5;
start transaction;

S2:

set session transaction isolation level serializable;
start transaction;
select count(*) from produkt;

S1:

select count(*) from produkt;
update kategorie set bezeichnung = 'Smartphone' where kategorieid = 1;

S2:

 insert into produkt(produktid, bezeichnung, kategorieid_fk) values (201, 'iPhone 8z', 1);

有人可以解释为什么现在阻止了S2中的insert into produkt吗?

这是Tableschema:

    -- Exportiere Datenbank Struktur für transaktiondb
    CREATE DATABASE IF NOT EXISTS `transaktiondb`;
    USE `transaktiondb`;


    -- Exportiere Struktur von Tabelle transaktiondb.kategorie
    CREATE TABLE IF NOT EXISTS `kategorie` (
      `KategorieID` int(11) NOT NULL AUTO_INCREMENT,
      `Bezeichnung` varchar(255) NOT NULL,
      PRIMARY KEY (`KategorieID`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    -- Exportiere Struktur von Tabelle transaktiondb.produkt
    CREATE TABLE IF NOT EXISTS `produkt` (
      `ProduktID` int(11) NOT NULL AUTO_INCREMENT,
      `Bezeichnung` varchar(255) NOT NULL,
      `KategorieID_FK` int(11) NOT NULL,
      PRIMARY KEY (`ProduktID`),
      KEY `fk_Produkt_Kategorie_idx` (`KategorieID_FK`),
      CONSTRAINT `fk_Produkt_Kategorie` FOREIGN KEY (`KategorieID_FK`) REFERENCES `kategorie` (`KategorieID`) ON DELETE NO ACTION ON UPDATE NO ACTION
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1 个答案:

答案 0 :(得分:0)

您有一个deadlock,MySQL将其描述为:

  

不同事务无法进行的情况,因为每个事务都持有对方需要的锁。因为这两个事务都在等待资源变得可用,所以两个都不会释放它持有的锁。

靠近How to Minimize and Handle Deadlocks的内容是:

  

InnoDB使用自动行级锁定。即使在仅插入或删除单行的事务中,也可能会遇到死锁。这是因为这些操作并不是真正的“原子”操作;他们会自动对插入或删除的行的(可能是多个)索引记录设置锁定。

关于innodb_lock_wait_timeout的性质,文档描述它仅适用于禁用inno_db_detect的情况,这不是默认配置:

  

启用innodb_deadlock_detect(默认设置)时,锁定等待超时值不适用于死锁,因为InnoDB立即检测到死锁并回滚死锁的事务之一。禁用innodb_deadlock_detect时,当发生死锁时,InnoDB依赖于innodb_lock_wait_timeout进行事务回滚。请参见第14.7.5.2节“死锁检测和回滚”。

此外,作为一个一般性提示,您经常会想使用start transaction,然后尽快使用commitrollback,而不要使会话“挂起”以最小化这些问题。