Cơ Chế Khóa Trong MySQL: Khóa Bảng, Khóa Trang Và Khóa Hàng

Khóa (lock) là cơ chế kiểm soát truy cập đồng thời vào tài nguyên chung nhằm đảm bảo tính toàn vẹn và nhất quán dữ liệu khi nhiều luồng hoặc giao dịch thao tác song song. Trong MySQL, hành vi khóa phụ thuộc mạnh vào bộ lưu trữ (storage engine) được sử dụng — mỗi loại hỗ trợ một hoặc nhiều mức độ granular lock khác nhau. Dưới đây là sự phân bố khóa theo engine tiêu biểu: - MyISAMMEMORY: chỉ hỗ trợ khóa bảng (table-level lock) - InnoDB: chủ yếu dùng khóa hàng (row-level lock), nhưng cũng hỗ trợ khóa bảng khi cần - BDB (Berkeley DB, đã bị loại bỏ từ MySQL 5.1 nhưng vẫn có giá trị tham khảo): hỗ trợ cả khóa trang (page-level lock) và khóa hàng

So sánh đặc điểm ba loại khóa

  • Khóa hàng
    • Ưu điểm: Độ chi tiết cao → xác suất xung đột khóa thấp → hiệu năng đồng thời tốt
    • Nhược điểm: Chi phí quản lý lớn, thời gian cấp khóa chậm hơn, dễ phát sinh deadlock do phải duy trì nhiều khóa nhỏ lẻ
  • Khóa bảng
    • Ưu điểm: Chi phí thấp, cấp khóa nhanh, không thể xảy ra deadlock vì toàn bộ bảng được khóa cùng lúc
    • Nhược điểm: Độ chi tiết thô → dễ gây tắc nghẽn khi có nhiều truy vấn đọc/ghi xen kẽ
  • Khóa trang
    • Là giải pháp trung gian: chi phí và thời gian cấp khóa nằm giữa khóa bảng và khóa hàng
    • Độ chi tiết ở mức khối dữ liệu (thường ~16KB), nên khả năng xung đột và mức độ song song đều ở mức trung bình
    • Vẫn có thể xuất hiện deadlock do khóa từng trang riêng lẻ

Khóa bảng trong MyISAM

MyISAM áp dụng khóa bảng theo hai chế độ: - Khóa đọc chia sẻ (shared read lock): Nhiều phiên có thể đọc đồng thời mà không cản trở nhau. - Khóa ghi độc quyền (exclusive write lock): Khi một phiên đang ghi, mọi phiên khác — dù đọc hay ghi — đều bị chặn cho đến khi khóa được giải phóng. Một điểm đặc biệt của MyISAM là chèn đồng thời (concurrent insert), điều khiển bởi biến hệ thống concurrent_insert:
  • 0: Tắt hoàn toàn chèn đồng thời
  • 1: Cho phép chèn vào cuối bảng nếu không có khoảng trống do xóa trước đó
  • 2: Luôn cho phép chèn vào cuối bảng, bất kể tình trạng phân mảnh
Mặc định, MyISAM tự động cấp khóa bảng trước mỗi truy vấn — không cần khai báo thủ công. Tuy nhiên, bạn vẫn có thể chủ động yêu cầu khóa bằng cú pháp:
LOCK TABLES orders READ;
-- hoặc
LOCK TABLES customers WRITE;
Và giải phóng bằng:
UNLOCK TABLES;
Do khóa được cấp toàn bộ ngay từ đầu (all-or-nothing), MyISAM không bao giờ rơi vào trạng thái deadlock.

Khóa hàng trong InnoDB

InnoDB thực hiện khóa hàng dựa trên các mục trong chỉ mục (index entries). Nếu truy vấn sử dụng chỉ mục phù hợp (ví dụ: WHERE id = ? với id là khóa chính), chỉ các hàng thỏa mãn mới bị khóa. Ngược lại, nếu không dùng chỉ mục (hoặc dùng chỉ mục không hiệu quả), InnoDB sẽ khóa toàn bộ bảng dưới dạng khóa hàng ảo — dẫn đến hiệu năng tương đương khóa bảng. Hai loại khóa hàng chính:
  • Shared Lock (S): Cho phép đọc, ngăn các giao dịch khác lấy khóa X trên cùng tập dữ liệu.
  • Exclusive Lock (X): Cho phép cập nhật/xóa, ngăn cả khóa S lẫn X từ các giao dịch khác.
Để hỗ trợ kết hợp khóa hàng và khóa bảng, InnoDB sử dụng hai loại khóa ý định (intention locks) — đều là khóa bảng:
  • IS (Intention Shared): Báo hiệu rằng giao dịch định đặt khóa S lên một số hàng trong bảng.
  • IX (Intention Exclusive): Báo hiệu rằng giao dịch định đặt khóa X lên một số hàng trong bảng.
Các khóa này được InnoDB tự động quản lý — người dùng không cần can thiệp. Ví dụ truy vấn khóa:
-- Đặt khóa S lên hàng có order_id = 1001
SELECT * FROM orders WHERE order_id = 1001 LOCK IN SHARE MODE;

-- Đặt khóa X lên hàng có order_id = 1002
SELECT * FROM orders WHERE order_id = 1002 FOR UPDATE;
Deadlock trong InnoDB thường xảy ra khi hai giao dịch lần lượt khóa các hàng theo thứ tự ngược nhau và chờ nhau giải phóng — ví dụ: giao dịch A khóa hàng 1 rồi chờ hàng 2, trong khi giao dịch B khóa hàng 2 rồi chờ hàng 1.

Khóa trang trong BDB

BDB chia bảng thành các đơn vị gọi là trang (pages), mỗi trang chứa nhiều hàng. Khi một truy vấn yêu cầu khóa, BDB chỉ khóa các trang liên quan — không khóa toàn bộ bảng như MyISAM, cũng không khóa từng hàng như InnoDB. Ưu điểm: cân bằng giữa hiệu năng và mức độ cô lập. Nhược điểm: vẫn tồn tại khả năng deadlock và mức độ song song thấp hơn InnoDB trong môi trường cập nhật tần suất cao trên tập dữ liệu phân tán. Tóm lại, lựa chọn engine và hiểu rõ hành vi khóa giúp tối ưu hóa thiết kế ứng dụng — ví dụ: dùng MyISAM cho hệ thống báo cáo chỉ đọc; InnoDB cho hệ thống giao dịch OLTP yêu cầu tính toàn vẹn cao và song song mạnh; còn BDB thì mang tính học thuật hơn trong bối cảnh hiện đại.

Thẻ: mysql innodb MyISAM Locking Concurrency

Đăng vào ngày 26 tháng 7 lúc 11:35