Deadlock trong sql là gì

Nội dung chính

Show

  • Deadlock trong java?
  • Cách tránh Deadlock
  • Tóm lược
  • 1. Sử dụng câu lệnh T-SQL SP_LOCK
  • 2. Sử dụng câu lệnh truy vấn với sys.sysprocesses
  • 3. Sử dụng trình DVM (Dynamic Management Views)
  • 4. Sử dụng sys.dm_tran_locks
  • 5. Bật cờ theo dõi bắt buộc để ghi thông tin liên quan đến DeadLock trong Tracefile
  • 6. Đếm tổng số lần xảy ra DeadLock
  • 7. Sử dụng Extended Events và đoạn script bên dưới để tạo một Extended Event cho theo dõi DeadLock
  • 8. Sử dụng SQL Server Profiler
  • Video liên quan

Java hỗ trợ lập trình đa luồng (multithreading), khi có nhiều thread chạy đồng thời trong một chương trình, trong một số trường hợp nhất định hoặc do sai xót dẫn đến các thread rơi vào tình trạng chờ mãi mãi. Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu về Deadlock là gì? làm sao để tránh Deadlock qua các ví dụ trong java.

Deadlock trong java?

DeadLock trong java là một trạng thái trong đó 2 hoặc nhiều thread rơi vào tình trạng chờ đợi lẫn nhau vì mỗi thread giữ một tài nguyên và chờ đợi tài nguyên từ thread khác. Ví dụ ThreadA giữ tài nguyên A và chời đợi tài nguyên B đang bị ThreadB nắm giữ, trong lúc đó ThreadB lại chờ đợi ThreadA trả tài nguyên A để sử dụng dẫn đến ThreadA và ThreadB chờ đợi lẫn nhau mãi mãi.

Ví dụ

class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println(“Thread 1: Holding lock 1…”);
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println(“Thread 1: Waiting for lock 2…”);
synchronized (Lock2) {
System.out.println(“Thread 1: Holding lock 1 & 2…”);
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println(“Thread 2: Holding lock 2…”);
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println(“Thread 2: Waiting for lock 1…”);
synchronized (Lock1) {
System.out.println(“Thread 2: Holding lock 1 & 2…”);
}
}
}
}
}

Chúng ta có 2 thread ThreadDemo1 và ThreadDemo2, hai tài nguyên Lock1 và Lock2.

  • Khi ThreadDemo1 start() nó bắt đầu chiếm giữ Lock1.
  • ThreadDemo1 ngủ 10millis, khoảng thời gian đó ThreadDemo2 start() và chiếm giữ lock2.
  • Sau khi ThreadDemo1 và ThreadDemo2 hoạt động, ThreadDemo1 giữ Lock1 và chờ ThreadDemo2 trả lại Lock2 để sử dụng.
  • ThreadDemo2 giữ Lock2 và đợi ThreadDemo1 trả lại Lock1

Dẫn đến ThreadDemo1 và ThreadDemo2 chờ lẫn nhau gây ra hiện tượng Deadlock.

Để giải quyết Deadlock ở ví dụ trên, mình sẽ sử dụng join() method cho T1 để các các thread bên dưới phải chờ cho đến khi T1 thực thi xong thì bắt đầu khởi chạy.

class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) throws InterruptedException {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
// waiting for T1 finished
T1.join();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
System.out.println(“Thread 1: Holding lock 1…”);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println(“Thread 1: Waiting for lock 2…”);
synchronized (Lock2) {
System.out.println(“Thread 1: Holding lock 1 & 2…”);
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
System.out.println(“Thread 2: Holding lock 2…”);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println(“Thread 2: Waiting for lock 1…”);
System.out.println(“Thread 2: Holding lock 1 & 2…”);
}
}
}

Output:

Thread 1: Holding lock 1…Thread 1: Waiting for lock 2…Thread 1: Holding lock 1 & 2…Thread 2: Holding lock 2…Thread 2: Waiting for lock 1…

Thread 2: Holding lock 1 & 2…

Cách tránh Deadlock

Để tránh Deadlock chúng ta phải biết chính xác các khả năng có thể xảy ra Deadlock, việc này khá là khó khăn, mình chém gió vậy thôi chứ gặp Deadlock cũng đắm đuối. Thế nhưng mà chúng ta cứ cố gắng thôi. Dưới đây là một số điểm chúng ta có thể xem qua để giảm bớt khả năng Deadlock xảy ra

  • Cách đơn giản đã được mình nêu trên là sử dụng join() method để các thread khác chờ cho đến khi một thread hoàn thành mới bắt đầu khởi chạy. Lưu ý sử dụng khi nào cần thôi nhé, chứ bất đồng bộ mà cứ chờ nhau thì làm single thread cho rồi!
  • Tránh khoá các tài nguyên không cần thiết để hạn chế Deadlock, không phải cứ cái nào cũng khoá cho 1 thread, chúng ta phải xem xét kỹ xem tài nguyên đó có được sử dụng cho nhiều luồng và giá trị của nó có ảnh hưởng đến kết quả tính toán của các luồng hay không rồi hẳn khoá nhé.
  • Tránh việc khoá lồng nhau, khi một tài nguyên đã được giao cho 1 thread rồi thì đừng cố giao cho các thread khác. Đây là trường hợp phổ biến nhất dẫn đến DeadLock, như ví dụ trên Lock1 và Lock2 mình đã giao cho cả 2 thread chạy song song mà không có các biện pháp cụ thể khác.

Tóm lược

DeadLock là một vấn đề khó trong lập trình đa luồng, ,mà chúng ta cần thực hành nhiều với đa luồng mới biết cách sử lý trong các tình huống cụ thể. Deadlock cũng có thể xảy ra các các truy vấn cơ sở dữ liệu etc, nó có thể xảy ra bất cứ khi nào một tài nguyên được nhiều luồng xử lý tranh giành. 

Deadlock có thể phá huỷ luồng chạy bình thường của chương trình tại thời điểm runtime, ảnh hưởng nghiêm trọnåg đến trải nghiệm người dùng.  

Nguồn tham khảo

https://www.geeksforgeeks.org/introduction-of-deadlock-in-operating-system/

https://www.tutorialspoint.com/java/java_thread_deadlock.htm

Would love your thoughts, please comment.x

DeadLock là hiện tượng tranh chấp tài nguyên giữa hai hay nhiều lệnh trong đó lệnh này giữ tài nguyên mà lệnh kia cần dẫn tới việc không lệnh nào có thể kết thúc để giải phóng tài nguyên.
Ví dụ:

  • Giao dịch T1 giữ được tài nguyên R1, nhưng cần tài nguyên R2 để kết thúc và giải phóng R1
  • R2 lại đang bị T2 giữ và T2 cần R1 để kết thúc và sau đó giải phóng R2.
  • Trong trường hợp này cả T1 và T2 không thể kết thúc. Trường hợp này trong SQL Server sẽ phải chọn kill một trong hai giao dịch.

Xem thêm bài https://timoday.edu.vn/phan-tich-deadlock-trong-co-so-du-lieu-va-cach-phong-tranh/
Trong bài này chúng tôi giới thiệu các cách khác nhau để tìm ra các lỗi DeadLock trong truy vấn cơ sở dữ liệu của SQL Server

1. Sử dụng câu lệnh T-SQL SP_LOCK

Thực thi câu lệnh T-SQL SP_LOCK của SQL Server, bạn có thể tìm các status là WAIT cho các phiên đang bị chặn.

USE master;
GO
EXEC sp_lock;
GO


Xem thêm tại đây

2. Sử dụng câu lệnh truy vấn với sys.sysprocesses

SELECT * FROM sys.sysprocesses
WHERE blocked > 0

3. Sử dụng trình DVM (Dynamic Management Views)

SELECT
der.blocking_session_id AS BlockingSessionID
,dest.text AS BlockingStatement
FROM sys.dm_exec_connections AS sdec
INNER JOIN sys.dm_exec_requests AS der
ON sdec.session_id = der.blocking_session_id
INNER JOIN sys.dm_os_waiting_tasks AS dowt
ON der.session_id = dowt.session_id
CROSS APPLY sys.dm_exec_sql_text(sdec.most_recent_sql_handle) AS dest

4. Sử dụng sys.dm_tran_locks

SELECT
request_session_id AS SPID
,DB_NAME(resource_database_id) AS DatabaseName
,resource_type AS LockedResource
,request_mode AS LockType
FROM sys.dm_tran_locks

5. Bật cờ theo dõi bắt buộc để ghi thông tin liên quan đến DeadLock trong Tracefile

DBCC TRACEON (1204, -1)
DBCC TRACEON (1222, -1)

6. Đếm tổng số lần xảy ra DeadLock

SELECT cntr_value AS TotalNumberOfDeadLocks
FROM sys.dm_os_performance_counters
WHERE counter_name = ‘Number of Deadlocks/sec’
AND instance_name = ‘_Total’

7. Sử dụng Extended Events và đoạn script bên dưới để tạo một Extended Event cho theo dõi DeadLock

CREATE EVENT SESSION [Deadlock_Monitor] ON SERVER
ADD EVENT sqlos.scheduler_monitor_deadlock_ring_buffer_recorded,
ADD EVENT sqlserver.lock_deadlock,
ADD EVENT sqlserver.lock_deadlock_chain,
ADD EVENT sqlserver.xml_deadlock_report
ADD TARGET package0.event_file(SET filename=N’C:\Temp\Deadlock_Monitor.xel’)
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)
GO

Bạn có thể sử dụng SSMS để tạo Extended Events cho DeadLock, và có thể theo dõi trạng thái trực tiếp của server.

8. Sử dụng SQL Server Profiler

SQL Server Profiler có ba kiểu sự kiện khác nhau để bắt DeadLock:

  • Deadlock graph
  • Lock: Deadlock
  • Lock: Deadlock Chain
    Bước 1: Chọn Template là Blank

    Bước 2: Chọn kiểu Events là Locks để bắt các sự kiện liên quan đến DeadLock