Cara memiliki riwayat perubahan entri basis data

21

Apa cara untuk memungkinkan versi entri basis data (data)?

Pikirkan kemampuan sistem manajemen konten untuk mengembalikan kembali perubahan artikel.

Apa pro / kontra mereka?

matcauthon
sumber
1
Apa yang sebenarnya ingin Anda versi? Skema atau data?
tdammers
1
Saya ingin versi datanya. Untuk tetap pada contoh cms, katakanlah versi artikel .
matcauthon
Anda mungkin ingin melihat ke Datomic.
dan_waterworth

Jawaban:

19

Pada dasarnya ada dua pendekatan: tabel audit, dengan semua nilai sebelumnya disimpan di dalamnya, atau sertakan tanggal mulai / berakhir sebagai bagian dari tabel, dan semua pembaruan membuat catatan baru sambil menutup yang lama.

Pembaruan: SQL SERVER 2016 mendukung ini sebagai pola desain / jenis tabel - https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2017

jmoreno
sumber
4
Jadi pendekatan pertama mungkin lebih terukur. Karena data "yang diarsipkan" akan jarang diakses, desain basis data dapat dioptimalkan. Dan meja kerjanya tetap kecil. Tergantung pada kerumitannya, seharusnya hanya mungkin untuk menyimpan perbedaan. Apakah disarankan untuk menggunakan pola kenang - kenangan ?
matcauthon
1
Itu akan tergantung pada penggunaan Anda, mungkin cukup menggunakan pemicu untuk mengisi tabel / s dan kemudian menyediakan cara memilih apa dan seberapa jauh untuk mengembalikan.
jmoreno
Anda memiliki kesalahan ketik dalam jawaban Anda (pola pola seharusnya)
geocodezip
7

Satu ide adalah menggunakan "Masukkan-Hanya Basis Data". Ide dasarnya adalah bahwa Anda tidak pernah menghapus atau memperbarui data pada satu baris .

Setiap tabel yang harus dilacak akan memiliki dua datetimekolom fromdan to. Mereka mulai dengan nilai NULLdi masing-masing (awal waktu hingga akhir waktu). Ketika Anda perlu "mengubah" baris Anda menambahkan baris baru, dan pada saat yang sama Anda memperbarui todi baris sebelumnya ke Nowdan fromdi baris yang Anda tambahkan Now.

Untuk info lebih rinci, lihat:

Teknik ini disebut AuditTrailuntuk mengelola data lawas, dan itu agak menyimpan sejarah perubahan.

Sepertinya pertanyaan seperti ini sudah diposting:

Yusubov
sumber
Sayangnya pertanyaan itu tampaknya telah dihapus :(
Douglas Gaskell
Tidak masalah, ini tautannya . Saran desain bagus lainnya dalam tautan
Yusubov
2

Saya pikir Anda dapat menggunakan pemicu untuk setiap tabel dan mempertahankan data dalam _history (atau Anda dapat memberikan nama apa pun) dan pada setiap sisipan, perbarui, hapus pada tabel utama akan memicu pemicu Anda dan Anda dapat menyimpan detailnya di tabel ini. Mekanisme pemicu juga tersedia dengan database SQLite jika Anda menggunakannya.

Mekanisme ini berguna untuk proyek-proyek besar juga. Dalam tabel ini Anda bisa mencatat informasi pengguna yang telah membuat perubahan bersama dengan cap waktu perubahan. Anda kemudian dapat mengembalikan tabel ke pencocokan cap waktu dengan kebutuhan Anda.

Setiap Database memiliki cara sendiri untuk menulis dan memicu kode. Jika Anda menggunakan SQLite, kunjungi SQLite.org untuk sintaksisnya. Untuk basis data lain, Anda dapat mengunjungi situs resminya.

SME
sumber
1

Anda mungkin mengetahui mesin Sqlite db. Seluruh db disimpan dalam satu file. Api juga mendukung sistem file virtual sehingga pada dasarnya Anda dapat mengatur penyimpanan di mana saja dan dengan format apa pun, cukup menanggapi operasi baca dan tulis pada offset file tertentu. Kemungkinan aplikasi untuk ini bisa berupa enkripsi, kompresi, dan sebagainya. Bagian terbaiknya adalah layer container seharusnya tidak tahu apa-apa tentang basis data, format file sql atau sqlite, cukup patuhi callback xRead dan xWrite.

Salah satu idenya adalah menerapkan fitur mesin waktu. Jadi setiap operasi xWrite menyimpan setiap segmen yang akan ditimpa dalam "undo" history dan pengguna dapat memilih tanggal di masa lalu untuk melihat apa yang terkandung dalam db (mungkin mode read-only). Saya belum memiliki contoh kerja (ada diskusi tentang hal itu di milis sqlite), tetapi mungkin mesin lain menyediakan API VFS sehingga hal serupa mungkin terjadi. Dan begitu itu diterapkan, itu harus kompatibel dengan struktur database dari kompleksitas apa pun.

Maksee
sumber
Menurut Anda, apakah pendekatan ini dapat diskalakan untuk proyek yang lebih besar?
matcauthon
Saya pikir ini bisa menambah overhead data besar untuk perubahan data besar (jelas karena setiap perubahan harus disimpan, meskipun kompresi untuk versi yang lebih lama dapat membantu). Terlepas dari itu dari sudut Anda skema Anda, selama itu berfungsi untuk dua tabel, itu berfungsi untuk dua puluh.
Maksee
1

Metode yang kami gunakan untuk memvariasikan entri basis data adalah dengan menggunakan tabel audit. Tabel memiliki skema di sepanjang garis:

Seq      - Int      ' Unique identifier for this table
Event    - Char     ' Insert / Update / Delete
TblName  - Char     ' Table that had field value changed
FldName  - Char     ' Field that was changed
KeyValue - Char     ' delimited list of values for fields that make up the PK of table changed
UsrId    - Char     ' User who made the change
OldValue - Char     ' Old value (converted to character)
NewValue - Char     ' New value (converted to character)
AddTs    - DateTime ' When the change was made

Kami kemudian memiliki pemicu pada Sisipkan / Perbarui / Hapus tabel yang ingin kami lacak.

Pro:

  • Semua data dalam satu tabel
  • Dapat diatur untuk melacak semua bidang atau bidang tertentu dalam sebuah tabel
  • Mudah menampilkan versi pada setiap bidang untuk tabel

Kekurangan:

  • Memiliki semua informasi audit dalam satu tabel menghasilkan sejumlah besar catatan
  • Banyak pemicu yang dibutuhkan
pengantin
sumber
0

Saya sedang melakukan versi ini sekarang. untuk setiap catatan saya memiliki Tanggal yang Dimasukkan, Tanggal yang dimodifikasi dan dan bendera boolean Rekaman Aktif. Untuk penyisipan awal, tanggal yang Dimasukkan dan Dimodifikasi disetel ke Sekarang () (Contoh ini di Access) dan bendera catatan Aktif diatur ke true. kemudian jika saya mengubah catatan itu saya menyalin semuanya ke catatan baru, mengubah bidang yang diubah pengguna, saya meninggalkan tanggal Sisipkan sama dengan yang asli dan mengubah tanggal Dimodifikasi ke Sekarang (). Saya kemudian membalik bendera Rekaman Aktif dari catatan asli ke falsedan catatan baru ke true. Saya juga memiliki bidang untuk ModifiedRecordsParentID tempat saya menyimpan identitas catatan asli.

Kemudian Jika saya perlu melakukan query, saya hanya dapat mengembalikan record di mana ActiveRecord = truedan saya hanya akan mendapatkan informasi terbaru.

Brad
sumber
Tidak perlu untuk ActiveRecordbendera. Baris MAX (*) harus selalu menjadi catatan saat ini. Mengembalikan ke versi sebelumnya cukup menyisipkan baris kata ke dalam tabel lagi.
balikkan
Saya tidak yakin bagaimana membuat karya terpilih, tetapi sekarang setelah Anda memanggil ini, saya sedang memikirkannya dan punya ide, hmmmm
Brad
Biasanya MAX (nama_kolom) memilih nilai terbesar di kolom tabel. Untuk memilih seluruh baris, sederhana select top 1 order by id descendingakan dilakukan.
balikkan
Ya, itu berfungsi untuk satu catatan tunggal tetapi meja saya adalah kumpulan catatan anak yang perlu dipilih sekaligus tetapi bisa dimodifikasi secara individual. Hanya sedikit lebih kompleks.
Brad