Unique Key yang Tidak Unique

Ini adalah salah satu tantangan kami secara teknis berkaitan dengan database. Suatu saat kami mencatatkan header transaksi dengan autogenerated number yang merupakan fitur natif dari database. Field bertipe big integer ini menjadi Primary Key untuk relasi ke tabel detail atau tabel lain yang berelasi. Semua baik-baik saja.

Keadaan berubah saat ada beberapa divisi memerlukan penomeran yang lebih mudah dibaca (readable). Beberapa divisi ini menginginkan penggunaan prefix untuk membedakan dengan transaksi dari divisi lain. Misalnya divisi penjualan umum menggunakan prefix “FU”, penjualan rawat inap dengan prefix “FI” dan penjualan rawat jalan dengan “FJ”. Ditambahkan lagi prefix berdasarkan waktu transaksi sehingga formatnya menjadi “FJ1208xxxxx” untuk penjualan rawat jalan.

Dengan penomeran model begini user bisa dengan cepat mengidentifikasi transaksi tersebut dari divisi mana dan terjadi pada tahun dan bulan berapa.

Beberapa divisi lain juga menginginkan hal yang sama, misalnya divisi Laboratorium dan Radiologi. Sedangkan divisi lain tidak memerlukan fitur penomeran readable ini. Jadi divisi lain tetap menggunakan Primary Key. Sedangkan beberapa divisi menggunakan TrxID.

Masalah ini diselesaikan secara teknis dengan menambahkan 1 field pendamping Primary Key, yaitu field “TrxID” yang diharapkan dapat menjadi Primary Key ke-2 yang harus bisa unik tetapi untuk kebanyakan departemen berisi kosong (NULL). Jadi harus unik tetapi bisa kosong (tidak unik).

Request ini diselesaikan secara softwariah. Software akan mencari nomer terakhir TrxID sesuai dengan prefix yang dimaksud kemudian menambahkan 1. Nampaknya masalah terselesaikan.

Tapi ternyata tidak!

Pada suatu waktu ada 2 user yang melakukan transaksi secara bersamaan dan mendapatkan nomer TrxID yang sama. Dan karena field ini bukan Primary Key atau Unique Index yang sesungguhnya dan tidak ada constraint secara native, maka kedua transaksi ini bisa disimpan dengan nomer TrxID yang sama.

Ini menjadi masalah besar. Walau pun detail transaksi tetap mengacu kepada Primary Key yang sesungguhnya, tapi user menjadi bingung dengan keberadaan 2 TrxID yang sama! Padahal konsistensi relasi header dan detail transaksi tetap terjaga dengan penggunaan Primary Key yang sesungguhnya. Sebenarnya 2 transaksi ini tetap 2 transaksi yang berbeda.

Pernah ada yang mengalami hal yang sama? Bagaimana pemecahan untuk mencegah hal ini? Yang jelas field TrxID ini bisa berisi kosong jika divisi lain tidak membutuhkan penomeran yang readable. Jadi field ini pun tidak bisa dibikin unique secara native di database.

Ternyata tidak sesederhana itu!

Iklan

Tentang Emanuel Setio Dewo

Tumbuh, Berkembang, Berbuah...
Pos ini dipublikasikan di Personal dan tag , , , , . Tandai permalink.

12 Balasan ke Unique Key yang Tidak Unique

  1. Agung Rangga berkata:

    ayo semangat kak~ 😀

  2. Lidya berkata:

    aku tunggu hasilnya aja deh mas hehehe malas mikir

  3. moonray berkata:

    Ditambahkan lagi prefix berdasarkan waktu transaksi sehingga formatnya menjadi “FJ1208xxxxx”
    ====
    xxxxx dibelakang itu rumusnya apa mas? kalau mau di bikin lebih susah untuk sama, isi aja dengan timestamp sampai ke milidetik saat di generate, jadi lebih panjang memang, tapi akan lebih “unique”

    • xxxxx = nomer urut 5 digit. Misalnya: FJ120800001, FJ120800002, dst…
      Wah kalau sampai ke timestamp bisa pusing semua, hehehe…
      Tapi tetap bisa terjadi jika 2 user input bareng sampe ke detik yg sama, hiks…
      Terima kasih masukannya.

  4. moonray berkata:

    hmm kalau mau lebih simple lagi, sebelum insert, lakukan logic pengecekan key itu.. pada saat key yang akan di insertkan ternyata sudah di commit ke database(artinya sudah dipakai oleh orang lain) ambil key terbesar terakhir di database, tambahkan satu lalu insert he he he.. memang jadi membuat lebih lama prosesnya… nanti kalau kepikiran cara lain lagi, saya tulis disini

    • Algoritma yg sekarang sih begini:

      1. Cek nomer terakhir transaksi (sesuai prefix)
      2. Tambahkan 1
      3. Simpan transaksi ke DB dgn nomer tsb

      Kalau sebelum simpan ngecek lagi nomer tsb, kayaknya bakal memakan resources server. Karena jika ternyata nomer tsb sudah ada, maka akan kembali ke langkah no. 1. Bisa terjadi rekursif sih.

      Ide lain sih dgn mekanisme “reserved number”. Ada sebuah tabel yg menyimpan nomer terakhir sesuai prefix. Setiap tambah transaksi akan me-reserve nomer baru. Tetapi berpotensi user reserved nomer yg sama juga. Kecuali tabel tersebut di-lock.

      Ditunggu ide lain ya, Mas. Terima kasih

  5. moonray berkata:

    eh jadi kepikiran lagi, apakah key ini ditampilkan di form pada saat sebelum insert? pertanyaan mendasar sih sebelum ke solusi harusnya.. karena kalau di hidden akan lebih mudah, dan ditampilkan saat sudah masuk ke db… kalau di tampilkan sebelum di insert, dan di hapal sama user.. baru perlu trik lain lagi 🙂

    sorry lagi kumat iseng untuk alpro nya 🙂 jadi perlu tahu case detail nya untuk bisa solve suatu problem 🙂

  6. moonray berkata:

    berarti jawabannya harusnya TIdak ditampilkan, karena yang muncul isinya AUTO 🙂 setelah disimpan baru tampil he he he, ..
    nanti kalau lagi agak lowong saya carikan idenya.. ide pake table reserved tadi oke juga, hanya saja triggernya itu harusnya button create transaction, jadi pada saat user klik create transaction, langsung insertkan satu nomer dan pakai nomer itu. Kenapa button create transaction? karena secara system timestamp sampai MILIdetik, harusnya setiap transaksi pasti unik 🙂

    • Betul, Mas.

      Kalau pakai tabel reserved harus lock table supaya tidak double. Sayangnya user kami banyak & transaksinya banyak juga sehingga sulit jika menggunakan lock table.

      Kalau saat create transaction sdh membuat nomer transaksi, kemudian user membatalkannya, maka banyak nomer transaksi yg bolong2 dan kesannya lompat2, hiks…

      Baik mas, saya tunggu ide2nya. Terima kasih ya

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s