Q

Quản trị viên

Là một lập trình viên yêu công nghệ, thích viết blog để chia sẻ kiến thức, kinh nghiệm lập trình và những điều thú vị trong thế giới tech.

2312 bài viết · Website
Lập trình 22/09/2026 6 phút

Băm mật khẩu: vì sao SHA-256 nhanh là SAI, và bcrypt chậm 1,3 triệu lần là cố ý

Dùng SHA-256 để băm mật khẩu nghe có vẻ an toàn — nó là hàm băm mạnh mà. Nhưng chính sự NHANH của nó khiến nó sai cho mật khẩu. Bài này đo thật trong Go: SHA-256 băm một mật khẩu trong 38 nano-giây (26 triệu lần/giây), còn bcrypt cost 10 mất 51ms — chậm hơn 1,3 triệu lần, cố ý, để brute-force bất khả thi; mỗi cost +1 chậm gấp đôi. Kèm vai trò của salt chống rainbow table.

Lập trình 22/09/2026 6 phút

Tối ưu query từ đầu tới cuối: cây quyết định, checklist, và một query từ 51ms xuống 3.7ms

Loạt SQL sâu đi qua 11 công cụ; bài cuối ghép chúng thành một quy trình. Query chậm không phải chuyện thử-sai — có cây quyết định rõ ràng bắt đầu từ EXPLAIN ANALYZE. Bài này đo thật một query chậm (JOIN + filter + ORDER BY LIMIT trên 2 triệu dòng): viết sargable một mình không đủ (vẫn 51ms), nhưng sargable + index đúng + ANALYZE đưa xuống 3.66ms — nhanh 14 lần. Kèm cây quyết định và checklist tối ưu.

Lập trình 22/09/2026 6 phút

Phân trang: vì sao OFFSET 1 triệu chậm 3000 lần, và keyset pagination giữ tốc độ phẳng

OFFSET LIMIT là cách phân trang ai cũng viết, và nó hoạt động hoàn hảo... cho tới trang thứ 50.000. Bài này đo thật trên bảng 2 triệu dòng: OFFSET chậm dần tuyến tính — trang đầu 0.029ms nhưng trang cuối 144.941ms, vì nó phải đọc qua 1.000.020 dòng chỉ để lấy 20. Keyset pagination (WHERE id > last_id) giữ ~0.04ms phẳng ở mọi trang. Kèm plan chứng minh OFFSET quét rồi vứt, keyset nhảy thẳng.

Lập trình 22/09/2026 6 phút

SQL injection: vì sao nối chuỗi làm lộ cả tài khoản admin, và prepared statement chặn triệt để

SQL injection vẫn nằm trong OWASP Top 10 sau hai thập kỷ, vì gốc rễ của nó đơn giản mà dễ mắc: trộn lẫn code và data. Bài này tái hiện thật trong lab PostgreSQL cô lập: một query đăng nhập nối chuỗi bị input ' OR '1'='1 biến điều kiện thành luôn-đúng, trả về 2 dòng (bypass đăng nhập, lộ cả admin); cùng input đó qua prepared statement trả 0 dòng — bị coi là chuỗi mật khẩu, không bao giờ thành SQL. Đây là kiến thức phòng thủ.

Lập trình Go 22/09/2026 9 phút

Build tags trong Go: một mã nguồn, nhiều binary theo điều kiện biên dịch

Build tags cho phép chọn tệp nào được biên dịch theo hệ điều hành, kiến trúc, hoặc cờ tùy biến. Đo thật trong Go 1.23 hai cơ chế: chỉ thị //go:build với biểu thức logic, và hậu tố tên tệp _GOOS.go — cùng go list chứng minh chính xác tệp nào lọt vào build.

Cơ sở dữ liệu 22/09/2026 6 phút

Nhân bản đồng bộ vs bất đồng bộ trong PostgreSQL: đổi thông lượng lấy độ bền

Nhân bản sync bắt primary chờ standby xác nhận trước khi commit — không mất dữ liệu khi primary chết, nhưng chậm hơn. Đo thật: dải synchronous_commit từ 5021 xuống 2475 tps, và demo commit treo với wait_event SyncRep khi standby chết. PostgreSQL 16.