Anchor: "Hệ thống thanh toán nội bộ gặp double charge khi user click submit 2 lần"
Bước 101
Mô phỏng 2 transaction đồng thời, đọc xmin/xmax thực
Trước khi làm bất cứ điều gì với isolation level, hiểu MVCC từ dưới lên. Mở 2 psql session, chạy concurrent transactions, query pg_stat_activity và xmin/xmax trên row đang được update. Thấy snapshot bằng tay.
Ví dụ
Session A: BEGIN, SELECT balance FROM accounts WHERE id=1; Session B: UPDATE accounts SET balance=balance-100 WHERE id=1; COMMIT; Session A SELECT lại: thấy gì? Thay isolation level Repeatable Read, chạy lại. So sánh output.
Bước 202
Vẽ lock graph cho 1 scenario có deadlock, hiểu Postgres detect ra sao
Không học deadlock qua lý thuyết. Tạo deadlock có chủ ý: transaction A lock row 1 rồi cố lock row 2, transaction B lock row 2 rồi cố lock row 1. Vẽ dependency graph, hiểu Postgres detect cycle ra sao và abort cái nào.
Ví dụ
Chạy 2 script song song tạo deadlock. Đọc log Postgres: 'ERROR: deadlock detected', 'DETAIL: Process N waits for ShareLock on transaction M'. Trace lại từng lock acquisition. Rút ra: consistent lock ordering ngăn deadlock.
Bước 303
Test 4 isolation level cùng 1 query, so sánh output
Cùng 1 scenario concurrent read-write, chạy với Read Committed, Repeatable Read, Serializable. Quan sát khi nào phantom read xảy ra, khi nào serialization error được throw, khi nào retry là cần thiết. Không đọc bảng so sánh, tự thấy.
Ví dụ
Scenario: transfer 1000 từ account A sang B, đồng thời calculate total balance. Chạy với Read Committed: total sai. Repeatable Read: total đúng nhưng transfer có thể lost update. Serializable: transaction bị abort, cần retry.
Bước 404
Implement outbox table cho 1 use case thật
Thay vì publish event trực tiếp sau DB write, implement outbox: write event vào table cùng transaction với business data. Poller đọc outbox và publish. Test failure: DB commit xong broker down, broker up xong poller xử lý tiếp. Data không mất.
Ví dụ
Schema: orders table + outbox table. Khi tạo order: INSERT orders và INSERT outbox trong cùng transaction. Poller: SELECT FOR UPDATE SKIP LOCKED từ outbox, publish event, DELETE. Test: kill broker giữa chừng, restart, verify order event delivered exactly once.
Bước 505
Refactor 1 saga sai sang version có compensation đúng
Bắt đầu với saga không có compensation: khi step 3 fail, step 1 và 2 đã commit, không rollback được. Refactor: thêm compensation transaction cho từng step. Test failure ở từng điểm trong chuỗi, verify system về trạng thái nhất quán.
Ví dụ
Saga: reserve inventory, charge payment, create shipment. Simulate payment fail sau khi inventory đã reserve. Không có compensation: inventory bị giữ mãi. Với compensation: inventory được release, order về trạng thái cancelled. Verify bằng query sau mỗi scenario.
5 bước này lặp lại qua từng module. Cuối khoá: nhìn vào bất kỳ scenario concurrent nào, não tự hỏi isolation level nào, lock gì, retry khi nào. Không cần nhớ lại, tự khắc hỏi.