MySQL: bir işlem satırı kilitler mi?


13

Daha önce MySQL işlemini kullanmayı denemedim, sadece bir şeyi açıklığa kavuşturmak istiyorum.

İki kullanıcı bir sorguyu tam zamanında yürütürse, MySQL bunu nasıl ele alır? örneğin kullanıcılar bir kaydı güncellemeye çalışıyor.

user1: güncelleme tablosu seti column = column - 4 burada column_id = 1;

user2: güncelleme tablosu kümesi column = column - 7 burada column_id = 1;

Şimdi işlemleri kullanırsam, MySQL ilk olarak hangi sorgunun yürütüleceğini seçecek ve ilk sorgu yapılana kadar ikinci kullanıcıyı kilitleyecek mi? Bu bir masa kilidi mi yoksa bir satır kilidi mi olacak?

Üçüncü bir kullanıcı bir select deyimi yayınlarsa ne olur? MySQL'in döndüreceği değer ne olacak?

PS bu Innodb üzerinde olacak.

Yanıtlar:


17

Bunun gibi tek bir ifade MyISAM veya InnoDB ile, bir işlemle veya autocommit = ON ile aynı şekilde çalışır. Sorguyu yapacak kadar engeller, böylece diğer bağlantıyı engeller. Tamamlandığında, diğer bağlantı devam eder. Her durumda, sütun yakında 11 azaltılır.

Üçüncü bir kullanıcı, 0 veya 4 veya 7 veya 11 oranında azaltılmış değeri görebilir. "Çok kesin zaman" gerçekten mümkün değildir, çünkü her ifadenin yürütülmesinin bir noktasında tek dişli bir kilit kontrol edilir / ayarlanır / . Yani onlar, olup edecektir Çok hızlı onu göremiyorum, serileştirilebilir.

InnoDB tabloları değil, yalnızca satırları kilitler. (Tamam, DDL deyimi daha kalın kilitler yapar.)

Daha ilginç olan şey, iki şeyi değiştiren veya fark edilir bir zaman alan bir işlemdir:

Niyet Olgu: Tek ürün ancak zaman alıyor:

BEGIN;
SELECT something;
think about it for a while
UPDATE that something;
COMMIT;

Seçimin şu şekilde yazılması gerekir:

SELECT something  FOR UPDATE;

Bu, diğer satırlara "Satırı güncellemeyi planlıyorum; lütfen bana bulaşma" der. (Bu örneği gündeme getiriyorum, çünkü pek çok yeni kişi bu inceliği kaçırıyor.)

Kilitlenme durumu: 2 şeyle uğraşmak:

BEGIN;    -- in one connection
UPDATE thing_1;
UPDATE thing_2;
COMMIT;

BEGIN;    -- in another connection, at the "exact same time"
UPDATE thing_2;
UPDATE thing_1;
COMMIT;

Bu bir kilitlenmenin klasik örneğidir - her biri bir şey alır ve sonra başka bir şeye ulaşır. Açıkçası işe yaramaz. Bir işlem öldürüldü; diğeri tamamlanır. Bu nedenle, hataları kontrol etmeniz gerekir , böylece keşfedebilirsiniz.

Bir kilitlenmeye karşı normal tepki, başarısız olan tüm işlemi yeniden oynatmaktır. O zamana kadar, diğer bağlantı karışmayacak ve sorunsuz bir şekilde ilerlemeli. (Tamam, ancak başka bir bağlantı başka bir kilitlenme oluşturabilir.)

Gecikme Durumu: İki bağlantı aynı sırayla birden çok şeyi tutarsa, diğeri bitene kadar gecikebilir. Bunu "sonsuza kadar beklemekten" kaçınmak için varsayılan 50 saniyedir innodb_lock_wait_timeout. Basit UPDATEsçiftiniz aslında bu duruma bir örnektir. Biri hemen bitecek; diğeri ilk bitene kadar durdu.

Bir Kilitlenmenin (bazı durumlarda) dokunduğunuz şeyleri tutarlı bir şekilde sipariş ederek nasıl bir Gecikmeye dönüştürülebileceğini unutmayın.

autocommit = 1: Bu ayar ile ve çağrı yapmadan BEGIN, her ifade etkili bir şekilde:

BEGIN;
your statement
COMMIT;

autocommit = 0: Bu, gerçekleşmesini beklerken sorun. Bir yazma sorgusu gerçekleştirdiğinizde, a BEGINdolaylı olarak oluşturulur. Ancak, nihayetinde vermek sizin sorumluluğunuzdadır COMMIT. Bunu yapmazsanız, sisteminizin neden asıldığını merak edeceksiniz. (Bir başka yaygın yeni hata.) Tavsiyem: "Asla kullanma =0".

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.