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

Series 7 — Web Quality – Engineering :Testing – Unit Testing, Integration Testing, Web Performance – Core Web Vitals, Code Splitting, Lazy Loading

Series 7 — Web Quality – Engineering Bài 3: Testing – Unit Testing, Integration Testing và End-to-End Testing trong ứng dụng web 1. Vì sao ứng dụng web cần Testing? Trong quá trình phát triển Frontend, chúng ta thường kiểm tra ứng dụng bằng cách chạy website trên trình duyệt, nhấn vào các nút, nhập […]

Series 7 — Web Quality – Engineering : Authentication & Authorization

Series 7 — Web Quality – Engineering Bài 1: Authentication & Authorization – Xác thực và phân quyền trong ứng dụng web 1. Mở đầu Khi xây dựng một ứng dụng web có chức năng đăng nhập, chúng ta thường nghĩ rằng chỉ cần tạo biểu mẫu nhập email, mật khẩu và kiểm tra thông […]

Series 6 – Next.js Advanced – Production: Next.js Build & Deployment

Series 6 – Next.js Advanced & Production Bài 5: Next.js Build & Deployment – Từ mã nguồn đến môi trường Production 1. Mở đầu Trong quá trình phát triển một ứng dụng web, việc chạy thành công trên máy tính cá nhân chưa có nghĩa là ứng dụng đã sẵn sàng để đưa đến người […]

Series 6 – Next.js Advanced – Production: Next.js Internationalized Routing Next.js Static Export

Series 6 – Next.js Advanced & Production   Bài 3: Next.js Internationalized Routing – Tổ chức URL cho website đa ngôn ngữ 1. Mở đầu Sau khi xây dựng cơ chế dịch nội dung và định dạng theo locale, ứng dụng cần một cách để người dùng truy cập đúng phiên bản ngôn ngữ. Ví […]

Series 6 – Next.js Advanced & Production: Metadata & SEO, Internationalization (i18n) & Localization (l10n)

Series 6 – Next.js Advanced & Production Bài 1: Metadata & SEO trong Next.js – Tối ưu thông tin và khả năng hiển thị trên công cụ tìm kiếm 1. Mở đầu Khi xây dựng một website, việc hoàn thiện giao diện và chức năng mới chỉ là một phần của quá trình phát triển. […]

Series 5 – Next.js Fundamentals: CSR, SSR, SSG, ISR và cách lựa chọn

Series 5 – Next.js Fundamentals   Bài 7 : CSR, SSR, SSG và ISR – Các chiến lược Rendering trong Next.js 1. Mở đầu Khi xây dựng một website bằng React, chúng ta thường tập trung vào việc tạo component, quản lý state và hiển thị giao diện trên trình duyệt. Tuy nhiên, khi ứng dụng […]

Leave a Reply

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