ऑडिट लॉगिंग के लिए डेटाबेस डिजाइन


151

हर बार मुझे एक नया डेटाबेस डिजाइन करने की आवश्यकता होती है, मैं यह सोचने में काफी समय बिताता हूं कि परिवर्तनों का ऑडिट लॉग रखने के लिए मुझे डेटाबेस स्कीमा कैसे सेट करना चाहिए।

इस बारे में कुछ प्रश्न पहले ही यहां पूछे जा चुके हैं, लेकिन मैं इस बात से सहमत नहीं हूं कि सभी परिदृश्यों के लिए एक ही सर्वोत्तम तरीका है:

मैंने इस दिलचस्प लेख को एक लॉग ऑफ़ डेटाबेस चेंजेज बनाए रखने पर ठोकर खाई है जो प्रत्येक दृष्टिकोण के समर्थक और विपक्ष को सूचीबद्ध करने की कोशिश करता है। यह बहुत अच्छी तरह से लिखा गया है और दिलचस्प जानकारी है, लेकिन इसने मेरे फैसलों को और भी कठिन बना दिया है।

मेरा सवाल यह है कि: क्या कोई संदर्भ है जो मैं उपयोग कर सकता हूं, शायद एक किताब या निर्णय के पेड़ की तरह कुछ है जिसे मैं यह तय करने के लिए संदर्भित कर सकता हूं कि मुझे किस तरह कुछ इनपुट चर पर आधारित होना चाहिए, जैसे:

  • डेटाबेस स्कीमा की परिपक्वता
  • लॉग को कैसे क्वियर किया जाएगा
  • संभावना है कि यह रिकॉर्ड को फिर से बनाने की आवश्यकता होगी
  • क्या अधिक महत्वपूर्ण है: प्रदर्शन लिखना या पढ़ना
  • लॉग किए जा रहे मानों की प्रकृति (स्ट्रिंग, संख्या, बूँदें)
  • संग्रहण स्थान उपलब्ध है

मैं जो दृष्टिकोण जानता हूं वे हैं:

1. निर्मित और संशोधित तिथि और उपयोगकर्ता के लिए कॉलम जोड़ें

तालिका उदाहरण:

  • आईडी
  • मान_1
  • मान_2
  • VALUE_3
  • रचना तिथि
  • संशोधित तिथि
  • के द्वारा बनाई गई
  • द्वारा संशोधित

प्रमुख विपक्ष: हम संशोधनों का इतिहास खो देते हैं। कमिट के बाद रोलबैक नहीं कर सकते।

2. केवल टेबल डालें

तालिका उदाहरण :

  • आईडी
  • मान_1
  • मान_2
  • VALUE_3
  • से
  • सेवा
  • हटा दिया गया (बूलियन)
  • उपयोगकर्ता

प्रमुख विपक्ष: विदेशी चाबियों को कैसे रखें? विशाल स्थान की आवश्यकता

3. प्रत्येक तालिका के लिए एक अलग इतिहास तालिका बनाएं

इतिहास तालिका उदाहरण:

  • आईडी
  • मान_1
  • मान_2
  • VALUE_3
  • VALUE_4
  • उपयोगकर्ता
  • हटा दिया गया (बूलियन)
  • टाइमस्टैम्प

प्रमुख विपक्ष: सभी अंकेक्षित तालिकाओं की नकल करने की आवश्यकता। यदि स्कीमा बदलता है तो सभी लॉग को माइग्रेट करने की भी आवश्यकता होगी।

4. सभी तालिकाओं के लिए एक समेकित इतिहास तालिका बनाएं

इतिहास तालिका उदाहरण:

  • तालिका नाम
  • मैदान
  • उपयोगकर्ता
  • नया मूल्य
  • हटा दिया गया (बूलियन)
  • टाइमस्टैम्प

प्रमुख विपक्ष: क्या मैं आसानी से जरूरत पड़ने पर रिकॉर्ड्स (रोलबैक) को फिर से बना पाऊंगा? New_value कॉलम को एक विशाल स्ट्रिंग होने की आवश्यकता है ताकि यह सभी विभिन्न स्तंभ प्रकारों का समर्थन कर सके।



1
और तालिकाओं के बजाय इतिहास डेटाबेस का उपयोग करने के बारे में क्या?
Jowen

हो सकता है कि आप github.com/airblade/paper_trail
zx1986

क्या सभी बुरे (आवश्यक) प्रश्नों को लॉग करना एक बुरा विचार है क्योंकि यह है?
दिनुशन

जवाबों:


87

कुछ विकी प्लेटफार्मों द्वारा उपयोग की जाने वाली एक विधि पहचान डेटा और जिस सामग्री की आप ऑडिटिंग कर रहे हैं, उसे अलग करना है। यह जटिलता जोड़ता है, लेकिन आप पूर्ण रिकॉर्ड के ऑडिट ट्रेल के साथ समाप्त होते हैं, न कि केवल उन फ़ील्ड्स की सूची जिन्हें संपादित किया गया था जो आपको उपयोगकर्ता को यह बताने के लिए मैश करना होगा कि पुराना रिकॉर्ड कैसा दिखता था।

उदाहरण के लिए, यदि आपके पास बिक्री सौदों को ट्रैक करने के लिए अवसर नामक एक तालिका है, तो आप वास्तव में दो अलग-अलग तालिकाएँ बनाएंगे:

अवसर
अवसर_संबंधी (या ऐसा कुछ)

अवसर तालिका जानकारी आप और विशिष्ट रूप से रिकॉर्ड की पहचान करने का उपयोग करें प्राथमिक कुंजी आप अपने विदेशी कुंजी संबंधों के लिए संदर्भ था घर होगा होगा। Opportunities_Content तालिका सभी क्षेत्रों के लिए अपने उपयोगकर्ताओं को बदल सकते हैं पकड़ होगा और जिसके लिए आप एक लेखापरीक्षा निशान रखना चाहते हैं। सामग्री तालिका में प्रत्येक रिकॉर्ड में अपना स्वयं का पीके और संशोधित-द्वारा और संशोधित-तिथि डेटा शामिल होगा। अवसर तालिका जब मुख्य रिकॉर्ड मूल रूप से बनाया गया था और किसके द्वारा पर और साथ ही वर्तमान संस्करण के लिए एक संदर्भ जानकारी शामिल है।

यहाँ एक सरल उदाहरण दिया गया है:

CREATE TABLE dbo.Page(  
    ID int PRIMARY KEY,  
    Name nvarchar(200) NOT NULL,  
    CreatedByName nvarchar(100) NOT NULL, 
    CurrentRevision int NOT NULL, 
    CreatedDateTime datetime NOT NULL

और सामग्री:

CREATE TABLE dbo.PageContent(
    PageID int NOT NULL,
    Revision int NOT NULL,
    Title nvarchar(200) NOT NULL,
    User nvarchar(100) NOT NULL,
    LastModified datetime NOT NULL,
    Comment nvarchar(300) NULL,
    Content nvarchar(max) NOT NULL,
    Description nvarchar(200) NULL

मैं शायद पृष्ठ तालिका से एक बहु-स्तंभ कुंजी सामग्री तालिका का PK बनाऊंगा और पुनरीक्षण प्रदान किया गया था, जिसमें संशोधन एक पहचान प्रकार था। आप संशोधन कॉलम का उपयोग FK के रूप में करेंगे। फिर आप इस तरह से जोइनिंग द्वारा समेकित रिकॉर्ड को खींचते हैं:

SELECT * FROM Page
JOIN PageContent ON CurrentRevision = Revision AND ID = PageID

वहाँ कुछ त्रुटियाँ हो सकती हैं ... यह मेरे सिर के ऊपर है। यह आपको एक वैकल्पिक पैटर्न का विचार देना चाहिए, यद्यपि।


10
ऑडिट अच्छे दृष्टिकोण के संदर्भ में, लेकिन उत्पादन के लिए डेटाबेस में प्रत्येक तालिका के लिए एक अलग ऑडिट टेबल विकसित करने में बहुत समय लगेगा, प्रत्येक तालिका के लिए ट्रिगर को लिखना, परिवर्तनों को कैप्चर करना और उसे ऑडिट टेबल पर लिखना। इसके अलावा सभी तालिकाओं के लिए एकल ऑडिट रिपोर्ट विकसित करने में एक बड़ी चुनौती है क्योंकि प्रत्येक ऑडिट टेबल संरचना में अलग है।
असीम-इशाक

11
यदि प्रत्येक तालिका के लिए स्क्रिप्ट लिखना और उसे बनाए रखना एक संगठन के लिए एक चिंता का विषय है जो एक ऑडिट किए गए डेटाबेस को प्रबंधित करने का इरादा रखता है तो मैं स्वाभाविक रूप से सिफारिश करूंगा कि वे या तो एक अनुभवी डीबीए या उच्च-लचीले और बहुत अनुभवी सॉफ्टवेयर-इंजीनियर को पर्याप्त अनुभव के साथ ऑडिट डेटाबेस बनाने के लिए किराए पर लें। ।
हरदौरी

1
क्या यह सही है कि PageContent.PageIDएफके टू है Page.IDऔर Page.CurrentRevisionएफके टू है PageContent.Revision? क्या यह निर्भरता वास्तव में परिपत्र है?

2
मैंने नीचे मतदान किया है क्योंकि यह उन विकल्पों को संबोधित नहीं करता है जिनका उल्लेख किया गया है। यह एक और विकल्प देता है जो बहुत विशिष्ट उपयोग के मामले के लिए बहुत विशिष्ट समाधान है। लेकिन मुझे सुझाए गए डिज़ाइन की
खूबियाँ दिखती हैं

1
मैं उन बहुत कम क्षेत्रों के बारे में सोच सकता हूं जिन्हें मैं विश्वास के साथ कह सकता था कि प्रत्येक इकाई के लिए "मुख्य" तालिकाओं के सभी परिवर्तन नहीं होंगे id, revision_id; जंक्शन टेबल का अधिक, वास्तव में। यह मुझे थोड़ा बदबूदार लगता है। ओपी के दृष्टिकोण 3 (ऑडिट टेबल की इतिहास तालिका) में इसका क्या लाभ है?
केनमोर

14

यदि आप SQL Server 2008 का उपयोग कर रहे हैं, तो आपको संभवतः डेटा कैप्चर को बदलने पर विचार करना चाहिए। यह 2008 के लिए नया है और आपको काफी काम बचा सकता है।


यहाँ SQL 2012 परिवर्तन ट्रैकिंग जानकारी के लिए लिंक है। msdn.microsoft.com/en-us/library/bb933994.aspx +1 कार्यक्षमता में निर्मित का उपयोग करने के लिए, कोई बिंदु पहिया का पुन: आविष्कार नहीं करता है।
क्रिस

4
@ क्रिस क्या आपने कभी इसका इस्तेमाल किया है? वास्तव में, यह सब कुछ ट्रैक करता है ... लेकिन इसके बारे में उपयोगी जानकारी प्राप्त करने में सक्षम होना एक पूरी कहानी है। मेरी बाइक के लिए ट्रैक्टर के पहिये का उपयोग नहीं कर सकते।
जोवेन

यह वास्तव में होता भयानक किया गया है। लेकिन अगर आपको केवल मेरी तरह SQL सर्वर का मानक संस्करण मिला है , तो आप भाग्य से बाहर हैं: "बदलें डेटा कैप्चर केवल एंटरप्राइज़ , डेवलपर और एंटरप्राइज़ मूल्यांकन संस्करणों में उपलब्ध है"।
ब्रैड टुरेक

6

मुझे किसी संदर्भ का पता नहीं है, लेकिन मुझे यकीन है कि किसी ने कुछ लिखा है।

हालांकि, अगर उद्देश्य बस एक रिकॉर्ड है कि क्या हुआ है - ऑडिट लॉग का सबसे विशिष्ट उपयोग - तो बस सब कुछ क्यों न रखें:

timestamp
username
ip_address
procedureName (if called from a stored procedure)
database
table
field
accesstype (insert, delete, modify)
oldvalue
newvalue

संभवतः यह एक ट्रिगर द्वारा बनाए रखा गया है।


मुझे डेटाबेस सर्वर के भीतर इसे प्राप्त करने के किसी भी तरीके का पता नहीं है, लेकिन निश्चित रूप से यह बाहर से आसानी से किया जा सकता है।
wallyk

5
यह मुझे लगता है कि यह मूल प्रश्न में दिखाए गए 4 वें विकल्प के समान डिज़ाइन पैटर्न है।
गिवंसे

3

हम ब्लॉगिंग एप्लिकेशन के लिए एक छोटा सा उदाहरण डेटाबेस बनाएंगे। दो तालिकाओं की आवश्यकता है:

blog: एक विशिष्ट पोस्ट आईडी, शीर्षक, सामग्री और हटाए गए ध्वज को संग्रहीत करता है। audit: एक रिकॉर्ड आईडी, ब्लॉग पोस्ट आईडी, परिवर्तन प्रकार (NEW, EDIT या DELETE) और उस परिवर्तन की तारीख / समय के साथ ऐतिहासिक परिवर्तनों का एक मूल सेट संग्रहीत करता है। निम्न SQL blogहटाए गए स्तंभ को बनाता है और अनुक्रमित करता है:

CREATE TABLE `blog` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
    `title` text,
    `content` text,
    `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    KEY `ix_deleted` (`deleted`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Blog posts';

निम्न SQL auditतालिका बनाता है । सभी कॉलम इंडेक्स किए गए हैं और ऑडिट के लिए एक विदेशी कुंजी को परिभाषित किया गया है। blog_id जो blog.id को संदर्भित करता है। इसलिए, जब हम भौतिक रूप से एक ब्लॉग प्रविष्टि को हटाते हैं, तो यह पूर्ण ऑडिट इतिहास भी हटा दिया जाता है।

CREATE TABLE `audit` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
    `blog_id` mediumint(8) unsigned NOT NULL,
    `changetype` enum('NEW','EDIT','DELETE') NOT NULL,
    `changetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `ix_blog_id` (`blog_id`),
    KEY `ix_changetype` (`changetype`),
    KEY `ix_changetime` (`changetime`),
    CONSTRAINT `FK_audit_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `blog` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

2

मुझे लगता है कि निर्णय वृक्ष जैसा कुछ नहीं है। चूंकि कुछ पेशेवरों और विपक्ष (या आवश्यकताएं) वास्तव में गिनने योग्य नहीं हैं। आप उदाहरण के लिए परिपक्वता को कैसे मापते हैं?

तो बस अपने ऑडिट लॉगिंग के लिए अपनी व्यावसायिक आवश्यकताओं को पूरा करें। भविष्यवाणी करने की कोशिश करें कि भविष्य में ये आवश्यकताएं कैसे बदल सकती हैं और आपकी तकनीकी आवश्यकताएं उत्पन्न कर सकती हैं। अब आप इसे पेशेवरों और विपक्षों से तुलना कर सकते हैं और सही / सर्वोत्तम विकल्प चुन सकते हैं।

और आश्वस्त रहें, इससे कोई फर्क नहीं पड़ता कि आप कैसे निर्णय लेते हैं, हमेशा कोई होगा जो आपको लगता है कि आपने गलत निर्णय लिया है। हालांकि, आपने अपना होमवर्क किया और आप अपने फैसले को सही ठहराते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.