Saya menulis skema untuk database bank sederhana. Berikut spesifikasi dasar:
- Basis data akan menyimpan transaksi terhadap pengguna dan mata uang.
- Setiap pengguna memiliki satu saldo per mata uang, sehingga setiap saldo hanyalah jumlah dari semua transaksi terhadap pengguna dan mata uang tertentu.
- Saldo tidak boleh negatif.
Aplikasi bank akan berkomunikasi dengan database secara eksklusif melalui prosedur tersimpan.
Saya berharap database ini menerima ratusan ribu transaksi baru per hari, serta menyeimbangkan kueri pada tingkat yang lebih tinggi. Untuk melayani saldo dengan sangat cepat, saya perlu melakukan pra-agregat. Pada saat yang sama, saya perlu menjamin bahwa saldo tidak pernah bertentangan dengan riwayat transaksinya.
Pilihan saya adalah:
Memiliki
balances
tabel terpisah dan lakukan salah satu dari yang berikut:Terapkan transaksi ke tabel
transactions
danbalances
. GunakanTRANSACTION
logika di lapisan prosedur tersimpan saya untuk memastikan bahwa saldo dan transaksi selalu sinkron. (Didukung oleh Jack .)Terapkan transaksi ke
transactions
tabel dan miliki pemicu yang memperbaruibalances
tabel untuk saya dengan jumlah transaksi.Terapkan transaksi ke
balances
tabel dan miliki pemicu yang menambahkan entri baru ditransactions
tabel untuk saya dengan jumlah transaksi.
Saya harus mengandalkan pendekatan berbasis keamanan untuk memastikan tidak ada perubahan yang dapat dilakukan di luar prosedur yang tersimpan. Kalau tidak, misalnya, beberapa proses dapat langsung memasukkan transaksi ke dalam
transactions
tabel dan di bawah skema1.3
saldo yang relevan akan tidak sinkron.Memiliki tampilan yang
balances
diindeks yang mengagregasi transaksi dengan tepat. Saldo dijamin oleh mesin penyimpanan untuk tetap selaras dengan transaksi mereka, jadi saya tidak perlu bergantung pada pendekatan berbasis keamanan untuk menjamin ini. Di sisi lain, saya tidak bisa memaksakan saldo menjadi non-negatif lagi karena pandangan - bahkan pandangan yang diindeks - tidak dapat memilikiCHECK
kendala. (Didukung oleh Denny .)Hanya punya
transactions
meja tetapi dengan kolom tambahan untuk menyimpan saldo efektif setelah transaksi itu dijalankan. Dengan demikian, catatan transaksi terbaru untuk pengguna dan mata uang juga mengandung saldo mereka saat ini. (Disarankan di bawah oleh Andrew ; varian yang diajukan oleh garik .)
Ketika saya pertama kali ditangani masalah ini, saya membaca ini dua diskusi dan memutuskan pada pilihan 2
. Untuk referensi, Anda dapat melihat implementasi sederhana di sini .
Sudahkah Anda merancang atau mengelola basis data seperti ini dengan profil beban tinggi? Apa solusi Anda untuk masalah ini?
Apakah Anda pikir saya sudah membuat pilihan desain yang tepat? Apakah ada sesuatu yang harus saya ingat?
Misalnya, saya tahu perubahan skema pada
transactions
tabel akan mengharuskan saya membangun kembalibalances
tampilan. Sekalipun saya mengarsipkan transaksi untuk menjaga basis data kecil (misalnya dengan memindahkannya ke tempat lain dan menggantinya dengan transaksi ringkasan), harus membangun kembali pandangan dari puluhan juta transaksi dengan setiap pembaruan skema mungkin akan berarti lebih banyak downtime per penyebaran.Jika tampilan yang diindeks adalah cara untuk pergi, bagaimana saya bisa menjamin bahwa tidak ada saldo negatif?
Pengarsipan transaksi:
Biarkan saya menguraikan sedikit tentang pengarsipan transaksi dan "ringkasan transaksi" yang saya sebutkan di atas. Pertama, pengarsipan teratur akan menjadi kebutuhan dalam sistem beban tinggi seperti ini. Saya ingin menjaga konsistensi antara saldo dan riwayat transaksi mereka sambil memungkinkan transaksi lama dipindahkan ke tempat lain. Untuk melakukan ini, saya akan mengganti setiap kumpulan transaksi yang diarsipkan dengan ringkasan jumlah mereka per pengguna dan mata uang.
Jadi, misalnya, daftar transaksi ini:
user_id currency_id amount is_summary
------------------------------------------------
3 1 10.60 0
3 1 -55.00 0
3 1 -12.12 0
diarsipkan dan diganti dengan ini:
user_id currency_id amount is_summary
------------------------------------------------
3 1 -56.52 1
Dengan cara ini, keseimbangan dengan transaksi yang diarsipkan mempertahankan riwayat transaksi yang lengkap dan konsisten.