TopDev AI Robot TopDev
#Backend & Microservices#Cơ sở dữ liệu & Tối ưu

Deadlock trong Database: Cách phân tích pg_stat_activity và phương pháp phòng tránh

Thu Trang (Backend Engineer)
📖 2 phút đọc 💬 1 phản hồi
⚡ Tóm tắt 30 giây bởi TopDev AI
AI Overview

Bản chất của Deadlock Bế tắc trong Cơ sở dữ liệu Lỗi Deadlock xảy ra khi hai hay nhiều giao dịch transactions cùng khóa các tài nguyên mà đối phương đang cần, tạo thành một vòng lặp phụ thuộc vô tận:…

☰ Mục lục bài viết (4 phần) Mở / Đóng mục lục

Bản chất của Deadlock (Bế tắc) trong Cơ sở dữ liệu#

Lỗi Deadlock xảy ra khi hai hay nhiều giao dịch (transactions) cùng khóa các tài nguyên mà đối phương đang cần, tạo thành một vòng lặp phụ thuộc vô tận:

  • Transaction A đang giữ khóa dòng 1 và muốn sửa dòng 2.
  • Transaction B đang giữ khóa dòng 2 và muốn sửa dòng 1.
  • Cả hai cùng đứng chờ nhau cho tới khi cơ chế phát hiện Deadlock của PostgreSQL can thiệp và hủy bỏ (abort) một trong hai giao dịch với mã lỗi 40P01.

Câu truy vấn truy tìm các tiến trình đang bị khóa trong PostgreSQL#

SQL
SELECT
    blocked_locks.pid     AS blocked_pid,
    blocked_activity.usename  AS blocked_user,
    blocking_locks.pid    AS blocking_pid,
    blocking_activity.usename AS blocking_user,
    blocked_activity.query    AS blocked_statement,
    blocking_activity.query   AS blocking_statement
FROM  pg_catalog.pg_locks         blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks         blocking_locks 
    ON blocking_locks.locktype = blocked_locks.locktype
    AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
    AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
    AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
    AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
    AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
    AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
    AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
    AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
    AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
    AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;

3 nguyên tắc vàng để loại bỏ 99% lỗi Deadlock#

  1. Luôn khóa các bảng/dòng theo một thứ tự duy nhất (Consistent Order): Nếu cập nhật nhiều bản ghi, hãy sắp xếp danh sách ID tăng dần trước khi thực hiện câu lệnh UPDATE hoặc SELECT FOR UPDATE.
  2. Giữ thời gian thực thi Transaction càng ngắn càng tốt: Tuyệt đối không gọi API bên thứ ba (gửi email, gọi cổng thanh toán) bên trong một transaction của database!
  3. Sử dụng mức cô lập (Isolation Level) phù hợp: Mặc định Read Committed đã đủ an toàn cho 90% nghiệp vụ thông thường.

Góc thảo luận#

Anh em đã từng phải debug một vụ Deadlock phức tạp liên quan đến Foreign Key cascade bao giờ chưa?


Xem thêm nội dung liên quan:

Chia sẻ thảo luận này:

Thảo luận

1 phản hồi

Ý kiến từ cộng đồng kỹ sư TopDev
💬

Tham gia thảo luận

Cộng đồng mở · Đăng nhập 1-chạm qua Google
  1. Hoàng Nam (Tech Lead)
    #1

    Nguyên tắc số 1: Luôn sort danh sách ID trước khi update là giải pháp rẻ tiền mà trị dứt điểm 90% các ca deadlock khi cập nhật số dư ví hoặc trừ kho nhiều sản phẩm một lúc!

Bài liên quan trong #Backend & Microservices

1
TopDev AI Companion
AI
✓ Đã sao chép link