我正在尝试使用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;
答案 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
,然后尽快使用commit
或rollback
,而不要使会话“挂起”以最小化这些问题。