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.







Khoá học lập trình game con rắn cho trẻ em




