- Giao dịch là cấu trúc để thực thi nhiều thao tác trong cơ sở dữ liệu như một đơn vị nguyên tử, bao gồm đọc, ghi, cập nhật và xóa
- MySQL và Postgres điều khiển giao dịch bằng
begin; và commit;, đồng thời hủy thay đổi bằng rollback; khi có lỗi hoặc thất bại
- Cả hai cơ sở dữ liệu đều đảm bảo đọc nhất quán (consistent read), nhưng Postgres dùng lưu trữ hàng đa phiên bản (MVCC), còn MySQL dùng undo log
- Mức cô lập (isolation level) kiểm soát sự can thiệp dữ liệu giữa các giao dịch và được chia thành bốn cấp từ Serializable đến Read Uncommitted
- Postgres và MySQL xử lý xung đột ghi đồng thời theo những cách khác nhau; Postgres dùng xác thực lạc quan, còn MySQL dùng khóa cấp hàng (row-level locking)
Khái niệm cơ bản về giao dịch
- Giao dịch là cấu trúc gom nhiều thao tác SQL trong cơ sở dữ liệu thành một đơn vị thực thi nguyên tử
- Bắt đầu bằng
begin; và kết thúc bằng commit;, có thể chạy nhiều truy vấn ở giữa
- Tại thời điểm
commit;, mọi thay đổi được áp dụng cùng một lúc
- Khi xảy ra sự cố ngoài ý muốn (mất điện, lỗi đĩa, v.v.) hoặc khi chủ động hủy, có thể dùng
rollback; để hoàn tác thay đổi
- Postgres hỗ trợ khôi phục bằng WAL (Write-Ahead Log)
- Dữ liệu được thay đổi trong giao dịch sẽ được cô lập, không hiển thị với các session khác
- Khi
rollback;, mọi thay đổi bị hủy và cơ sở dữ liệu được khôi phục về trạng thái ban đầu
Đọc nhất quán (Consistent Reads)
- Giao dịch cần duy trì một khung nhìn dữ liệu nhất quán không bị ảnh hưởng bởi các thay đổi bên ngoài trong lúc đang chạy
- MySQL và Postgres đều hỗ trợ điều này từ chế độ
REPEATABLE READ trở lên, nhưng cách triển khai khác nhau
- Postgres: quản lý phiên bản của từng hàng bằng lưu trữ hàng đa phiên bản (MVCC)
- MySQL: dùng undo log để tái tạo các phiên bản trước đó
Lưu trữ hàng đa phiên bản trong Postgres
- Mỗi khi một hàng được cập nhật, một phiên bản mới sẽ được tạo; phiên bản cũ ghi ID giao dịch trong
xmax, còn phiên bản mới ghi trong xmin
- Trước khi giao dịch được commit, các session khác không thể nhìn thấy nội dung thay đổi
- Sau khi commit, phiên bản mới được phản ánh trên toàn bộ cơ sở dữ liệu
- Khi
rollback;, thay đổi bị loại bỏ và dữ liệu gốc được giữ nguyên
- Các phiên bản hàng cũ được dọn dẹp bằng lệnh
VACUUM FULL để thu hồi không gian lưu trữ
Undo Log của MySQL
- MySQL ghi đè trực tiếp lên hàng, nhưng ghi lại giá trị trước đó vào undo log để có thể khôi phục khi cần
- Mỗi hàng có metadata gồm
xid (ID giao dịch chỉnh sửa gần nhất) và ptr (con trỏ undo log)
- Khi nhiều giao dịch chạy đồng thời, undo log cho phép mỗi giao dịch chọn đọc đúng phiên bản mà nó cần
- Có thể tồn tại nhiều bản ghi undo log cho cùng một hàng và phiên bản phù hợp sẽ được chọn dựa trên ID giao dịch
Mức cô lập (Isolation Levels)
- Đây là thiết lập kiểm soát sự can thiệp dữ liệu giữa các giao dịch, được nới lỏng dần theo thứ tự Serializable → Repeatable Read → Read Committed → Read Uncommitted
- Serializable: mọi giao dịch hoạt động như thể được thực thi tuần tự
- Repeatable Read: chạy lại cùng một truy vấn sẽ cho cùng kết quả, nhưng vẫn có thể xảy ra phantom read
- Read Committed: có thể đọc các thay đổi từ giao dịch khác đã được commit
- Read Uncommitted: cho phép dirty read, là mức bảo vệ thấp nhất nhưng hiệu năng cao
Ghi đồng thời (Concurrent Writes)
- Cách xử lý khi hai giao dịch cùng sửa một hàng tại cùng thời điểm sẽ khác nhau tùy cơ sở dữ liệu
MySQL: Khóa cấp hàng (Row-level Locking)
- Khóa chia sẻ (S lock) cho phép nhiều giao dịch đọc cùng lúc
- Khóa độc quyền (X lock) chỉ cho phép một giao dịch sửa hàng
- Trong chế độ
SERIALIZABLE, mọi cập nhật đều phải lấy X lock và có thể phát sinh deadlock khi xảy ra xung đột
- MySQL phát hiện deadlock và chấm dứt một trong hai giao dịch
Postgres: Serializable Snapshot Isolation
- Postgres dùng predicate lock để theo dõi truy cập ở cấp độ tập hợp hàng
- Ví dụ: khóa đối với điều kiện
WHERE id BETWEEN 10 AND 20
- Hệ thống không chặn truy cập thực tế mà phát hiện xung đột, rồi chấm dứt giao dịch khi có vi phạm
- Cơ chế giải quyết xung đột lạc quan (optimistic conflict resolution) giúp tránh deadlock
- Tương tự MySQL, khi có xung đột thì một giao dịch sẽ bị chấm dứt và ứng dụng cần triển khai logic thử lại
Kết luận
- Giao dịch là thành phần cốt lõi của cơ sở dữ liệu, đảm bảo tính nguyên tử, tính nhất quán, tính cô lập và tính bền vững (ACID)
- Postgres và MySQL đạt cùng một mục tiêu thông qua những cấu trúc nội bộ khác nhau
- Hiểu bốn mức cô lập và nguyên lý hoạt động của giao dịch sẽ giúp vận hành cơ sở dữ liệu ổn định hơn
Chưa có bình luận nào.