Lesson 54 — SQL & database/sql

Ba mô-đun tương tác để "thấy" cách Go nói chuyện với database: connection pool hoạt động ra sao khi quá tải, vì sao placeholder chống được SQL injection còn nối chuỗi thì không, và vòng đời một query Query → Rows → Scan → Close.

1. Connection pool visualizer

*sql.DB giữ một pool connection tái dùng. Mỗi query cần "mượn" một connection rảnh; nếu hết, request phải xếp hàng chờ; nếu pool đã đạt MaxOpenConns thì không mở thêm. Tăng tải để thấy pool cạn (exhaust).


Pool (connection)
Đang bận: 0 / 4
Hàng chờ (request đợi connection)
Trong hàng chờ: 0

2. Prepared statement vs string concat — SQL injection

Gõ "email" người dùng nhập (thử input độc hại bên dưới) rồi xem hai cách dựng query. Nối chuỗi biến input thành cú pháp SQL; placeholder coi input chỉ là giá trị.

❌ Nối chuỗi (string concat)

✅ Placeholder (? + tham số)

3. Query lifecycle — Query → Rows → Scan → Close

Đi từng bước vòng đời một db.Query trả nhiều dòng. Chú ý ba việc bắt buộc: defer rows.Close(), loop rows.Next() + Scan, và rows.Err() sau loop.

B1
db.Query()
Gửi SQL + tham số, mượn 1 connection, trả *Rows
B2
defer Close()
Đặt lịch đóng Rows → trả connection về pool
B3
rows.Next()
Con trỏ tiến tới dòng kế; false khi hết
B4
rows.Scan()
Copy cột dòng hiện tại vào biến Go
B5
rows.Err()
Sau loop: kiểm tra lỗi I/O giữa chừng
B6
Close()
defer chạy → connection về pool, dùng lại được
idnameemail
Bấm "Bước tiếp →" để bắt đầu.