Asked Jul 22nd, 2021 2:46 p.m. 119 0 2
  • 119 0 2
+5

Dead Lock khi insert đồng thời.

Share
  • 119 0 2

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 ạ.

Avatar Mai Anh Hứa @Mai_Anh_Hua
Jul 23rd, 2021 3:04 a.m.

Quan tâm vấn đề này!

0
| Reply
Share
Avatar Quan @lxquan
Jul 23rd, 2021 3:50 a.m.

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

0
| Reply
Share
Avatar Mai Trung Đức @maitrungduc1410
Jul 23rd, 2021 3:53 a.m.

@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 😀

0
| Reply
Share
Avatar Quan @lxquan
Jul 23rd, 2021 3:55 a.m.

@maitrungduc1410 follow a đã lâu, a cũng chưa gặp vấn đề này ạ 😄

0
| Reply
Share
Avatar Mai Trung Đức @maitrungduc1410
Jul 23rd, 2021 4:02 a.m.

@lxquan mình chưa làm với transaction trong mysql bao giờ bạn ạ 😄

0
| Reply
Share
Avatar Quan @lxquan
Jul 30th, 2021 1:39 a.m.

@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 😦

0
| Reply
Share

2 ANSWERS


Answered Jul 23rd, 2021 2:53 p.m.
0

E xin phép chấm hóng nha bác 😄

Share
Answered Jul 29th, 2021 11:19 a.m.
0

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)

Share
Viblo
Let's register a Viblo Account to get more interesting posts.