2014-12-02 15 views
5

Son zamanlarda, uygulamanızda birçok kilitlenme hatası buldum.Mysql2 :: Hata: Kilit almaya çalışırken kilitlenme bulundu; işlemi yeniden başlatmayı deneyin: INSERT INTO

Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction: INSERT INTO `products`.... 

aşağıda kodu: kullanıcı oluşturuldu

sonra kullanıcıya bazı ürünleri katacak. Kilitlenme nedenini anlamıyorum.

class User < ActiveRecord::Base 
    after_create :add_products 
    has_many :products, :dependent => :destroy 

    def self.create_user 
     User.create!(.......) 
    end 

    def add_products 
     Product.add(self, "product_name", 10) 
    end 
    ..... 
end 

class Product < ActiveRecord::Base 
    belongs_to :user 

    def self.add(user, product_name, amount) 
     transaction do 
     product = user.products.find_by_product_name(product_name) 
     if product 
      product.increment :amount, amount 
      product.save! 
     else 
      product = self.create! user_id: user.id, 
            product_name: product_name, 
            amount: amount 
     end 
     end 
     product 
    end 
end 

Kök neden bulamadım, kimse bana biraz öneride bulunabilir mi? Şimdiden teşekkürler!!!

+0

, tekrar kendini kullandığınız Neden: mücevher README itibaren

.? Bunun yerine Ürünü kullanın. – Jyothu

+0

Haklısınız, daha önce değiştirdim. – pangpang

+0

aşağıdaki linki bakın, bu size yardımcı olacaktır http://stackoverflow.com/questions/2332768/how-to-avoid-mysql-deadlock-found-when-trying-to-get-lock-try- restarting-trans – Sush

cevap

9

Tahminimce InnoDB kullanıyorsunuz ve muhtemelen eşzamanlı ekleme yapıyorsunuz.

iz ve neden Checkout bu makaleleri

bir yolu aşağıda kodu gibi gerçekleştireceği deneme anlamak için

def add_products 
    retries = 0 

    begin 
     Product.add(self, "product_name", 10) 
    rescue ActiveRecord::StatementInvalid => ex 
     if ex.message =~ /Deadlock found when trying to get lock/ #ex not e!! 
      retries += 1 
      raise ex if retries > 3 ## max 3 retries 
      sleep 10 
      retry 
     else 
      raise ex 
     end 
    end 
end 

Veya MySQL kilitlenmelerini işlemek için transaction_query gibi bazı değerli taşlar vardır.

+0

Bir sorum var: kaydetme ve oluşturma yöntemleri bir işlemin içine sarılır, 'add' yöntemine işlem eklemek gerekli değildir? – pangpang

+0

İşlemlerin başarılı olduğundan veya iptal edildiğinden emin olmak için birden çok ekleme varsa, işlem yapmanız gerekir. Tamamen uygulamanıza bağlı, ancak sağladığınız kodu bakarak sadece gerekli olmadığını söyleyebilirim. – shiva

2

Bu beni çok fazla başağrıdan kurtardı: transaction_retry ruby ​​gem. Eklenti yönteminde ile

Retries database transaction on deadlock and transaction serialization errors. Supports MySQL, PostgreSQL, and SQLite.

+1

Üzgünüz, bu sitedeki yüksek bir itibara sahip olduğunuzu biliyorum, ancak ... bu cevap bir çeşit link-only ve spam değil. Eğer bu sorunun nasıl yardımcı olacağı konusunda biraz daha fazla ışık tutabilseydiniz, – iGbanam

+0

@Yasky'nin, soruyu sorduğu problemlerle tam olarak ilgilenen bir mücevher olduğu takdir edilecektir. Bir uyum ortamında bazen kilitlenmeler kaçınılmazdır, tek yol sadece işlemi yeniden dener. Bu mücevher bu iş otomatik olarak. – fguillen

İlgili konular