2013-03-14 15 views
11

Anlamakta yardıma ihtiyaç duyduğum çok karışık bir kilitlenme durumu buldum.
(2) sorgusu delete from myTable where id = NAME_CONST('p_id',10000) için kilit tutan:İşlem kilitleme işlemini başlatmaya çalıştığında kilitlenme sorunu zaten var

oluyor iki işlemler vardır. Bu tam anahtar değil bir aralık olmasına rağmen PRIMARY KEY tarafından bir kilit. Bu, lock_mode X locks rec but not gap diyorsa bana tam bir yazma kilidi gibi görünüyor.
(1), delete from myTable where id = NAME_CONST('p_id',10000) sorgusu için de aynı kilidi beklemektedir.
(2) aynı zamanda bu kilidi almayı deniyor ve MySQL bir kilitlenme tespit ediyor.

Neyi anlayamadığım, (2) kilidin zaten tutulduğu kadar kilidi alması gerektiğidir ve her durumda bir yazma kilidi (lock_mode X).

Aynı sorgu için olduğu gibi görünüyor. İşte

tablo tanımı

create myTable (
    id int unsigned not null, 
    value1 char(8) not null, 
    value2 int unsigned, 
    primary key (id, value1) 
); 

ve burada aynı kilit değil SHOW ENGINE INNODB STATUS\G

------------------------ 
LATEST DETECTED DEADLOCK 
------------------------ 
130313 14:46:28 
*** (1) TRANSACTION: 
TRANSACTION 75ACB8A3, ACTIVE 0 sec, process no 6110, OS thread id 139973945382656 starting index read 
mysql tables in use 1, locked 1 
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s) 
MySQL thread id 5154970, query id 5201313618 192.168.0.2 user updating 
delete from myTable where id = NAME_CONST('p_id',10000) 
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB8A3 lock_mode X waiting 
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 
0: len 4; hex 0005af3a; asc :;; 
1: len 8; hex 2020202020202020; asc ;; 
2: len 6; hex 000075acb890; asc u ;; 
3: len 7; hex ea0000020d011e; asc ;; 
4: len 4; hex 00000065; asc e;; 

*** (2) TRANSACTION: 
TRANSACTION 75ACB890, ACTIVE 0 sec, process no 6110, OS thread id 139973957895936 starting index read 
mysql tables in use 1, locked 1 
7 lock struct(s), hea 
p size 1248, 6 row lock(s), undo log entries 4 
MySQL thread id 5155967, query id 5201313625 192.168.0.1 user updating 
delete from myTable where id = NAME_CONST('p_id',10000) 
*** (2) HOLDS THE LOCK(S): 
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB890 lock_mode X locks rec but not gap 
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 
0: len 4; hex 0005af3a; asc :;; 
1: len 8; hex 2020202020202020; asc ;; 
2: len 6; hex 000075acb890; asc u ;; 
3: len 7; hex ea0000020d011e; asc ;; 
4: len 4; hex 00000065; asc e;; 

*** (2) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB890 lock_mode X waiting 
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0 
0: len 4; hex 0005af3a; asc :;; 
1: len 8; hex 2020202020202020; asc ;; 
2: len 6; hex 000075acb890; asc u ;; 
3: len 7; hex ea0000020d011e; asc ;; 
4: len 4; hex 00000065; asc e;; 

*** WE ROLL BACK TRANSACTION (1) 
+0

Hata oluşturmaya çalıştınız mı? Eğer "evet" senaryosunu gösterebilir miydin? – ravnur

+0

Bu silme işlemini "start transaction" ile olabildiğince hızlı yapmaya çalıştım; ... silmek; rollback; 'bash gibi hızlı iki iş parçacığı iş parçacığı mysql besleyebilir ama bir kez bir çıkmaz aldın. Bunun nasıl olabileceğine dair oldukça clueless. –

+0

Lütfen bu soruya göz atın (deadlock'u nasıl yakalayabileceğinizi açıklar): http://stackoverflow.com/questions/2143873/how-to-explain-the-deadlock-better. Ayrıca, http://dwachira.hubpages.com/hub/Process-Deadlock-Definition-Prevention-Detection-Recovery-ve-Avoidance adresinin de bulunduğu, çıkmazdan tespit ve kurtarma hakkında oldukça güzel bir makale var. Genel olarak, kilitlenme mimarlık ve tasarım meselesidir. Verileri güncelleyen süreçlerinizi gözden geçirmelisiniz. – ravnur

cevap

19

gelen bilgidir - Kilit işlem 1 sahiptir (endeks) üzerine olan kayıt sadece ve boşluk kilidi değil.

İşte bitenler:

  1. İşlem 2 rekor ('rec ancak boşluğu') önce (endeks) için kilit rekoru ancak boşluğu alır, bu bir rekor kilidi sadece sahiptir yani .
  2. İşlem 1, önce kayıtta ve boşlukta bir kilit (yani bir sonraki tuş kilidi) almayı dener, ancak işlem 2'nin bir kayıt kilidi olduğundan (ve böylece işlem 1 bekler) çalışamaz. İşlem 2, kayıt ve (yani bir sonraki tuş kilidi) önce bir kilit almak için çalışır ve işlem 1 zaten aynı kilit için beklediğinden ve önündeki sırada olduğu için yapamaz. Üste |
  3. Kilitlenme. kayıt kilidi elde etmenin belki süreci ve ardından boşluk kilidi genel anlamda (atomik değil -

Ben İşlem 2 hemen sonraki anahtar kilidi almaz neden tamamen emin değilim kelime).

Sorun şu ki, bir bileşik birincil anahtarınız (id, value1) var, ancak bir aralıktan siliyorsunuz (yalnızca kimlik belirtiyor) - bu boşluk boşlukları gerektirir. Özellikle, http://dev.mysql.com/doc/refman/5.0/en/innodb-record-level-locks.html Bkz:

Gap kilitleme benzersiz bir satır için aramak için benzersiz dizini kullanarak satırları kilitlemek ifadeleri için gerekli değildir. (Bu arama koşulu birden çok sütuna benzersiz dizin sadece bazı sütunları içerir davayı içermez; bu durumda, boşluk kilitleme meydana gelmez.) Belirttiğiniz böylece

kodunuzu değiştirebilir silerken tam birincil anahtar, örn. ve value1?

Diğer seçenekler: Bir kilitlenme, örneğin varken

  • silme yeniden dene Kodunuzdaki hatayı yakalayın ve bir kilitlenme nedeniyle meydana geldiyse tekrar deneyin. Bu yaklaşım genellikle daha kolaydır, özellikle eski uygulamalarda, bitmiş, ancak how to cope with deadlocks üzerinde MySQL sayfası tarafından önerilmektedir daha söyledi:

Hep bunun yüzünden kilitlenme başarısız olursa bir işlem yeniden düzenlememiz hazır olun. Kilitlenmeler tehlikeli değildir. Sadece tekrar dene.

  • silme deyimini vermeden önce bir tablo düzeyi kilit ile bütün tablo kilitleyin. Bu, performansı etkileyebilir ve bir 'balyoz' yaklaşımıdır.
+0

Bir IN ifadesinde veya bir birleştirmede tüm olası tuşların bir iç seçimini eklerseniz bu mümkün olabilir. Tek bir silme ifadesinin a) atomik olmaması ve b) diğer herhangi bir silmenin gerçekten tarafından kilitlenmesini gerektirmeyecek kadar hızlı olmaması bence garip geliyor. –

+0

Bu çıkmazları ne sıklıkla alıyorsunuz? Silme işleminden önce işlemde başka bir şey var mı? Silmeleri kaç eşzamanlı işliyor? Kodu gönderir misin? –

+0

Her gün birkaç kez, her zaman iki farklı makineden olur. Bu tabloyla ilgili silme işleminden önce hiçbir şey olmaz. Diğer şeyler diğer masalarda olur ama önemli olmamalı. Şifrelenmemiş kodu gönderemiyorum. –

İlgili konular