Mysql
 sql >> база данни >  >> RDS >> Mysql

Грешка в застой в MySQL

След като направих още малко четене, установих, че тъй като InnoDB използва заключване на ниво ред, могат да възникнат блокирания при просто вмъкване или актуализиране на един ред, тъй като действията не са атомарни. Избягах:

SHOW ENGINE INNODB STATUS

за да намерите информация за последната безизходица. Намерих:

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

Можете да видите, че двете заявки, които причиняват блокиране, всъщност са същите. Показва, че има и различни параметри за колоните в клаузата WHERE, така че действителните редове, които се заключват, са различни, което ми се стори малко противоинтуитивно - как може операциите върху различни набори от редове да доведат до безизходица?

Отговорът изглежда е, че блокирането възниква от заключването на записите на механизма за заявки в индексиращите структури. Ако погледнете изхода по-горе, можете да видите, че една транзакция има заключване на определена част от определена страница в country индекс и се нуждае от заключване на част от индекса на първичния ключ, докато другата транзакция е по същество обратният случай.

Инвариант в тази част на нашето приложение, че само един ред някога ще има по-малко от 1000 щраквания, така че вярвам, че чрез коригиране на този проблем проблемът със заключване ще бъде сведен до минимум, тъй като като цяло ще има по-малко заключване. Документацията на MySQL предлага кодиране на вашите приложения, така че винаги да се издават повторно транзакции в случай на връщане назад поради блокиране, което би предотвратило този проблем за причиняване на грешки в страниците. Въпреки това, ако някой има някакви други идеи за това как всъщност да избегнете тези безизходица, отново, моля, публикувайте ги в коментарите!

РЕДАКТИРАНЕ -

country не е необходимо индексът да се използва от транзакцията, както за всеки camp_id стойност имаше само няколко (обикновено само 1) различни стойности на country , всеки от които отговаряше само на един ред. Добавих подсказка за индекс към заявката, за да я накарам да спре да използва този индекс и проблемът вече е отстранен без никакво намаление на производителността (вероятно малка печалба).




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Неуспех на сериализацията:Открита застой при опит за заключване

  2. Защо mysqli_real_escape_string има обект на връзка като първи параметър

  3. Можем ли да използваме PHP функция strtotime в Mysql Query

  4. Mysql сума от записи по месеци за последните 12 месеца

  5. Как да изтрия редове от таблица за присъединяване (ManyToMany) в Doctrine?