संस्करण डेटाबेस की सामग्री को नियंत्रित करता है


16

मैं एक वेब परियोजना पर काम कर रहा हूं जिसमें उपयोगकर्ता-संपादन योग्य सामग्री शामिल है, और मैं वास्तविक सामग्री के संस्करण-ट्रैकिंग करने में सक्षम होना चाहता हूं, जो एक डेटाबेस में रहता है। मूल रूप से, मैं विकि-शैली परिवर्तन इतिहास को लागू करना चाहता हूं।

कुछ बैकग्राउंड रिसर्च करते हुए, मुझे आपके डेटाबेस स्कीमा को वर्जन करने के तरीके के बारे में बहुत सारे दस्तावेज दिखाई देते हैं (मेरा वास्तव में पहले से ही नियंत्रित है), लेकिन आपके डेटाबेस के कंटेंट में बदलाव के बारे में कोई मौजूदा रणनीति स्कीमा संस्करण सामग्री के हिमस्खलन में खो जाती है, कम से कम मेरी खोजों में।

मैं अपनी खुद की परिवर्तन ट्रैकिंग को लागू करने के कुछ तरीकों के बारे में सोच सकता हूं, लेकिन वे सभी कच्चे लगते हैं:

  • प्रत्येक परिवर्तन पर पूरी पंक्ति को सहेजें, एक प्राथमिक कुंजी के साथ पंक्ति को स्रोत आईडी से संबंधित करें (जो मैं वर्तमान में झुक रहा हूं, यह सबसे सरल है)। छोटे परिवर्तन के बहुत सारे टेबल ब्लोट का उत्पादन कर सकते हैं, हालांकि।
  • प्रत्येक परिवर्तन के लिए / बाद में / उपयोगकर्ता / टाइमस्टैम्प से पहले से संबंधित कॉलम में परिवर्तन से संबंधित एक कॉलम नाम के साथ सहेजें।
  • प्रत्येक स्तंभ के लिए एक तालिका के साथ / बाद / उपयोगकर्ता / टाइमस्टैम्प से पहले सहेजें (बहुत अधिक तालिकाओं में परिणाम होगा)।
  • एक कॉलम के साथ प्रत्येक परिवर्तन के लिए भिन्न / उपयोगकर्ता / टाइमस्टैम्प को बचाएं (इसका मतलब यह होगा कि आपको एक निश्चित तिथि पर वापस जाने के लिए संपूर्ण हस्तक्षेप परिवर्तन इतिहास चलना होगा)।

यहाँ सबसे अच्छा तरीका क्या है? अपने आप को रोल करना ऐसा लगता है कि मैं शायद किसी और के (बेहतर) कोडबेस को पुनः प्राप्त कर रहा हूं।


PostgreSQL के लिए बोनस अंक।


यह प्रश्न पहले ही SO: stackoverflow.com/questions/3874199/… पर चर्चा कर चुका है । "डेटाबेस रिकॉर्ड इतिहास" के लिए Google, और आपको कुछ और लेख मिलेंगे।
डॉक ब्राउन


ट्रिक करने के लिए SQL-Server के ट्रांजेक्शन लॉग का उपयोग क्यों नहीं किया जाता है?
थॉमस जंक

जवाबों:


11

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

यदि आप इस प्रणाली को अपनाते हैं, तो मैं आपको नियम लागू करने के लिए सूचकांक या बाधा जोड़ने की दृढ़ता से सलाह देता हूं। यह ओरेकल के साथ आसान है, क्योंकि एक अद्वितीय सूचकांक में एक और केवल एक शून्य हो सकता है। अन्य डेटाबेस समस्या का अधिक हो सकता है। नियम लागू करने वाला डेटाबेस आपके कोड को ईमानदार रखेगा।

आप काफी हद तक सही हैं कि बहुत से छोटे-छोटे बदलावों से ख़ुशियाँ पैदा होंगी, लेकिन आपको कोड और रिपोर्टिंग की सादगी के खिलाफ इस पर अमल करने की ज़रूरत है।


ध्यान दें कि अन्य डेटाबेस इंजन अलग तरह से व्यवहार कर सकते हैं, जैसे MySQL अद्वितीय सूचकांक के साथ एक कॉलम में कई NULL मानों की अनुमति देता है। यह इस बाधा को लागू करने के लिए और अधिक कठिन बना देता है।
qbd

वास्तविक टाइमस्टैम्प का उपयोग करना असुरक्षित है, लेकिन कुछ MVCC डेटाबेस आंतरिक रूप से न्यूनतम और अधिकतम लेन-देन के सीरियल नंबर को स्टेपल के साथ संग्रहीत करके काम करते हैं।
user2313838

"यह ओरेकल के साथ आसान है, क्योंकि एक अद्वितीय सूचकांक में एक और केवल एक शून्य हो सकता है"। गलत। Oracle में अशक्त मानों को अनुक्रमणिका में शामिल नहीं किया गया है। एक अद्वितीय सूचकांक वाले कॉलम में नल की संख्या पर कोई सीमा नहीं है।
गेरेट

@Gerrat यह एक ऐसा वर्ष है जब मैंने एक डेटाबेस डिज़ाइन किया है जिसकी यह आवश्यकता थी, और अब मेरी उस डेटाबेस तक पहुँच नहीं है। आप सही हैं कि एक मानक अद्वितीय सूचकांक कई नलियों का समर्थन कर सकता है, लेकिन मुझे लगता है कि हमने या तो एक अद्वितीय बाधा या संभवतः एक कार्यात्मक सूचकांक का उपयोग किया।
कीवरॉन

8

ध्यान दें कि यदि आप Microsoft SQL सर्वर का उपयोग करते हैं, तो पहले से ही एक सुविधा है जिसे चेंज डेटा कैप्चर कहा जाता है । एक्सेस करने के लिए आपको अभी भी कोड लिखना होगा बाद में पिछले संशोधनों (सीडीसी उस के लिए विशिष्ट विचार बनाता है), लेकिन कम से कम आपको अपनी तालिकाओं के स्कीमा को बदलने की आवश्यकता नहीं है, और न ही परिवर्तन ट्रैकिंग को लागू करें।

हुड के तहत , क्या होता है:

  • सीडीसी संशोधन के साथ एक अतिरिक्त तालिका बनाता है,

  • आपकी मूल तालिका का उपयोग पहले के रूप में किया जाता है, कोई भी अपडेट इस तालिका में सीधे परिलक्षित होता है,

  • सीडीसी तालिका केवल परिवर्तित मूल्यों को संग्रहीत करती है, जिसका अर्थ है कि डेटा दोहराव को न्यूनतम रखा गया है।

तथ्य यह है कि परिवर्तन एक अलग तालिका में संग्रहीत किए जाते हैं, के दो प्रमुख परिणाम होते हैं:

  • मूल तालिका से चयन बिना सीडीसी के रूप में तेजी से कर रहे हैं। यदि मुझे अच्छी तरह से याद है, तो सीडीसी अपडेट के बाद होता है , इसलिए अपडेट समान रूप से तेज़ होते हैं (हालांकि मुझे अच्छी तरह से याद नहीं है कि सीडीसी डेटा स्थिरता कैसे प्रबंधित करता है)।

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


6

समस्या को "दार्शनिक" और पहले कोड में हल करें। और फिर इसे करने के लिए कोड और डेटाबेस के साथ "बातचीत" करें।

उदाहरण के लिए , यदि आप सामान्य लेखों के साथ काम कर रहे हैं, तो एक लेख के लिए एक प्रारंभिक अवधारणा इस तरह दिख सकती है:

class Article {
  public Int32 Id;
  public String Body;
}

और अगले सबसे बुनियादी स्तर पर, मैं संशोधन की एक सूची रखना चाहता हूं:

class Article {
  public Int32 Id;
  public String Body;
  public List<String> Revisions;
}

और यह मुझ पर भोर हो सकता है कि वर्तमान निकाय केवल नवीनतम संशोधन है। और इसका मतलब है कि दो चीजें: मुझे दिनांकित या गिने जाने के लिए प्रत्येक संशोधन की आवश्यकता है:

class Revision {
  public Int32 Id;
  public Article ParentArticle;
  public DateTime Created;
  public String Body;
}

और ... और लेख के वर्तमान निकाय को नवीनतम संशोधन से अलग होने की आवश्यकता नहीं है:

class Article {
  public Int32 Id;
  public String Body {
    get {
      return (Revisions.OrderByDesc(r => r.Created))[0];
    }
    set {
      Revisions.Add(new Revision(value));
    }
  }
  public List<Revision> Revisions;
}

कुछ विवरण गायब हैं; लेकिन यह दर्शाता है कि आप शायद दो संस्थाएँ चाहते हैं । एक लेख (या अन्य हेडर-प्रकार) का प्रतिनिधित्व करता है, और दूसरा संशोधन की एक सूची है (जो भी फ़ील्ड समूह को समूह में अच्छा "दार्शनिक" अर्थ देता है)। आपको शुरू में विशेष डेटाबेस बाधाओं की आवश्यकता नहीं है, क्योंकि आपका कोड किसी भी संशोधन के बारे में और खुद के बारे में परवाह नहीं करता है - वे एक लेख के गुण हैं जो संशोधन के बारे में जानते हैं।

तो, आपको "वर्तमान" लेख को चिह्नित करने के लिए किसी विशेष तरीके से फ़्लैगिंग संशोधन या डेटाबेस बाधा पर झुकाव के बारे में चिंता करने की आवश्यकता नहीं है। आप बस उन्हें टाइमस्टैम्प करें (यहां तक ​​कि एक ऑटो-इंकॉइड आईडी भी ठीक होगी), उन्हें उनके मूल लेख से संबंधित बनाते हैं, और लेख को "नवीनतम" जानने के प्रभारी होने दें, जो सबसे अधिक प्रासंगिक है।

और आप एक ORM को कम दार्शनिक विवरणों को संभालने देते हैं - या यदि आप किसी आउट-ऑफ-द-बॉक्स ORM का उपयोग नहीं कर रहे हैं, तो आप उन्हें कस्टम उपयोगिता वर्ग में छिपाते हैं।

बहुत बाद में, आपने कुछ तनाव परीक्षण करने के बाद, आप उस संशोधन संपत्ति को आलसी-भार बनाने के बारे में सोच सकते हैं, या आपके शरीर की विशेषता आलसी-भार को केवल सबसे ऊपरी संशोधन कर सकती है। लेकिन, इस मामले में आपकी डेटा संरचना को उन अनुकूलन को समायोजित करने के लिए नहीं बदलना चाहिए।


2

ऑडिट ट्रैकिंग ट्रिगर के लिए एक PostgreSQL विकि पृष्ठ है जो आपको ऑडिट लॉग सेट करने के तरीके के माध्यम से चलता है जो कि आपकी ज़रूरत है।

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

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

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


1

ठीक है, मैं बस सबसे सरल विकल्प के साथ जा रहा हूं, एक ट्रिगर जो एक पंक्ति के पुराने संस्करण को प्रति-टेबल इतिहास लॉग में कॉपी करता है।

अगर मैं बहुत अधिक डेटाबेस ब्लोट से हवा लेता हूं, तो मैं जरूरत पड़ने पर कुछ मामूली इतिहास परिवर्तनों को ढहा सकता हूं।

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

वैसे भी, यह सब यहाँ github पर है

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