sql >> Database teknologi >  >> RDS >> Mysql

MySQL deadlock-fejl

Efter at have læst mere fandt jeg ud af, at da InnoDB bruger række-niveau-låsning, kan deadlocks opstå, når du blot indsætter eller opdaterer en enkelt række, da handlingerne ikke er atomare. Jeg løb:

SHOW ENGINE INNODB STATUS
 

for at finde information om det sidste dødvande. Jeg fandt:

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

Du kan se, at de to forespørgsler, der forårsager deadlocks, faktisk er de samme nøjagtige. Det viser, at der også er forskellige parametre for kolonnerne i WHERE-klausulen, så de faktiske rækker, der bliver låst, er forskellige, hvilket forekom lidt kontraintuitivt for mig - hvordan kunne operationer på forskellige sæt rækker forårsage en deadlock?

Svaret ser ud til at være, at dødvandet opstår fra forespørgselsmotorens låseindgange i indekseringsstrukturerne. Hvis du ser på outputtet ovenfor, kan du se, at en transaktion har en lås på en bestemt del af en bestemt side i country indeks og har brug for en lås på en del af det primære nøgleindeks, mens den anden transaktion i det væsentlige er det modsatte tilfælde.

En invariant i denne del af vores app, at kun én række nogensinde ville have mindre end 1000 klik, så jeg tror, ​​at ved at løse dette problem vil dødvandeproblemet blive minimeret, da der generelt ville være mindre låsning udført. MySQL-dokumentationen foreslår kodning af dine applikationer til altid at genudstede transaktioner i tilfælde af en tilbagerulning på grund af en dødvande, hvilket ville forhindre dette problem for at forårsage fejl på sider. Men hvis nogen har andre ideer til, hvordan man rent faktisk undgår disse dødvande, så skriv dem igen i kommentarerne!

REDIGER -

country indeks behøvede ikke at blive brugt af transaktionen, som for hver camp_id værdi var der kun en håndfuld (normalt kun 1) forskellige værdier af country , som hver kun svarede til én række. Jeg har tilføjet et indekstip til forespørgslen for at få den til at stoppe med at bruge dette indeks, og problemet er nu løst uden nogen præstationshit (sandsynligvis en lille gevinst).




  1. Kan jeg være sikker på Last Insert Id af Mysql?

  2. Identitetslignende kolonne, men baseret på Group By-kriterier

  3. mysqli_connect():(HY000/2003):Kan ikke oprette forbindelse til MySQL-server på 'domænenavn' (111)

  4. Hvordan viser jeg det første bogstav som stort?