【问题标题】:why is insert on table locked?为什么插入表被锁定?
【发布时间】:2019-03-15 16:34:19
【问题描述】:

我正在 mysql 上尝试一些事务级别。

我有会话 S1 和会话 S2。 S1 正在使用默认隔离 lavel 可重复读取。对于 S2,我设置了 Isolation Level Serializable。

这里是情景:

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 现在被屏蔽了?

这是表模式:

    -- 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;

【问题讨论】:

    标签: mysql isolation-level


    【解决方案1】:

    您有一个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,并且不要让会话“挂起”以尽量减少这些问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 2014-05-15
      • 2014-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多