Dead Lock khi insert đồng thời.
Chào mọi người, em đang gặp phải vấn đề insert đồng thời nhiều bản ghi gây ra tình trạng deadlock.
Cụ thể, hệ thống của e cùng một lúc có thể có nhiều transaction đến table A để insert (nhiều bản ghi), gây ra tình trạng deadlock.
Em có khắc phục bằng cách cho retry 5 lần (em dùng Transaction trong Laravel). Tuy nhiên, đấy chỉ là cách chống chế và làm như vậy đôi khi còn ảnh hưởng đến hệ thống, vì insert quá chậm...
Sơ qua thì bảng đấy ngoài id primary key, thì có vài trường index và 1 trường unique.
Em có tìm hiểu qua thì do vấn đề GAP LOCK trong mysql (chưa hiểu hết, vì đọc docs khó hiểu quá), nó lock khoảng index trong column unique đó.
link tìm hiểu
Để chắc chắn thì e có làm 1 cái demo để tái hiện và hiểu hơn, tuy nhiên. Nó lại k bị deadlock như e mong đợi. Tạo bảng:
CREATE TABLE demo (
id int(10) NOT NULL auto_increment,
name varchar(191) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY uk_name (name)
) ENGINE=InnoDB
Insert data:
id 1 | name 2 |
---|---|
10 | ggg |
05 | jjj |
Tạo ra 2 transaction để test deadlock:
T1
SET autocommit = 0;
START TRANSACTION;
BEGIN;
INSERT INTO demo VALUES(null, 'ppp'); (1)
DO SLEEP(10);
INSERT INTO demo VALUES(null, 'hhh'); (2)
COMMIT;
T2
SET autocommit = 0;
START TRANSACTION;
BEGIN;
INSERT INTO demo VALUES(null, 'iii'); (3)
DO SLEEP(10);
INSERT INTO demo VALUES(null, 'mmm'); (4)
COMMIT;
Theo đúng như những gì em tìm hiểu thì lẽ ra phải xảy ra DeadLock, tuy nhiên, mọi thứ lại chạy bình thường. Cả 2 transaction đều insert thành công!
==> Mọi người ai có câu trả lời giải thích giúp em tại sao ví dụ trên lại không xảy ra deadlock? Có cách nào để hạn chế deadlock với bài toàn insert đồng thời không ạ? em đang định xử lý bỏ trường unique đi ạ.
3 CÂU TRẢ LỜI
Chào bạn,
Deadlock
xảy ra khi có 1 transaction A chiếm 1 vùng tài nguyên, và cơ sở dữ liệu đang lock
lại vùng tài nguyên đó cho transaction A.
Đồng thời tại thời điểm đó, có transaction B cũng truy xuất cùng vùng tài nguyên này. Để đảm bảo không bị inconsistency thì DB sẽ throw ra deadlock cho B.
Ở ví dụ bạn demo, thì không rơi vào trường hợp đó, nên hiển nhiên không bị throw ra lỗi rồi.
Bạn có thể tái hiện bằng cách insert cùng giá trị ID, hoặc cùng giá trị NAME ở 2 transaction khác nhau. (Tốt nhất transaction A nên có SLEEP time lớn hơn transaction B, để dễ tái hiện)
Chào bạn, do column name là unique bạn nhé, cơ chế gap lock và next-key của mysql là khi bạn thêm 1 dữ liệu vào column name 1 cách đồng thời, nếu database đang có dữ liệu là A và E, bạn insert đồng thời là B và D hoặc C và D (nằm khoảng giữa A và E) thì sẽ xảy ra deadlock Nguyên nhân là do cột name đã được indexed vì thế bên trong db sẽ có index, tại đó name được sắp xếp và bạn muốn chèn vào giữa thì database phải check xem liệu có bị trùng data không, nó sẽ lock khoảng giữa của những data có sẵn, nếu bạn insert vào data nằm giữa A và E ví dụ B và D thì query insert B sẽ nắm khoảng từ A đến B, còn query insert D sẽ nắm khoảng từ D đến E, vùng tranh chấp của 2 query là B đến D, khi query B lock đến chỗ D đang giữ và D lock đến chỗ B đang giữ thì sẽ xảy ra deadlock. Bạn có thể test nếu insert vào database là B và F (cả 2 data thêm chỉ cần 1 cái không nằm trong khoảng giữa) sẽ ko bị deadlock (tất nhiên mình đã thử :>)
Quan tâm vấn đề này!
@maitrungduc1410 khi mà đẩy vào queue thì job quá nhiều. worker run không kịp ấy ạ. vì k đơn giản là insert không thôi ạ. vì sau khi insert, lại có action đọc data ra để xử lý tiếp ạ.
(ví dụ: count down 10s để thực hiện transactions insert. sau 10s đó, thì lại có action khác đọc data insert để thực hiện update...)
@lxquan uk, khi xem lại bài toán về transaction thì mình thấy dùng queue chưa chắc đã tốt, và còn phụ thuộc vào bài toán như bạn nói nữa. hóng các cao nhân
@maitrungduc1410 follow a đã lâu, a cũng chưa gặp vấn đề này ạ
@lxquan mình chưa làm với transaction trong mysql bao giờ bạn ạ
@tungtv ID là auto increment. mình đâu cần thiết phải thêm vào ạ? nếu để cùng name thì nó báo lỗi unique thôi chứ kp deadlock. e đang mô phỏng lại bài toán của hệ thống em 1 cách đơn giản thông qua link bài viết e đính kèm ạ: http://thushw.blogspot.com/2010/11/mysql-deadlocks-with-concurrent-inserts.html Và thực tế, hệ thống của e insert với value bình thường chứ k đặc biệt như a nói vẫn deadlock đấy ạ. Còn e đang không tái hiện được qua ví dụ mô phỏng