Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

रिकॉर्ड में परिवर्तन के इतिहास को ट्रैक करने के लिए क्या कोई MySQL विकल्प/सुविधा है?

ऐसा करने का यह एक सीधा तरीका है:

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

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

इस अनुक्रमण व्यवहार को करने के लिए प्राथमिक कुंजी स्तंभ और संशोधन स्तंभ पर एक दो स्तंभ (समग्र) अनुक्रमणिका बनाई जाती है। ध्यान दें कि आप केवल इस तरह से अनुक्रमण कर सकते हैं यदि इतिहास तालिका द्वारा उपयोग किया जाने वाला इंजन MyISAM है (इस पेज पर 'MyISAM नोट्स' देखें)

इतिहास तालिका बनाना काफी आसान है। नीचे दी गई वैकल्पिक तालिका क्वेरी में (और उसके नीचे ट्रिगर क्वेरी में), 'प्राथमिक_की_कॉलम' को अपनी डेटा तालिका में उस कॉलम के वास्तविक नाम से बदलें।

CREATE TABLE MyDB.data_history LIKE MyDB.data;

ALTER TABLE MyDB.data_history MODIFY COLUMN primary_key_column int(11) NOT NULL, 
   DROP PRIMARY KEY, ENGINE = MyISAM, ADD action VARCHAR(8) DEFAULT 'insert' FIRST, 
   ADD revision INT(6) NOT NULL AUTO_INCREMENT AFTER action,
   ADD dt_datetime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER revision,
   ADD PRIMARY KEY (primary_key_column, revision);

और फिर आप ट्रिगर बनाते हैं:

DROP TRIGGER IF EXISTS MyDB.data__ai;
DROP TRIGGER IF EXISTS MyDB.data__au;
DROP TRIGGER IF EXISTS MyDB.data__bd;

CREATE TRIGGER MyDB.data__ai AFTER INSERT ON MyDB.data FOR EACH ROW
    INSERT INTO MyDB.data_history SELECT 'insert', NULL, NOW(), d.* 
    FROM MyDB.data AS d WHERE d.primary_key_column = NEW.primary_key_column;

CREATE TRIGGER MyDB.data__au AFTER UPDATE ON MyDB.data FOR EACH ROW
    INSERT INTO MyDB.data_history SELECT 'update', NULL, NOW(), d.*
    FROM MyDB.data AS d WHERE d.primary_key_column = NEW.primary_key_column;

CREATE TRIGGER MyDB.data__bd BEFORE DELETE ON MyDB.data FOR EACH ROW
    INSERT INTO MyDB.data_history SELECT 'delete', NULL, NOW(), d.* 
    FROM MyDB.data AS d WHERE d.primary_key_column = OLD.primary_key_column;

और आपने कल लिया। अब, 'MyDb.data' में सभी इंसर्ट, अपडेट और डिलीट को 'MyDb.data_history' में रिकॉर्ड किया जाएगा, जिससे आपको इस तरह की एक हिस्ट्री टेबल मिलेगी (कम से कम 'data_columns' कॉलम)

ID    revision   action    data columns..
1     1         'insert'   ....          initial entry for row where ID = 1
1     2         'update'   ....          changes made to row where ID = 1
2     1         'insert'   ....          initial entry, ID = 2
3     1         'insert'   ....          initial entry, ID = 3 
1     3         'update'   ....          more changes made to row where ID = 1
3     2         'update'   ....          changes made to row where ID = 3
2     2         'delete'   ....          deletion of row where ID = 2 

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

CREATE VIEW data_history_changes AS 
   SELECT t2.dt_datetime, t2.action, t1.primary_key_column as 'row id', 
   IF(t1.a_column = t2.a_column, t1.a_column, CONCAT(t1.a_column, " to ", t2.a_column)) as a_column
   FROM MyDB.data_history as t1 INNER join MyDB.data_history as t2 on t1.primary_key_column = t2.primary_key_column 
   WHERE (t1.revision = 1 AND t2.revision = 1) OR t2.revision = t1.revision+1
   ORDER BY t1.primary_key_column ASC, t2.revision ASC

संपादित करें:ओह वाह, लोग 6 साल पहले की मेरी इतिहास तालिका वाली चीज़ को पसंद करते हैं:पी

इसका कार्यान्वयन अभी भी साथ-साथ चल रहा है, बड़ा और अधिक बोझिल होता जा रहा है, मुझे लगता है। मैंने इस डेटाबेस में इतिहास को देखने के लिए विचार और बहुत अच्छा UI लिखा था, लेकिन मुझे नहीं लगता कि इसका कभी अधिक उपयोग किया गया था। तो यह जाता है।

किसी विशेष क्रम में कुछ टिप्पणियों को संबोधित करने के लिए:

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

  • यदि प्राथमिक कुंजी और संशोधन कॉलम के बीच संबंध बंद लगता है तो आमतौर पर इसका मतलब है कि समग्र कुंजी किसी भी तरह से बोर हो गई है। कुछ दुर्लभ मौकों पर मैं ऐसा हुआ था और इस कारण से मुझे नुकसान हुआ था।

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

  • यदि आपको बार-बार प्रविष्टियां मिल रही हैं, तो INSERT IGNORE प्रकार की क्वेरी के लिए अपने सॉफ़्टवेयर स्तर की जाँच करें। हम्म, अब याद नहीं आ रहा है, लेकिन मुझे लगता है कि इस योजना और लेनदेन के साथ कुछ समस्याएं हैं जो अंततः कई डीएमएल क्रियाओं को चलाने के बाद विफल हो जाती हैं। कम से कम कुछ तो पता होना चाहिए।

  • यह महत्वपूर्ण है कि इतिहास तालिका और डेटा तालिका के फ़ील्ड मेल खाते हों। या, इसके बजाय, कि आपकी डेटा तालिका में इतिहास तालिका से अधिक स्तंभ नहीं हैं। अन्यथा, डेटा तालिका पर सम्मिलित/अद्यतन/डेल क्वेरी विफल हो जाएंगी, जब इतिहास तालिका में प्रविष्टियां उस क्वेरी में कॉलम डालती हैं जो मौजूद नहीं है (ट्रिगर क्वेरी में d.* के कारण), और ट्रिगर विफल हो जाता है। t बहुत बढ़िया होगा यदि MySQL में स्कीमा-ट्रिगर जैसा कुछ था, जहाँ आप डेटा तालिका में कॉलम जोड़े जाने पर इतिहास तालिका को बदल सकते थे। क्या MySQL के पास अब यह है? मैं इन दिनों रिएक्ट करता हूं :P



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL - फिक्स - त्रुटि - आपका पासवर्ड वर्तमान नीति आवश्यकताओं को पूरा नहीं करता है

  2. LOAD DATA LOCAL INFILE त्रुटि देता है इस MySQL संस्करण के साथ प्रयुक्त कमांड की अनुमति नहीं है

  3. MySQL डेटाबेस में लिंक की गई सूची लाई जा रही है

  4. मैं प्रत्येक पंजीकृत उपयोगकर्ता को PHP का उपयोग करके अपना यूआरएल कैसे दे सकता हूं?

  5. रोलिंग के आधार पर MySQL से पुरानी पंक्तियों को हटाने का सबसे अच्छा तरीका क्या है?