sql >> Database >  >> RDS >> Mysql

INSERT ... SELECT, InnoDB en locking

Dat is correct. De rijen in de tabel waaruit wordt gelezen, zijn vergrendeld met een gedeelde vergrendeling (de SELECT is impliciet LOCK IN SHARE MODE ). Er is geen manier om dit te vermijden. Het is een beetje waar je het systeem om vraagt:kopieer alle rijen die aan een voorwaarde voldoen. De enige manier om ervoor te zorgen dat in feite alle rijen zijn die aan de voorwaarde voldoen en dat die lijst niet verandert tijdens of direct na het uitvoeren van dat statement, is door de rijen te vergrendelen.

Ter verduidelijking waarom u niet kunt INSERT met group_id = 2 :

Dit heeft te maken met het feit dat uw zoekopdracht specifiek WHERE group_id = 3 AND created < '2014-01-04' op KEY group_id_created (group_id, created) . Om alle rijen te doorzoeken die overeenkomen met group_id = 3 AND created < '2014-01-04' de index wordt achteruit doorlopen, te beginnen met de eerste rij die die voorwaarde overschrijdt de bovengrens, dat is (3, '2014-01-14') en doorgaan tot het vinden van een rij die niet overeenkomt met de voorwaarde, die sinds created geen ondergrens heeft, is de eerste rij waar group_id < 3 wat natuurlijk group_id = 2 . is .

Dat betekent dat de eerste rij gevonden met group_id = 2 is ook vergrendeld, wat de rij zal zijn met het maximum created waarde. Dit maakt het onmogelijk om INSERT in de "gap" tussen (2, MAX(created)) en (3, MIN(created)) (geen echte SQL natuurlijk, alleen pseudo-SQL), hoewel dit niet specifiek een "gap lock" is.




  1. Een injectie-aanval die slaagt met mysql_query, maar faalt met mysqli_query

  2. Wat is de beste manier om een ​​naar zichzelf verwijzende MySQL-tabel leeg te maken?

  3. Trigger-insert met een SELECT/JOIN

  4. Is het mogelijk om twee primaire sleutels in één tabel te maken?