MySQL - Autoincrement tidak bertambah secara berurutan jika baris terakhir telah dihapus

8

Saya memiliki tabel yang berisi id kunci primer yang ditambahkan secara otomatis. Jika saya menghapus baris terakhir (id tertinggi, untuk exampe id = 6) dan menyisipkan baris baru, id baru dimulai pada 7. Parameter apa yang harus saya ubah bahwa kunci utama dimulai pada 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');

Hasil:
id name
1 dog
2 cat
3 penguin
4 lax
5 whale
6 ostrich

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

Hasil:
id name
1 dog
2 cat
3 penguin
4 lax
5 whale
7 x

Terima kasih atas sarannya.

giordano
sumber
Jadi bagaimana jika ada kesenjangan? (yang dapat muncul karena beberapa alasan lain, tidak hanya dengan menghapus baris)
ypercubeᵀᴹ
apa yang ingin Anda lakukan jika penghapusan terjadi setelah beberapa penyisipan? apakah Anda akan menggunakan kembali celah itu? adalah ya maka saya tidak berpikir Identitas adalah tipe yang tepat untuk kolom itu. itu memberi Anda kesempatan untuk tidak khawatir tentang nilai-nilai unik di kolom itu. jika Anda berniat untuk menjaga nilai dalam urutan maka Anda bisa saja menggunakan tipe data tipe INT / BIGINT biasa. menemukan / menggunakan kembali / mereset nilai untuk setiap celah yang hilang seperti kehilangan tujuan Properti Identitas.
Anup Shah
@giordano Mengapa Anda ingin menjadi AUTO_INCREMENT PRIMARY KEY key freak? berurusan dengannya ada juga "celah" pada data tabel Anda jika Anda memperbarui / menghapus karena fragmentasi ..
Raymond Nijland
Saya melakukan penyelidikan tentang nilai auto_increment terus menerus untuk SQL Server beberapa waktu yang lalu: sqlity.net/en/792/the-gap-in-the-identity-value- followingence - Meskipun bukan untuk MySQL, mekanisme yang mendasarinya adalah sama , jadi Anda akan mendapatkan hasil yang serupa. Singkatnya, Anda tidak dapat mencegah celah dari urutan yang dibuat secara otomatis.
Sebastian Meine
@ ypercube: terima kasih atas jawaban. Memang, celah yang saya dapatkan dari contoh lain yang lebih kompleks tetapi saya ingin menunjukkan contoh minimal. Contoh nyata adalah (1) mengubah tanggal kadaluwarsa dari suatu baris (misalnya dari tabel produk) karena perubahan atribut dan (2) menambahkan produk baru dengan kode produk yang sama, attrribute baru, tanggal efektif baru dan kadaluwarsa terbuka tanggal. Yang terjadi adalah kunci primer baru tidak secara otomatis bertambah dengan +1 tetapi +2. Jelas, pada langkah (1) atau (2) ada kenaikan otomatis yang tidak terlihat. Saya bertanya-tanya apa alasan lain untuk kesenjangan.
giordano

Jawaban:

12

Ini adalah desain - semua tindakan DBMS ini dengan kolom kenaikan otomatis.

Jika integritas integritas referensial mereka tidak dapat rusak. Untuk contoh sederhana ini, bayangkan Anda menyimpan URL untuk layanan pemendek menggunakan kolom kenaikan otomatis sebagai kunci. Anda tidak tahu apakah URL yang diperpendek telah diberikan kepada siapa pun, dan databasenya jelas tidak, jadi menggunakan kembali ID 1234 dapat mengakibatkan nenek miskin mengunjungi somenastypornsite.xxx alih-alih loverlyknitting.org ketika dia mengklik http: / /shortthi.ng/1234 di email lama, alih-alih menerima pesan "maaf tapi tautan ini tidak ada lagi di catatan kami".

Juga jika Anda mengatur ulang kenaikan setelah menghapus item terakhir, apakah Anda juga akan melalui semua pekerjaan (atau mengharapkan basis data) untuk menomori ulang semuanya setelah item ke-5 dari 5 juta ketika item ke-5 dihapus? lengkap dengan perubahan pada tabel lain di mana kendala kunci asingnya menunjuk pada kolom kenaikan? Pekerjaan ekstra semacam itu bisa sangat mahal untuk IO.

Jika Anda melakukan reset titik kenaikan setelah menghapus item terakhir, jangan menjadi sangat sangat berhati-hati dari tingkat isolasi transaksi Anda: Anda mungkin ulang seperti transaksi lain merek menggunakan dari nilai, yang mengarah ke kesalahan (atau lebih buruk, kegagalan diam), kecuali Anda memastikan bahwa tindakan Anda sepenuhnya 100% terisolasi.

Saya biasanya merekomendasikan orang yang bekerja dengan database membaca "SQL Antipatterns" yang memiliki bab tentang masalah ini bernama "Psuedo-Key Neat Freaks" (yang membahas masalah ini dengan cara yang lebih ramah daripada judul bab yang mungkin menyiratkan pada beberapa!). Pada dasarnya, jika nilai memiliki makna di luar menjadi kunci (atau paling banyak membawa informasi pesanan penyisipan) maka mungkin tidak boleh menjadi kolom penambahan-otomatis, dan jika itu tidak memiliki makna di luar menjadi kunci (atau paling banyak membawa urutan penyisipan informasi) maka kesenjangan seharusnya tidak menjadi masalah.

David Spillett
sumber
Terima kasih atas penjelasan ini. Saya melihat bahwa saya harus membenamkan lebih dalam ke konsep kunci. Saya bertanya-tanya bagaimana mekanisme kenaikan otomatis bekerja, karena saya amati juga celah di kunci utama ketika saya tidak menghapusnya tetapi mengubah (memperbarui) satu baris dan menambahkan yang baru. Jelas, apa yang tidak akan saya lakukan adalah mengubah nilai kenaikan otomatis manaully.
giordano
Mengenai "menggali lebih dalam konsep kunci", saya sangat merekomendasikan buku SQL Antipatterns oleh Bill Karwin - ini membahas hal ini dan sejumlah topik umum lainnya (dan tidak begitu umum), berbicara tentang bagaimana mendapatkan kesalahan, mengapa kesalahan umum metode dapat menyebabkan masalah, cara memperbaikinya, dan ketika metode "salah" mungkin boleh digunakan (atau satu-satunya pilihan), dengan cara yang ringkas namun dapat diakses.
David Spillett
Spillet: Terima kasih atas indikasi ini. Saya membaca sekarang dan itu sangat membantu. Namun demikian, saya tidak mengerti mengapa InnoDB dan MyISAM dihitung secara berbeda: dba.stackexchange.com/questions/51883/…
giordano
0

Anda dapat mengatur ulang nilai auto_increment menggunakan yang berikut:

ALTER TABLE MyTable AUTO_INCREMENT = 1234;

Anda harus menentukan nilai maksimum yang ada dalam tabel, dan menambahkan 1 ke nilai itu untuk digunakan dalam pernyataan di atas.

Max Vernon
sumber
Ide buruk ini akan mengunci meja Anda dari membaca atau menulis di "hampir semua" versi MySQL. MySQL 5.6 dapat melakukan ALTER LANGSUNG tetapi terkadang juga perlu mengunci tabel.
Raymond Nijland
2
@RaymondNijland Saya tidak berpikir kunci akan bertahan cukup lama bagi siapa pun untuk memperhatikan.
ypercubeᵀᴹ
@ Max, Raymond, ypercube: Terima kasih atas jawabannya. Saya akan menghindari untuk melakukan perubahan semacam ini.
giordano