1. Two-Phase Locking là gì?

Two-Phase Locking (2PL – khóa hai pha) là một giao thức kiểm soát đồng thời (concurrency control protocol) trong database. Giao thức này quy định cách một transaction lấy và giải phóng lock nhằm đảm bảo các transaction chạy đồng thời tạo ra kết quả tương đương với một thứ tự thực thi tuần tự hợp lệ.

Khi nhiều transaction cùng đọc hoặc cập nhật dữ liệu, chúng có thể xung đột. Ví dụ, hai request cùng đọc số lượng sản phẩm còn lại là 1 rồi đều quyết định tạo đơn hàng. Nếu không có cơ chế phối hợp phù hợp, hệ thống có thể bán vượt số lượng tồn kho.

Database có thể sử dụng lock để điều phối những thao tác xung đột. Tuy nhiên, chỉ sử dụng lock là chưa đủ: cần có quy tắc về thời điểm được lấy lock và thời điểm được giải phóng lock. Đây chính là vai trò của Two-Phase Locking.

Điểm cốt lõi của 2PL là:

Một transaction có hai giai đoạn: giai đoạn lấy lock và giai đoạn giải phóng lock. Khi đã bắt đầu giải phóng lock, transaction không được lấy thêm lock mới.

2. Vì sao cần Two-Phase Locking?

Hãy xem xét hai transaction cùng thao tác trên hai tài khoản ngân hàng A và B.

  • Transaction T1 chuyển 100.000 đồng từ tài khoản A sang B.
  • Transaction T2 thực hiện một nghiệp vụ khác cần đọc và cập nhật các tài khoản này.

Nếu T1 cập nhật A rồi mới cập nhật B, trong khi T2 đọc A và B vào thời điểm T1 đang xử lý, T2 có thể nhìn thấy một trạng thái trung gian không phù hợp với nghiệp vụ.

Database cần ngăn các thao tác xung đột diễn ra theo thứ tự gây ra kết quả không nhất quán. Một cách là giữ các lock cần thiết trong suốt khoảng thời gian mà việc giải phóng chúng có thể khiến transaction khác quan sát hoặc ghi đè dữ liệu không an toàn.

3. Hai giai đoạn của Two-Phase Locking

Growing Phase – Giai đoạn tăng trưởng

Ví dụ:

T1:
    LOCK X trên tài khoản A
    LOCK X trên tài khoản B
    Đọc và cập nhật A
    Đọc và cập nhật B

Trong giai đoạn này, transaction chưa giải phóng lock nào. Số lượng lock mà nó đang giữ có thể tăng lên.

quang trọng: Growing phase  không có nghĩa transaction bắt buộc phải lấy lock ở mọi câu lệnh. Nó chỉ có nghĩa transaction vẫn được phép lấy thêm lock và chưa bắt đầu nhả lock.

Shrinking Phase – Giai đoạn thu hẹp

Giai đoạn thu hẹp bắt đầu khi transaction giải phóng lock đầu tiên.

Sau thời điểm đó, transaction có thể tiếp tục nhả những lock còn lại, nhưng không được lấy lock mới hoặc nâng cấp một lock theo cách cần cấp thêm quyền khóa.

Ví dụ:

T1:
    LOCK X trên A
    LOCK X trên B
    Cập nhật A
    Cập nhật B
    UNLOCK A       ← Bắt đầu Shrinking Phase
    UNLOCK B
    COMMIT

Sau khi nhả lock trên A, T1 không được quay lại lấy lock mới trên C.

Nếu T1 lấy thêm lock trên C sau thời điểm đó, giao thức 2PL đã bị vi phạm.

4. Shared Lock và Exclusive Lock trong 2PL

2PL quy định cách quản lý vòng đời lock, còn loại lock quyết định những thao tác nào có thể cùng tồn tại trên dữ liệu.

Shared Lock (S Lock)

Nhiều transaction có thể cùng giữ shared lock trên một dữ liệu vì các thao tác đọc không nhất thiết xung đột với nhau. Tuy nhiên, shared lock thường không tương thích với exclusive lock trên cùng phạm vi dữ liệu.

Ví dụ:

T1: lấy S lock trên account A
T2: lấy S lock trên account A

Hai transaction có thể cùng đọc A trong khi cả hai giữ shared lock.

Nếu T3 muốn lấy exclusive lock trên A để cập nhật, T3 thường phải chờ đến khi những lock không tương thích được giải phóng.

Exclusive Lock (X Lock)

Exclusive lock thường được sử dụng khi transaction cần cập nhật dữ liệu. Nó ngăn các transaction khác lấy lock không tương thích trên cùng phạm vi dữ liệu trong thời gian lock còn hiệu lực.

Ví dụ:

T1: lấy X lock trên account A
T2: yêu cầu X lock trên account A → phải chờ
T1: cập nhật A và kết thúc
T2: có thể lấy lock khi điều kiện cho phép

Cách database xử lý những request đang chờ còn phụ thuộc engine, loại lock và transaction đang hoạt động.

5. Two-Phase Locking có đảm bảo Serializability không?

Một trong những lý do quan trọng khiến 2PL được nghiên cứu và sử dụng là khả năng bảo đảm conflict serializability. Một lịch thực thi là conflict-serializable nếu có thể biến đổi nó thành một lịch thực thi tuần tự tương đương bằng cách hoán đổi những thao tác không xung đột. Trong 2PL, mỗi transaction có một lock point, tức thời điểm lấy lock cuối cùng. Nếu các transaction tuân thủ 2PL, có thể sắp xếp chúng theo thứ tự lock point để lập luận rằng lịch thực thi tương đương với một lịch tuần tự hợp lệ.

6. Deadlock trong Two-Phase Locking

2PL bảo đảm một tính chất quan trọng về lịch thực thi, nhưng không ngăn được deadlock. Deadlock xảy ra khi các transaction giữ lock mà transaction khác cần, đồng thời chờ nhau theo một chu trình.

Ví dụ:

T1 lấy X lock trên A
T2 lấy X lock trên B

T1 yêu cầu X lock trên B → chờ T2
T2 yêu cầu X lock trên A → chờ T1

T1 đang chờ T2 giải phóng B, còn T2 đang chờ T1 giải phóng A. Không transaction nào có thể tiếp tục nếu không có sự can thiệp từ database.

7. Tổng kết

Two-Phase Locking là giao thức quản lý vòng đời lock của transaction nhằm đảm bảo lịch thực thi có tính conflict-serializable.

Hai giai đoạn cần nhớ:

  • Growing Phase: được lấy lock mới, chưa được nhả lock.
  • Shrinking Phase: được nhả lock, không được lấy lock mới.

Các biến thể đáng chú ý gồm Basic 2PL, Strict 2PL, Rigorous 2PL và Conservative 2PL. Chúng khác nhau ở thời điểm giải phóng lock và cách xử lý nguy cơ đọc dữ liệu chưa commit hoặc deadlock.

 

Bài viết khác

Isolation Level

Isolation Level là gì? Các mức độ cô lập trong Database Trong một ứng dụng Backend, nhiều request có thể truy cập và thay đổi dữ liệu trong database cùng một thời điểm. Khi nhiều transaction chạy đồng thời, kết quả của một transaction có thể bị ảnh hưởng bởi những thao tác của transaction […]

Boundary Value Analysis(Phân tích giá trị biên)

1.Boundary Value Analysis là gì? Trong quá trình xây dựng và phát triển phần mềm, mặc dù đội ngũ lập trình viên luôn cố gắng viết mã nguồn thật chuẩn xác, nhưng thực tế kiểm thử từ nhiều thập kỷ qua đã đúc kết một quy luật kinh điển: Phần lớn các lỗi logic (logic […]

Saga Pattern – Quản lý Distributed Transactions

1. Saga Pattern là gì? Saga Pattern là một mẫu thiết kế dùng để quản lý một nghiệp vụ lớn trải qua nhiều service hoặc database độc lập. các nghiệp vụ được chia thành nhiều local transaction. mỗi transaction cập nhật nghiệp vụ của một service của nó. nếu một bước thất bại, hệ thống […]

Database Isolation Level – Các mức cô lập transaction

1. Isolation Level là gì? Isolation Level (mức cô lập giao dịch) là mức độ kiểm soát việc một transaction nhìn thấy những thay đổi của transaction khác khi nhiều transaction chạy đồng thời trên database. Isolation là chữ I trong ACID. Mục tiêu của nó là hạn chế những kết quả không nhất quán […]

Series 4 – React Rendering :Component Lifecycle, Rendering và Re-rendering Virtual DOM, Reconciliation và DOM

Series 4 – React Hooks – State   Bài 1 :Component Lifecycle, Rendering và Re-rendering – React cập nhật giao diện như thế nào? 1. Mở đầu Khi xây dựng ứng dụng React, một câu hỏi quan trọng là: điều gì xảy ra khi state thay đổi? Vì sao một component được hiển thị lần […]

locking & dead lock (Transaction)

1. Locking là gì? Locking (cơ chế khóa) là cơ chế database sử dụng để kiểm soát việc nhiều transaction cùng truy cập hoặc thay đổi dữ liệu, nhằm tránh những xung đột có thể làm sai lệch kết quả. Trong một ứng dụng có nhiều user, nhiều request có thể đồng thời thao tác […]

Leave a Reply

Your email address will not be published. Required fields are marked *