sql >> Database >  >> RDS >> Mysql

MySQL-deadlock-fout

Nadat ik wat meer had gelezen, ontdekte ik dat, aangezien InnoDB vergrendeling op rijniveau gebruikt, er deadlocks kunnen optreden bij het invoegen of bijwerken van een enkele rij, omdat de acties niet atomair zijn. Ik rende:

SHOW ENGINE INNODB STATUS

om informatie te vinden over de laatste impasse. Ik heb gevonden:

------------------------
LATEST DETECTED DEADLOCK
------------------------
140106 17:22:41
*** (1) TRANSACTION:
TRANSACTION 63EB5222A, ACTIVE 0 sec starting index read
mysql tables in use 3, locked 3
LOCK WAIT 9 lock struct(s), heap size 3112, 6 row lock(s), undo log entries 2
MySQL thread id 4304350, OS thread handle 0x7fd3b74d3700, query id 173460207 192.168.0.2 sharecash Updating
UPDATE `click_rollups` SET `clicks` = `clicks` + 1, `last_updated` = '1389046961' WHERE `camp_id` = '27739' AND `country` = 'US' AND `clicks` < '1000' AND `time_created` = '1389046866'
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 186 page no 407 n bits 1272 index `country` of table `sharecash`.`click_rollups` trx id 63EB5222A lock_mode X waiting
*** (2) TRANSACTION:
TRANSACTION 63EB52225, ACTIVE 0 sec fetching rows
mysql tables in use 3, locked 3
177 lock struct(s), heap size 31160, 17786 row lock(s), undo log entries 2
MySQL thread id 4304349, OS thread handle 0x7fd6961c8700, query id 173460194 192.168.0.1 sharecash Updating
UPDATE `click_rollups` SET `clicks` = `clicks` + 1, `last_updated` = '1389046961' WHERE `camp_id` = '30949' AND `country` = 'US' AND `clicks` < '1000' AND `time_created` = '1388964767'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 186 page no 407 n bits 1272 index `country` of table `sharecash`.`click_rollups` trx id 63EB52225 lock_mode X
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 186 page no 512 n bits 384 index `PRIMARY` of table `sharecash`.`click_rollups` trx id 63EB52225 lock_mode X locks rec but not gap waiting
*** WE ROLL BACK TRANSACTION (1)

U kunt zien dat de twee query's die de impasses veroorzaken, in feite exact dezelfde zijn. Het laat zien dat er ook verschillende parameters zijn voor de kolommen in de WHERE-component, dus de daadwerkelijke rijen die worden vergrendeld, zijn anders, wat een beetje contra-intuïtief leek - hoe kunnen bewerkingen op verschillende sets rijen een impasse veroorzaken?

Het antwoord lijkt te zijn dat de impasse voortkomt uit de vergrendelingsitems van de query-engine in de indexeringsstructuren. Als je naar de output hierboven kijkt, kun je zien dat één transactie een slot heeft op een bepaald deel van een bepaalde pagina in het country index en heeft een slot nodig op een deel van de primaire sleutelindex, terwijl de andere transactie in wezen het tegenovergestelde geval is.

Een invariant in dit deel van onze app dat slechts één rij ooit minder dan 1000 klikken zou hebben, dus ik geloof dat door dat probleem op te lossen het probleem van de impasse wordt geminimaliseerd, omdat er over het algemeen minder vergrendeling wordt gedaan. De MySQL-documentatie stelt voor om uw applicaties te coderen om transacties altijd opnieuw uit te geven in het geval van een rollback vanwege een deadlock, waardoor dit probleem zou voorkomen dat pagina's fouten veroorzaken. Als iemand echter nog andere ideeën heeft om deze impasses te vermijden, plaats ze dan alsjeblieft in de reacties!

BEWERKEN -

Het country index hoefde niet te worden gebruikt door de transactie, zoals voor elke camp_id waarde er waren slechts een handvol (meestal slechts 1) verschillende waarden van country , die elk slechts overeenkwamen met één rij. Ik heb een indexhint aan de zoekopdracht toegevoegd om het gebruik van deze index te stoppen, en het probleem is nu opgelost zonder prestatieverlies (waarschijnlijk een kleine winst).




  1. Emoji invoegen in MYSQL 5.5 en hoger met Django ORM

  2. Hoe te herschrijven IS ONDERSCHEIDEN VAN en IS NIET ONDERSCHEIDEN VAN?

  3. SQL-query om product_type te controleren in WooCommerce

  4. Verschil tussen NOW(), SYSDATE() &CURRENT_DATE() in MySQL