Urutan tidak menghasilkan kumpulan angka yang bebas celah, dan benar-benar tidak ada cara untuk membuatnya melakukannya karena rollback atau kesalahan akan "menggunakan" nomor urut.
Saya menulis artikel tentang ini beberapa waktu lalu. Ini ditujukan pada Oracle tetapi sebenarnya tentang prinsip-prinsip dasar angka bebas celah, dan saya pikir hal yang sama berlaku di sini.
Nah, itu terjadi lagi. Seseorang telah bertanya bagaimana menerapkan persyaratan untuk menghasilkan serangkaian angka bebas celah dan segerombolan penentang telah mendatangi mereka untuk mengatakan (dan di sini saya memparafrasekan sedikit) bahwa ini akan mematikan kinerja sistem, itu jarang persyaratan yang valid , bahwa siapa pun yang menulis persyaratan adalah idiot bla bla bla.
Seperti yang saya tunjukkan di utas, terkadang merupakan persyaratan hukum asli untuk menghasilkan rangkaian angka bebas celah. Nomor faktur untuk 2.000.000+ organisasi di Inggris Raya yang terdaftar PPN (pajak penjualan) memiliki persyaratan seperti itu, dan alasannya agak jelas:bahwa hal itu membuat lebih sulit untuk menyembunyikan perolehan pendapatan dari otoritas pajak. Saya telah melihat komentar bahwa itu adalah persyaratan di Spanyol dan Portugal, dan saya tidak terkejut jika itu bukan persyaratan di banyak negara lain.
Jadi, jika kita menerima bahwa itu adalah persyaratan yang valid, dalam situasi apa deret bilangan* bebas celah menjadi masalah? Pemikiran kelompok sering kali membuat Anda percaya bahwa hal itu selalu terjadi, tetapi sebenarnya itu hanya masalah potensial dalam keadaan yang sangat khusus.
- Rangkaian angka tidak boleh ada celah.
- Beberapa proses membuat entitas yang terkait dengan nomor tersebut (mis. faktur).
- Angka harus dibuat pada saat entitas dibuat.
Jika semua persyaratan ini harus dipenuhi, maka Anda memiliki poin serialisasi dalam aplikasi Anda, dan kami akan membahasnya sebentar lagi.
Pertama, mari kita bicara tentang metode penerapan persyaratan rangkaian angka jika Anda dapat membatalkan salah satu persyaratan tersebut.
Jika rangkaian angka Anda dapat memiliki celah (dan Anda memiliki beberapa proses yang membutuhkan pembuatan nomor secara instan), maka gunakan objek Urutan Oracle. Mereka adalah kinerja yang sangat tinggi dan situasi di mana kesenjangan dapat diharapkan telah dibahas dengan sangat baik. Tidak terlalu sulit untuk meminimalkan jumlah nomor yang dilewati dengan membuat upaya desain untuk meminimalkan kemungkinan kegagalan proses antara pembuatan nomor dan melakukan transaksi, jika itu penting.
Jika Anda tidak memiliki banyak proses yang membuat entitas (dan Anda memerlukan serangkaian angka bebas celah yang harus dibuat secara instan), seperti halnya dengan pembuatan batch faktur, maka Anda sudah memiliki titik serialisasi. Itu sendiri mungkin tidak menjadi masalah, dan mungkin merupakan cara yang efisien untuk melakukan operasi yang diperlukan. Menghasilkan angka bebas celah agak sepele dalam kasus ini. Anda dapat membaca nilai maksimum saat ini dan menerapkan nilai yang bertambah ke setiap entitas dengan sejumlah teknik. Misalnya, jika Anda memasukkan kumpulan faktur baru ke dalam tabel faktur dari tabel kerja sementara, Anda mungkin:
insert into
invoices
(
invoice#,
...)
with curr as (
select Coalesce(Max(invoice#)) max_invoice#
from invoices)
select
curr.max_invoice#+rownum,
...
from
tmp_invoice
...
Tentu saja Anda akan melindungi proses Anda sehingga hanya satu instance yang dapat berjalan pada satu waktu (mungkin dengan DBMS_Lock jika Anda menggunakan Oracle), dan melindungi faktur# dengan batasan kunci unik, dan mungkin memeriksa nilai yang hilang dengan kode terpisah jika Anda benar-benar peduli.
Jika Anda tidak memerlukan pembuatan nomor secara instan (tetapi Anda membutuhkannya tanpa celah dan beberapa proses menghasilkan entitas), maka Anda dapat mengizinkan entitas dibuat dan transaksi dilakukan, dan kemudian membiarkan pembuatan nomor menjadi satu kumpulan pekerjaan. Pembaruan pada tabel entitas, atau penyisipan ke tabel terpisah.
Jadi, jika kita membutuhkan trifecta generasi instan dari serangkaian angka bebas celah dengan banyak proses? Yang bisa kita lakukan adalah mencoba untuk meminimalkan periode serialisasi dalam proses, dan saya menawarkan saran berikut, dan menerima saran tambahan (atau saran balasan tentu saja).
- Simpan nilai Anda saat ini dalam tabel khusus. JANGAN gunakan urutan.
- Pastikan bahwa semua proses menggunakan kode yang sama untuk menghasilkan angka baru dengan mengenkapsulasinya dalam suatu fungsi atau prosedur.
- Akses serial ke pembuat nomor dengan DBMS_Lock, pastikan setiap rangkaian memiliki kunci khusus sendiri.
- Tahan kunci di generator seri hingga transaksi pembuatan entitas Anda selesai dengan melepaskan kunci saat komit
- Tunda pembuatan nomor hingga saat terakhir yang memungkinkan.
- Pertimbangkan dampak kesalahan tak terduga setelah membuat nomor dan sebelum komit selesai — akankah aplikasi mundur dengan anggun dan melepaskan kunci, atau akankah menahan kunci pada generator seri hingga sesi terputus nanti? Apapun metode yang digunakan, jika transaksi gagal maka nomor seri harus “dikembalikan ke pool”.
- Dapatkah Anda merangkum semuanya dalam pemicu di tabel entitas? Bisakah Anda merangkumnya dalam tabel atau panggilan API lain yang menyisipkan baris dan melakukan penyisipan secara otomatis?
Artikel asli