MySQL - Autoincrement không tăng liên tiếp nếu hàng cuối cùng bị xóa


8

Tôi có một bảng chứa id khóa chính tăng tự động. Nếu tôi xóa hàng cuối cùng (id cao nhất, cho exampe id = 6) và chèn một hàng mới, id mới bắt đầu ở 7. Thông số nào tôi phải thay đổi mà khóa chính bắt đầu từ 6?

CREATE TABLE animals (
 id MEDIUMINT NOT NULL AUTO_INCREMENT,
 name CHAR(30) NOT NULL,
 PRIMARY KEY (id)
) ENGINE=MyISAM;

INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');

Kết quả:
id name
1 dog
2 cat
3 penguin
4 lax
5 whale
6 đà điểu

DELETE FROM animals WHERE id = 6;
INSERT INTO animals (name) VALUES
('x');

Kết quả:
id id
1 dog
2 cat
3 penguin
4 lax
5 whale
7 x

Cảm ơn về lời khuyên.


Vậy nếu có khoảng trống thì sao? (có thể xuất hiện do một số lý do khác, không chỉ bằng cách xóa các hàng)
ypercubeᵀᴹ

Bạn muốn làm gì nếu xóa xảy ra sau khi chèn? bạn sẽ sử dụng lại những khoảng cách? là có thì tôi không nghĩ Danh tính là loại phù hợp cho cột đó. nó cung cấp cho bạn một cơ hội để không lo lắng về các giá trị duy nhất trong cột đó. nếu bạn có ý định giữ các giá trị theo thứ tự thì bạn có thể chỉ cần sử dụng kiểu dữ liệu kiểu INT / BIGINT thông thường. tìm / tái sử dụng / đặt lại các giá trị cho mọi khoảng trống bị thiếu cũng giống như từ bỏ mục đích của Tài sản Nhận dạng.
Anup Shah

@giordano Tại sao bạn muốn trở thành một TỰ DO CHÍNH HÃNG TỰ ĐỘNG gọn gàng? đối phó với nó cũng có một "khoảng trống" trong dữ liệu bảng của bạn nếu bạn cập nhật / xóa do phân mảnh ..
Raymond Nijland

Tôi đã thực hiện một cuộc điều tra về các giá trị auto_increment liên tục cho SQL Server một thời gian trước: sqlity.net/en/792/the-gap-in-the-identity-value- resultence - Mặc dù nó không dành cho MySQL, nhưng các cơ chế bên dưới là như nhau , vì vậy bạn sẽ nhận được kết quả tương tự. Nói tóm lại, bạn không thể ngăn các khoảng trống tạo ra các chuỗi tự động.
Sebastian Meine

@ypercube: cảm ơn câu trả lời. Thật vậy, khoảng cách tôi nhận được từ một ví dụ khác phức tạp hơn nhưng tôi muốn chỉ ra một ví dụ tối thiểu. Ví dụ thực tế là (1) thay đổi ngày hết hạn của một hàng (ví dụ: từ bảng sản phẩm) do thay đổi thuộc tính và (2) thêm sản phẩm mới có cùng mã sản phẩm, thuộc tính mới, ngày hiệu lực mới và thời hạn mở ngày. Điều đáng mừng là khóa chính mới không tự động tăng lên với +1 nhưng +2. Rõ ràng, trong bước (1) hoặc (2) có sự gia tăng tự động vô hình. Tôi tự hỏi những lý do khác cho khoảng cách.
giordano

Câu trả lời:


12

Đây là theo thiết kế - tất cả DBMS thực hiện điều này với các cột tăng tự động.

Nếu họ không toàn vẹn tham chiếu bên ngoài có thể bị hư hại. Đối với một ví dụ đơn giản về điều này, hãy tưởng tượng bạn đang lưu trữ URL cho dịch vụ rút ngắn bằng cách sử dụng cột tăng tự động làm khóa. Bạn không biết liệu URL rút ngắn đã được cung cấp cho bất kỳ ai chưa, và cơ sở dữ liệu chắc chắn là không, vì vậy việc sử dụng lại ID 1234 có thể dẫn đến việc bà ngoại nghèo truy cập somenastyyhsite.xxx thay vì lovlyknmit.org khi cô nhấp vào http: / /shortthi.ng/1234 trong một email cũ, thay vì nhận được thông báo "xin lỗi nhưng liên kết này không còn tồn tại trong hồ sơ của chúng tôi".

Ngoài ra, nếu bạn đặt lại mức tăng sau khi xóa mục cuối cùng, bạn cũng sẽ hoàn thành tất cả công việc (hoặc mong muốn cơ sở dữ liệu) đánh số lại mọi thứ sau mục thứ 5 là 5 triệu khi mục thứ 5 bị xóa? hoàn thành với các thay đổi đối với các bảng khác trong đó các ràng buộc khóa ngoài của chúng chỉ vào cột tăng? Làm thêm như vậy có thể nhận được IO-khôn rất tốn kém.

Nếu bạn làm reset điểm tăng sau khi xóa mục cuối cùng, đừng có rất rất cẩn thận về mức cô lập giao dịch của bạn: Bạn có thể thiết lập lại nó chỉ như là một giao dịch làm cho việc sử dụng các giá trị, dẫn đến sai sót (hoặc tệ hơn, thất bại im lặng), trừ trường hợp bạn chắc chắn rằng hành động của bạn được cách ly hoàn toàn 100%.

Tôi thường khuyên những người làm việc với cơ sở dữ liệu nên đọc "SQL Antipotype" có một chương về vấn đề này có tên là "Psuedo-Key Neat Freaks" (bao gồm vấn đề theo cách thân thiện hơn so với tiêu đề chương có thể ám chỉ một số!). Về cơ bản, nếu giá trị có ý nghĩa ngoài việc là khóa (hoặc nhiều nhất là mang thông tin thứ tự chèn) thì có lẽ đó không phải là cột tăng tự động và nếu nó không có ý nghĩa gì ngoài việc là khóa (hoặc nhiều nhất là mang theo lệnh chèn thông tin) sau đó khoảng cách không nên quan trọng.


Cảm ơn lời giải thích này. Tôi thấy rằng tôi phải đi sâu hơn vào khái niệm chính. Tôi tự hỏi làm thế nào cơ chế tăng tự động hoạt động, vì tôi cũng quan sát thấy các lỗ hổng trong khóa chính khi tôi không xóa nó nhưng thay đổi (cập nhật) một hàng và thêm một hàng mới. Chắc chắn, những gì tôi sẽ không làm là thay đổi giá trị gia tăng tự động một cách manaully.
giordano

Liên quan đến "tìm hiểu sâu hơn về khái niệm chính", tôi đặc biệt khuyến nghị cuốn sách Antipotypes SQL của Bill Karwin - nó bao gồm chủ đề này và một số chủ đề phổ biến khác (và không phổ biến), nói về cách hiểu sai, tại sao lại sai phương pháp có thể gây ra sự cố, cách khắc phục và khi phương thức "sai" có thể được sử dụng (hoặc là lựa chọn duy nhất) dù sao, theo cách ngắn gọn nhưng dễ tiếp cận.
David Spillett

Spillet: Cảm ơn vì chỉ định này. Tôi đọc bây giờ và nó rất hữu ích. Tuy nhiên, tôi không hiểu tại sao InnoDB và MyISAM đếm khác nhau: dba.stackexchange.com/questions/51883/...
Giordano

0

Bạn có thể đặt lại giá trị auto_increment bằng cách sử dụng như sau:

ALTER TABLE MyTable AUTO_INCREMENT = 1234;

Bạn cần xác định giá trị tối đa có trong bảng và thêm 1 vào giá trị đó để sử dụng trong câu lệnh trên.


Ý tưởng tồi này sẽ khóa bảng của bạn khỏi việc đọc hoặc viết trong các phiên bản MySQL "gần như tất cả". MySQL 5.6 có thể thực hiện TRỰC TIẾP nhưng đôi khi nó cũng cần khóa bảng.
Raymond Nijland

2
@RaymondNijland Tôi không nghĩ khóa sẽ đủ lâu để bất cứ ai chú ý.
ypercubeᵀᴹ

@Max, Raymond, ypercube: Cảm ơn câu trả lời. Tôi sẽ tránh để làm loại thay đổi này.
giordano
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.