Bạn mua vé xem phim, trên mỗi vé sẽ có số in sẵn. Sau đó, hệ thống sẽ đánh số vé tiếp theo liền kề (ví dụ: vé 001, 002, 003) cho các vé tiếp theo. Không bao giờ có hai vé trùng số.
Giả sử ngày hôm nay bạn tạo bảng mới là users
Dữ liệu:
id username
1 admin
2 nam
3 hoa
4 linh
5 hung
Trời đẹp, chim hót líu lo, hoa nở khắp nơi, mọi thứ đều ổn.
Xem xét kỹ "công trình", bạn quyết định xóa:
DELETE FROM users
WHERE id=5;
Bảng còn:
id username
1 admin
2 nam
3 hoa
4 linh
Sau đó thêm user mới:
INSERT INTO users(username)
VALUES('tuan');Bạn mong đợi:
ID = 5
Nhưng MySQL trả về:
ID = 6
Lính mới "trình độ cao" như bạn sẽ...théc méc:
"Ủa? Sao kỳ cục kẹo vậy...Số 5 còn trống mà?"
Vì sao chuyện này xảy ra?
Trong MySQL, cột AUTO_INCREMENT thường không sử dụng lại các ID đã bị xóa.
Thay vào đó MySQL tiếp tục tăng từ giá trị lớn nhất đã từng cấp phát.
Ví dụ:
Đã dùng tới 5
↓
Xóa 5
↓
Bản ghi mới nhận 6
Đây là hành vi hoàn toàn bình thường.
Ví dụ thực tế
Bạn đi khám bệnh.
Lấy số:
001
002
003
004
005
Vì một lý do nào đó, người số 005 bỏ về.
Bệnh viện không làm:
005
mới rồi phát lại cho người kế tiếp.
Thay vào đó:
006
Đơn giản hơn.
Ít rủi ro hơn.
AUTO_INCREMENT cũng suy nghĩ như vậy.
MySQL nhớ điều gì?
Nhiều người nghĩ:
MySQL đếm số dòng
Không.
MySQL nhớ:
Số tiếp theo sẽ cấp phát
Ví dụ:
1
2
3
4
5
Nó ghi nhớ:
Lần tới là 6
Cho dù:
5 bị xóa
vẫn vậy.
Một hiểu lầm phổ biến
Lính mới:
"Nếu bảng còn 4 dòng thì ID mới phải là 5."
Không. MySQL không quan tâm bảng còn bao nhiêu dòng.
Nó chỉ quan tâm:
Lần cấp phát cuối cùng là bao nhiêu
Ví dụ đau lòng
Bảng:
id username
1 admin
2 nam
3 hoa
Bạn xóa:
2
Còn:
id username
1 admin
3 hoa
Thêm mới:
linh
Kết quả:
id username
1 admin
3 hoa
4 linh
Lính mới...théc méc:
"ID số 2 đâu?"
MySQL:
"Đó là lịch sử."
Tại sao MySQL không tái sử dụng ID?
Nếu tái sử dụng liên tục:
5
↓
xóa
↓
5
↓
xóa
↓
5
Có thể gây:
- Nhầm dữ liệu
- Nhầm log
- Nhầm liên kết
- Nhầm báo cáo
Đặc biệt ở hệ thống lớn.
Ví dụ thực tế
User:
ID = 500
đã từng tồn tại.
Log hệ thống ghi:
User 500 đăng nhập
Nếu sau này:
500
được cấp cho người khác.
Bạn sẽ rất khó phân biệt.
Có phải ID bị nhảy số là lỗi?
Không hề, điều đó còn là điều tốt.
Ví dụ:
1
2
5
8
12
Hoàn toàn bình thường.
Rất nhiều website lớn cũng vậy.
Tập tành làm web
Bạn đã bao giờ upload website lên host.
Nhìn thấy một số "thứ tự" nào đó kiểu như:
1
2
4
7
9
Và hoảng hốt:
"Database lỗi rồi!"
Không sao.
Đây là hành vi bình thường của:
AUTO_INCREMENTCó nên reset AUTO_INCREMENT?
Ví dụ:
ALTER TABLE users
AUTO_INCREMENT = 1;Nghe có vẻ hấp dẫn.
Nhưng thực tế:
Hiếm khi cần.
Và nếu dữ liệu vẫn còn:
Có thể gặp:
Duplicate Entry
Khi nào nên reset?
Thường chỉ khi:
- Bảng test
- Bảng demo
- Bảng rỗng
Ví dụ:
TRUNCATE TABLE users;
Sau đó:
AUTO_INCREMENTthường quay về đầu.
Nhưng với dữ liệu thật:
Thường không cần.
Sự thật biết rồi, khổ lắm, nói mãi
Nhiều người nghĩ:
ID phải liên tục
Thực tế:
Các hệ thống lớn thường có:
ID nhảy số
Thậm chí có nơi:
1001
1050
1200
3000
Và không ai quan tâm.
Điều quan trọng là:
ID duy nhất
Không phải:
ID đẹp
Debug kiểu dev "xịn sò"
1. Kiểm tra AUTO_INCREMENT
SHOW CREATE TABLE users;
2. Kiểm tra giá trị tiếp theo
Trong phpMyAdmin:
Auto Increment
3. Dùng COUNT(*) để đếm dữ liệu
Đừng dùng:
SELECT MAX(id)
Hãy dùng:
SELECT COUNT(*)
Checklist chuẩn không cần chỉnh
- Xóa dữ liệu không làm ID quay lại
- AUTO_INCREMENT không đếm số dòng
- ID nhảy số là bình thường
- Không cần reset AUTO_INCREMENT thường xuyên
- COUNT(*) mới là số lượng dữ liệu
- MAX(id) không phải số user
FAQ nhanh
Vì sao xóa ID số 5 nhưng user mới nhận số 6?
Vì AUTO_INCREMENT tiếp tục tăng.
ID bị nhảy số có phải lỗi?
Không
Có nên sửa cho ID liên tục không?
Thường không.
MAX(id) có phải số lượng dữ liệu không?
Không
Bạn có thể cũng đang gặp
AUTO_INCREMENT hoạt động ra sao?
Tổng kết
AUTO_INCREMENT không hoạt động theo kiểu:
Tiết kiệm từng con số cho...đẹp!
Nó hoạt động theo kiểu:
Đã dùng rồi
↓
Cho nghỉ hưu luôn
Vì vậy:
1
2
3
4
5
xóa:
5
Thêm mới:
6
là hoàn toàn bình thường.
Và hãy nhớ:
MySQL không quan tâm ID có đẹp hay không.
Nó chỉ quan tâm:
"Có duy nhất hay không."
Còn chuyện số 5 đang trống...
MySQL ngủ rất ngon và không hề bận tâm.