সংস্করণ কীভাবে একটি ডাটাবেসে রেকর্ড নিয়ন্ত্রণ করে


176

ধরা যাক যে ডাটাবেসে আমার একটি রেকর্ড রয়েছে এবং প্রশাসক এবং সাধারণ ব্যবহারকারী উভয়ই আপডেট করতে পারেন।

যে কেউ এই টেবিলের প্রতিটি পরিবর্তনকে কীভাবে সংস্করণে নিয়ন্ত্রণ করতে পারে সে সম্পর্কে একটি ভাল পদ্ধতির / আর্কিটেকচারের পরামর্শ দিতে পারে যাতে কোনও পূর্ববর্তী পুনর্বিবেচনায় রেকর্ডটি রোলব্যাক করা সম্ভব।

উত্তর:


164

ধরা যাক আপনার একটি FOOটেবিল রয়েছে যা প্রশাসক এবং ব্যবহারকারীরা আপডেট করতে পারে। বেশিরভাগ সময় আপনি FOO টেবিলের বিপরীতে প্রশ্ন লিখতে পারেন। সুখের দিনগুলি.

তারপরে, আমি একটি FOO_HISTORYটেবিল তৈরি করব । এটিতে FOOটেবিলের সমস্ত কলাম রয়েছে । প্রাথমিক কীটি এফও ও প্লাস একটি রিভিশননাম কলামের সমান। সেখান থেকে একটি বিদেশী চাবিকাঠি FOO_HISTORYকরতে FOO। আপনি ইউজারআইডি এবং রিভিশনডেটের মতো সংশোধন সম্পর্কিত কলামগুলি যুক্ত করতে পারেন। সমস্ত *_HISTORYটেবিল জুড়ে একটি ক্রমবর্ধমান ফ্যাশনে পুনর্বিবেচনা সংখ্যাগুলি পপুলেট করুন (অর্থাত্ ওরাকল ক্রম বা সমতুল্য থেকে)। সেখানে কেবলমাত্র এক সেকেন্ডে একটি পরিবর্তন হচ্ছে তার উপর নির্ভর করবেন না (যেমন RevisionDateপ্রাথমিক কীতে রাখবেন না)।

এখন, প্রতিবার আপনি আপডেট করার পরে FOO, আপডেট করার ঠিক আগে আপনি পুরানো মানগুলিকে সন্নিবেশ করান FOO_HISTORY। আপনি আপনার ডিজাইনের কিছু মৌলিক স্তরে এটি করেন যাতে প্রোগ্রামাররা দুর্ঘটনাক্রমে এই পদক্ষেপটি মিস করতে না পারে।

আপনি যদি একটি সারি মুছে ফেলতে চান তবে আপনার FOOকিছু পছন্দ আছে। হয় ক্যাসকেড এবং সমস্ত ইতিহাস মুছুন, বা মুছে FOOফেলা হিসাবে পতাকাঙ্কিত করে একটি লজিকাল মুছা সম্পাদন করুন ।

আপনি যখন সর্বাধিক বর্তমান মানগুলিতে আগ্রহী এবং কেবল কখনও কখনও ইতিহাসে আগ্রহী তখন এই সমাধানটি ভাল। আপনার যদি সর্বদা ইতিহাসের প্রয়োজন হয় তবে আপনি কার্যকর শুরু এবং শেষের তারিখগুলি রাখতে পারেন এবং সমস্ত রেকর্ডকে FOOনিজের মধ্যে রাখতে পারেন । প্রতিটি প্রশ্নের পরে সেই তারিখগুলি পরীক্ষা করা দরকার।


1
আপনার ডেটা অ্যাক্সেস লেয়ারটি সরাসরি সমর্থন না করে আপনি ডাটাবেস ট্রিগারগুলির সাথে অডিট টেবিল আপডেট করতে পারেন। এছাড়াও, সিস্টেম ডেটা অভিধান থেকে অন্তঃকরণ ব্যবহার করে এমন ট্রিগারগুলি তৈরি করতে কোড জেনারেটর তৈরি করা শক্ত নয়।
কনফারডঅফটুনব্রিজ

44
আমি আপনাকে সুপারিশ করব যে আপনি আসলে নতুন তথ্য সন্নিবেশ করান , আগেরটি নয়, তাই ইতিহাসের টেবিলে সমস্ত ডেটা থাকে। যদিও এটি অপ্রয়োজনীয় ডেটা সংরক্ষণ করে, historicalতিহাসিক ডেটা প্রয়োজন হলে উভয় সারণীতে অনুসন্ধানের জন্য প্রয়োজনীয় বিশেষ কেসগুলি সরিয়ে দেয়।
Nerdfest

6
ব্যক্তিগতভাবে আমি কোনও কিছু মুছতে না দেওয়ার (এটি একটি নির্দিষ্ট গৃহকর্মী ক্রিয়াকলাপকে মুলতুবি করার জন্য) সুপারিশ করব এবং এটি সন্নিবেশ / আপডেট / মোছা কিনা তা নির্দিষ্ট করার জন্য একটি "ক্রিয়া টাইপ" কলাম রয়েছে। মুছে ফেলার জন্য আপনি সারিটি স্বাভাবিক হিসাবে অনুলিপি করেন তবে ক্রিয়া ধরণের কলামে "মুছুন" রেখে দিন।
নীল বার্নওয়েল

3
@ হাইড্রিজারাম বর্তমান মানগুলিকে ধারণ করে একটি টেবিল historicতিহাসিক সারণির দর্শন চেয়ে আরও ভাল সম্পাদন করবে। আপনি বর্তমান মানগুলি উল্লেখ করে বিদেশী কীগুলি সংজ্ঞায়িত করতেও পারেন।
ডাব্লুডাব্লু

2
There is a foreign key from FOO_HISTORY to FOO': খারাপ ধারণা, আমি ইতিহাস পরিবর্তন না করে ফু থেকে রেকর্ড মুছতে চাই। ইতিহাসের সারণিটি কেবল সাধারণ ব্যবহারের জন্য সন্নিবেশ করা উচিত।
জেসেন

46

আমি মনে করি আপনি ডাটাবেস রেকর্ডের সামগ্রীটির সংস্করণটির সন্ধান করছেন (যেমন কেউ যখন কোনও প্রশ্ন / উত্তর সম্পাদনা করে স্ট্যাকওভারফ্লো করে)। একটি ভাল সূচনা পয়েন্ট হয়ত কিছু ডাটাবেস মডেলের দিকে তাকিয়ে থাকবে যা রিভিশন ট্র্যাকিং ব্যবহার করে ।

সবচেয়ে ভাল উদাহরণ যা মনে আসে তা হ'ল মিডিয়াউইকি, উইকিপিডিয়া ইঞ্জিন। এখানে ডাটাবেস চিত্রের তুলনা করুন , বিশেষত সংশোধন সারণী

আপনি কোন প্রযুক্তি ব্যবহার করছেন তার উপর নির্ভর করে আপনাকে কিছু ভাল ডিফ / মার্জ অ্যালগরিদমগুলি খুঁজতে হবে।

এটি নেট। নেট এর জন্য কিনা এই প্রশ্নটি পরীক্ষা করে দেখুন ।


30

দ্বি বিশ্বে আপনি যে সংস্করণটি চান তা সারণীতে স্টার্টেট এবং শেষ তারিখ যুক্ত করে এটি সম্পাদন করতে পারেন। আপনি যখন টেবিলের মধ্যে প্রথম রেকর্ড সন্নিবেশ করান, তখন স্টার্টেটটি জনবহুল হয় তবে শেষের তারিখটি শূন্য হয়। আপনি যখন দ্বিতীয় রেকর্ড সন্নিবেশ করান, আপনি দ্বিতীয় রেকর্ডের স্টার্টেটের সাথে প্রথম রেকর্ডের এন্ডেট তারিখও আপডেট করেন।

আপনি যখন বর্তমান রেকর্ডটি দেখতে চান, আপনি এমন একটি নির্বাচন করুন যেখানে শেষের তারিখটি নাল।

এটি কখনও কখনও টাইপ 2 ধীরে ধীরে পরিবর্তনশীল মাত্রা নামে পরিচিত । TupleVersioning দেখুন


এই পদ্ধতির সাহায্যে আমার টেবিলটি বেশ বড় হবে না?
নীল বোসমা

1
হ্যাঁ, তবে আপনি টেবিলটি সূচীকরণ এবং / অথবা বিভাজন করে এটি মোকাবেলা করতে পারেন। এছাড়াও, কেবলমাত্র কয়েকটি বড় বড় টেবিল থাকবে। বেশিরভাগই অনেক ছোট হবে।
কনসার্নড

আমি যদি এখানে ভুল না হয়ে থাকি তবে এটি প্রতি সেকেন্ডে একবারে পরিবর্তনগুলি সীমাবদ্ধ করে দেয়?
পিমব্রউবার্স 16'19

@ পিমব্রউবউয়ার্স হ্যাঁ, এটি শেষ পর্যন্ত ক্ষেত্রগুলির যথার্থতা এবং সেগুলি কার্যকারী ফাংশনের উপর নির্ভর করে।
ডেভ নীলে

9

এসকিউএল ২০০৮ এ আপগ্রেড করুন।

এসকিউএল ২০০৮-এ এসকিউএল চেঞ্জ ট্র্যাকিং ব্যবহার করার চেষ্টা করুন time টাইমস্ট্যাম্পিং এবং সমাধিস্টোন কলাম হ্যাকের পরিবর্তে, আপনি আপনার ডাটাবেসের ডেটাতে পরিবর্তনগুলি ট্র্যাক করার জন্য এই নতুন বৈশিষ্ট্যটি ব্যবহার করতে পারেন।

এমএসডিএন এসকিউএল ২০০৮ ট্র্যাকিং পরিবর্তন করুন


7

এই সমস্যাটির একটি ভাল সমাধান কেবলমাত্র যুক্ত করতে চেয়েছিলেন তা হল টেম্পোরাল ডাটাবেস ব্যবহার করা । অনেক ডাটাবেস বিক্রেতারা বক্সের বাইরে বা কোনও এক্সটেনশনের মাধ্যমে এই বৈশিষ্ট্যটি সরবরাহ করে। আমি পোস্টগ্র্রেএসকিউএল সহ টেম্পোরাল টেবিল এক্সটেনশনটি সফলভাবে ব্যবহার করেছি তবে অন্যদের কাছেও এটি রয়েছে। আপনি যখনই ডাটাবেসে কোনও রেকর্ড আপডেট করেন, ডাটাবেসটি সেই রেকর্ডের পূর্ববর্তী সংস্করণটি ধরে রাখে।


6

দুটি বিকল্প:

  1. একটি ইতিহাস সারণী রয়েছে - যখনই মূলটি আপডেট করা হয় তখন এই ইতিহাসের টেবিলটিতে পুরানো ডেটা sertোকান।
  2. নিরীক্ষণ সারণী - মানগুলির আগে এবং পরে সংরক্ষণ করুন - কেবলমাত্র অডিট টেবিলে পরিবর্তিত কলামগুলির সাথে সাথে কে আপডেট হয়েছে এবং কখন হয়েছে তার অন্যান্য তথ্যের সাথে রয়েছে।

5

আপনি এসকিউএল ট্রিগারগুলির মাধ্যমে কোনও এসকিউএল টেবিলে নিরীক্ষণ করতে পারেন। ট্রিগার থেকে আপনি 2 টি বিশেষ টেবিল ( সন্নিবেশিত এবং মুছে ফেলা ) অ্যাক্সেস করতে পারেন । এই টেবিলগুলিতে সারণী আপডেট হওয়ার সাথে সাথে সুনির্দিষ্ট সারিগুলি sertedোকানো বা মুছে ফেলা হয়েছে। ট্রিগার এসকিউএল এ আপনি এই সংশোধিত সারিগুলি নিতে এবং সেগুলি নিরীক্ষার টেবিলের মধ্যে সন্নিবেশ করতে পারেন। এই পদ্ধতির অর্থ আপনার অডিটিং প্রোগ্রামারের কাছে স্বচ্ছ; তাদের কাছ থেকে কোন প্রচেষ্টা বা কোনও বাস্তবায়নের জ্ঞানের প্রয়োজন নেই।

এই পদ্ধতির যোগ করা বোনাস হ'ল এসকিএল অপারেশনটি আপনার ডেটা অ্যাক্সেস ডিএলএল, বা ম্যানুয়াল এসকিউএল ক্যোয়ারির মাধ্যমে হয়েছিল কিনা তা বিবেচনা না করেই নিরীক্ষণটি ঘটবে; (যেমন অডিটিং সার্ভারে নিজেই সঞ্চালিত হয়)।


3

আপনি কোন ডাটাবেসটি বলবেন না এবং আমি এটি পোস্টের ট্যাগগুলিতে দেখতে পাচ্ছি না। যদি এটি ওরাকল এর হয় তবে আমি ডিজাইনার অন্তর্ভূক্ত পদ্ধতির সুপারিশ করতে পারি: জার্নাল টেবিলগুলি ব্যবহার করুন । যদি এটি অন্য কোনও ডাটাবেসের জন্য হয় তবে ভাল, আমিও মূলত একইভাবে সুপারিশ করি ...

এটি যেভাবে কাজ করে, আপনি যদি এটি অন্য ডিবিতে প্রতিলিপি করতে চান বা আপনি কেবল এটি বুঝতে চান তবে এটি হ'ল একটি টেবিলের জন্য একটি ছায়ার টেবিলও তৈরি করা হয়েছে, ঠিক একটি সাধারণ ডাটাবেস টেবিল, একই ক্ষেত্রের চশমা সহ , অতিরিক্ত কিছু ক্ষেত্র: সর্বশেষে কী কী পদক্ষেপ নেওয়া হয়েছিল (যেমন স্ট্রিং, সন্নিবেশের জন্য আদর্শ মান "আইএনএস", আপডেটের জন্য "ইউপিডি" এবং মোছার জন্য "ডেল"), ক্রিয়াটি কখন সংঘটিত হয়েছিল তার তারিখ সময় এবং ব্যবহারকারী আইডি এটা।

ট্রিগারগুলির মাধ্যমে, টেবিলের যে কোনও সারিতে প্রতিটি ক্রিয়া জার্নাল সারণীতে একটি নতুন সারি নতুন মান সন্নিবেশ করায়, কোন পদক্ষেপ নেওয়া হয়েছিল, কখন এবং কোন ব্যবহারকারী দ্বারা। আপনি কখনই কোনও সারি মুছবেন না (অন্তত শেষ কয়েক মাসের জন্য নয়)। হ্যাঁ এটি বড় হয়ে উঠবে, সহজেই কয়েক মিলিয়ন সারি, তবে জার্নালিং শুরু হওয়ার পরে বা পুরানো জার্নাল সারিগুলি সর্বশেষ শুদ্ধ হওয়ার পরে এবং শেষ পরিবর্তনটি করার পরে আপনি যেকোন সময় যে কোনও রেকর্ডের জন্য মূল্য সহজেই ট্র্যাক করতে পারেন ।

ওরাকলগুলিতে আপনার যা যা করা দরকার তা এসকিউএল কোড হিসাবে স্বয়ংক্রিয়ভাবে উত্পন্ন হয়, আপনাকে যা করতে হবে তা হ'ল এটি সংকলন / চালানো; এবং এটি পরিদর্শন করার জন্য এটি একটি প্রাথমিক সিআরইউডি অ্যাপ্লিকেশন (আসলে কেবল "আর") আসে।


2

আমিও একই কাজ করছি। পাঠের পরিকল্পনার জন্য আমি একটি ডাটাবেস তৈরি করছি। এই পরিকল্পনাগুলির জন্য পারমাণবিক পরিবর্তন সংস্করণকরণের নমনীয়তা দরকার। অন্য কথায়, প্রতিটি পরিবর্তন, যত ছোটই হোক না কেন, পাঠ্যক্রমের পরিকল্পনার অনুমতি দেওয়া দরকার তবে পুরাতন সংস্করণটিও অক্ষত রাখতে হবে। এইভাবে, পাঠ নির্মাতারা শিক্ষার্থীরা তাদের ব্যবহার করার সময় পাঠ পরিকল্পনা সম্পাদনা করতে পারবেন।

এটি যেভাবে কাজ করবে তা হ'ল কোনও শিক্ষার্থী একবার পাঠ করলে, তাদের ফলাফলগুলি তাদের সম্পন্ন সংস্করণের সাথে সংযুক্ত থাকে। যদি কোনও পরিবর্তন করা হয়, তবে তাদের ফলাফলগুলি সর্বদা তাদের সংস্করণে নির্দেশ করবে।

এইভাবে, যদি পাঠের মানদণ্ড মুছে ফেলা হয় বা সরানো হয় তবে তাদের ফলাফল পরিবর্তন হবে না।

আমি বর্তমানে যেভাবে এটি করছি তা হ'ল এক টেবিলের সমস্ত ডেটা পরিচালনা করে। সাধারণত আমার কেবল একটি আইডি ক্ষেত্র থাকবে তবে এই সিস্টেমটির সাথে আমি একটি আইডি এবং একটি সাব_আইডি ব্যবহার করছি। সাব-আইডি সর্বদা আপডেট এবং মুছে ফেলার মাধ্যমে সারির সাথে থাকে। আইডিটি স্বয়ং-বর্ধিত। পাঠ পরিকল্পনা সফ্টওয়্যারটি নতুন সাব_আইডিতে লিঙ্ক করবে। শিক্ষার্থীর ফলাফলগুলি আইডিতে লিঙ্ক করবে। পরিবর্তনগুলি যখন ঘটেছিল তখন আমি ট্র্যাকিংয়ের জন্য একটি টাইমস্ট্যাম্পও অন্তর্ভুক্ত করেছি, তবে সংস্করণটি হ্যান্ডেল করার প্রয়োজন নেই।

একটা জিনিস আমি পরিবর্তন করতে পারি, একবার এটি পরীক্ষা করে দেখলে আমি পূর্বের উল্লিখিত শেষ তারিখের নাল ধারণাটি ব্যবহার করতে পারি। আমার সিস্টেমে, নতুন সংস্করণটি খুঁজতে, আমাকে সর্বাধিক (আইডি) সন্ধান করতে হবে। অন্যান্য সিস্টেমটি কেবল শেষ তারিখ = নালার সন্ধান করে। নিশ্চিত না যে উপকারের বাইরে অন্য তারিখের ক্ষেত্র রয়েছে।

আমার দুই সেন্ট.


2

@WW- এর সময় উত্তর হ'ল উত্তম উত্তর হ'ল একটি সংস্করণ কলাম তৈরি করা এবং আপনার সমস্ত সংস্করণ একই টেবিলে রাখা।

একটি টেবিলের জন্য আপনি হয়:

  • সর্বশেষতম আলা ওয়ার্ড প্রেসকে নির্দেশ করতে একটি পতাকা ব্যবহার করুন
  • অথবা সংস্করণের চেয়ে বড়ো কোনও দুষ্টু করুন outer join

outer joinসংশোধন নম্বর ব্যবহার করে পদ্ধতির একটি উদাহরণ এসকিউএল হ'ল:

SELECT tc.*
FROM text_content tc
LEFT OUTER JOIN text_content mc ON tc.path = mc.path
AND mc.revision > tc.revision
WHERE mc.revision is NULL 
AND tc.path = '/stuff' -- path in this case is our natural id.

খারাপ খবর উপরেরটি হ'ল একটি outer joinবাহ্যিক সংযুক্তি ধীর হতে পারে requires সুসংবাদটি হ'ল নতুন এন্ট্রি তৈরি করা তাত্ত্বিকভাবে কম সস্তা কারণ আপনি এটি লেনদেনের মাধ্যমে একটি লিখন অপারেশনে করতে পারেন (আপনার ডাটাবেসটিকে পারমাণবিক বলে ধরে নিচ্ছেন)।

এর জন্য একটি নতুন সংশোধন করার উদাহরণ '/stuff'হতে পারে:

INSERT INTO text_content (id, path, data, revision, revision_comment, enabled, create_time, update_time)
(
SELECT
(md5(random()::text)) -- {id}
, tc.path
, 'NEW' -- {data}
, (tc.revision + 1)
, 'UPDATE' -- {comment}
, 't' -- {enabled}
, tc.create_time
, now() 
FROM text_content tc
LEFT OUTER JOIN text_content mc ON tc.path = mc.path
AND mc.revision > tc.revision
WHERE mc.revision is NULL 
AND tc.path = '/stuff' -- {path}
)

আমরা পুরানো ডেটা ব্যবহার করে সন্নিবেশ করি। এটি বিশেষত কার্যকর যদি বলুন যে আপনি কেবল একটি কলাম আপডেট করতে চান এবং আশাবাদী লকিং এবং বা লেনদেন এড়াতে চান।

পতাকা পদ্ধতির এবং ইতিহাস সারণির পদ্ধতির জন্য দুটি সারি সন্নিবেশ করা / আপডেট করা দরকার।

outer joinরিভিশন নম্বর পদ্ধতির সাথে অন্য সুবিধাটি হ'ল আপনি সর্বদা ট্রিগারগুলির সাথে একাধিক টেবিল পদ্ধতির রিপ্যাক্টর করতে পারেন কারণ আপনার ট্রিগারটি মূলত উপরের মতো কিছু করা উচিত।


2

অলোক Audit tableউপরে প্রস্তাবিত , আমি এটি আমার পোস্টে ব্যাখ্যা করতে চাই।

আমি আমার প্রকল্পে এই স্কিমা-কম, একক টেবিল ডিজাইন গ্রহণ করেছি।

স্কিমা:

  • আইডি - স্বতন্ত্র স্বয়ং ইনক্রিমেন্ট
  • ব্যবহারকারীর নাম - STRING
  • টেবিলের নাম - STRING
  • পুরানো মূল্য - পাঠ / জেএসএন
  • নতুন মূল্য - পাঠ / জেএসএন
  • তৈরি - DATETIME

এই টেবিলটি প্রতিটি টেবিলের জন্য onceতিহাসিক রেকর্ডগুলি একসাথে একই স্থানে রাখতে পারে, একটি রেকর্ডে সম্পূর্ণ অবজেক্টের ইতিহাস সহ। এই সারণীটি ট্রিগার / হুক ব্যবহার করে পপুলেট করতে পারে যেখানে ডেটা পরিবর্তিত হয়, লক্ষ্য সারিটির পুরানো এবং নতুন মান স্ন্যাপশট সংরক্ষণ করে।

এই নকশা সহ পেশাদার:

  • ইতিহাস পরিচালনার জন্য টেবিলের কম সংখ্যা।
  • প্রতিটি সারি পুরানো এবং নতুন রাজ্যের সম্পূর্ণ স্ন্যাপশট সংরক্ষণ করে।
  • প্রতিটি টেবিলে অনুসন্ধান করা সহজ।
  • টেবিল দ্বারা পার্টিশন তৈরি করতে পারেন।
  • প্রতি সারণীতে ডেটা ধরে রাখার নীতি নির্ধারণ করতে পারে।

এই নকশার সাথে মতামত:

  • যদি সিস্টেমে ঘন ঘন পরিবর্তন হয় তবে ডেটা আকার বড় হতে পারে।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.