نگهداری تاریخچه تغییرات اطلاعات در یک دیتابیس


چند وقتی است درگیر پروژه ای شدم که ذخیره تغییرات برخی داده های اساسی سیستم از نیازهای اصلی آن است. به این صورت که اگر اطلاعات پایه دچار تغییرات شد، باید نسخه قبلی این اطلاعات در جایی ذخیره شود که بعداً برای گزارش گیری مورد استفاده قرار گیرد. به صورت معمول و در سیستم های معمولی رسم بر این است که اگر داده ای در یک جدول دیتابیس تغییر کرد دیگر تغییر کرده و اطلاعات قبلی آن قابل ردگیری نیست. ساده ترین راه حلی که به ذهن می رسد، گرفتن نسخه پشتیبان از دیتابیس به صورت دوره ای است. اما این روش برای این کار روش مناسبی نیست. ممکن است داده ها در طول یک دوره پشتیبان گیری بارها تغییر کنند، آن وقت تنها آخرین داده های تغییر داده شده را خواهیم داشت نه کل تغییرات را. به این اضافه کنید حجم زیادی که ممکن است فایل های Backup داشته باشند.

خوشبختانه این مشکلی نیست که برای اولین بار در جهان ما با آن برخورد کرده باشیم. در سطح اینترنت بحث های زیادی در این مورد وجود دارد و راه حل های مختلفی در مورد آن ارائه شده است. قبل از ما نرم افزارهای مختلفی مثل سورس کنترل ها و وب سایت معروف Wikipedia مکانیزم هایی برای ذخیره تغییرات داده های مهم خود پیاده سازی کرده اند. پس این نیاز، به هیچ وجه نیاز غیر معقولی نیست. کاربر نیاز دارد بداند در یک بازه زمانی خاص، موجودیت مورد نظرش چه مقداری داشته است و ما باید این امکان را برایش پیاده سازی کنیم.

یک روش طراحی دیتابیس به نام Point in Time Architecture وجود دارد که به صورت مخصوص برای حل چنین مشکلی بکار می رود. این روش طراحی تضمین می کند که همیشه تصویری از اطلاعات گذشته را در خود نگهداری کند تا هر گاه نیازی به اطلاعات گذشته بود، در اختیار ما قرار بدهد. در این روش طراحی هیچ گاه رکوردها به صورت فیزیکی آپدیت یا حذف نخواهند شد و فقط flagهایی برای علامت گذاری بر روی رکوردهای تغییر داده شده قرار می گیرد. در این روش، ساختار دیتابیس باید طوری طراحی شود که دیتابیس به ازای هر رکورد بتواند به سئوالات زیر پاسخ دهد :

  • رکورد چه موقع و توسط چه کسی Insert شد؟
  • رکورد چه موقع و توسط چه کسی Update شد؟
  • در یک تاریخ خاص اطلاعات رکورد چگونه بوده است؟

برای پاسخ به این سئوالات باید یکسری فیلد کنترلی داشته باشیم :

  • CreatedDate : تاریخ ساخته شدن رکورد برای اولین بار
  • ModifiedDate : تاریخی که اطلاعات رکورد تغییر داده می شوند
  • UserID : کاربری که اطلاعات را تغییر می دهد

tuple versioningبرای پیاده سازی چنین روشی می توان دو جور عمل کرد. روش اول این است که هر گاه کاربر خواست اطلاعات را تغییر دهد، به جای عمل Update ما یک عمل Insert انجام دهیم و اطلاعات قبلی را با یک فیلد کنترلی آرشیو شده محسوب کنیم. در این روش باید یک فیلد ModifiedDate داشت که هر زمان رکورد ویرایش شد مقداردهی شود. رکوردی که فیلد ModifiedDate آن برابر null باشد، رکورد جاری ما خواهد بود. این روش Tuple Versioning نام دارد که مکانیزمی برای ذخیره حالت فعلی یک رکورد به علاوه حالت های گذشته آن در یک جدول است. این روش برای زمانی که امکان تغییرات در رکوردهای جدول کم باشد بسیار مناسب است. در صورت زیاد بودن امکان تغییرات یک رکورد، باعث حجیم شدن جدول می شود و کارایی را پایین می آورد.

روش دوم ایجاد یک جدول History برای هر جدولی است که می خواهیم تغییرات داده های آن را پیگیری کنیم. به این صورت که برای هر جدول که نیاز به ذخیره تغییرات آن داریم یک جدول History می سازیم که هنگام تغییر هر یک از رکوردهای جدول اصلی، یک رکورد به جدول History متناظر آن اضافه می کنیم و یکسری اطلاعات اضافه مثل تاریخ تغییر و کاربر تغییر دهنده را همراه با آن ذخیره می کنیم.

History Tableهمانطور که در شکل بالا می بینید، برای نگهداری تاریخچه تغییرات قیمت یک محصول، یک Table جداگانه میسازیم و چند فیلد کنترلی به آن اضافه می کنیم. در اینجا فیلدهای ModifiedDate تاریخ تغییر قیمت محصول، SalesPrice قیمت محصول در زمان تغییر و UserID مشخص کننده کاربری است که قیمت محصول را تغییر داده است.

مزیت اینگونه طراحی دیتابیس در هنگان گزارش گیری مشخص می شود. با این طراحی، کاربر می تواند تمام تغییرات داده های مهم خود در طی زمان های مختلف را مشاهده کند.

Advertisements