มีตัวเลือก / คุณสมบัติ MySQL ในการติดตามประวัติการเปลี่ยนแปลงบันทึกหรือไม่?


122

ฉันถูกถามว่าฉันสามารถติดตามการเปลี่ยนแปลงของระเบียนในฐานข้อมูล MySQL ได้หรือไม่ ดังนั้นเมื่อมีการเปลี่ยนแปลงฟิลด์เก่าและใหม่จะพร้อมใช้งานและวันที่นี้เกิดขึ้น มีคุณสมบัติหรือเทคนิคทั่วไปในการทำเช่นนี้หรือไม่?

ถ้าเป็นเช่นนั้นฉันคิดจะทำอะไรแบบนี้ changesสร้างตารางที่เรียกว่า มันจะมีสาขาเดียวกับต้นแบบตาราง แต่นำหน้าด้วยเก่าและใหม่ แต่สำหรับเขตข้อมูลเหล่านั้นที่มีการเปลี่ยนแปลงและจริงTIMESTAMPสำหรับมัน มันจะถูกสร้างดัชนีด้วยIDไฟล์. วิธีนี้SELECTสามารถเรียกใช้รายงานเพื่อแสดงประวัติของแต่ละระเบียน วิธีนี้เป็นวิธีที่ดีหรือไม่? ขอบคุณ!

คำตอบ:


83

มันบอบบาง

หากข้อกำหนดทางธุรกิจคือ "ฉันต้องการตรวจสอบการเปลี่ยนแปลงข้อมูล - ใครทำอะไรและเมื่อไหร่" โดยปกติคุณสามารถใช้ตารางการตรวจสอบได้ (ตามตัวอย่างทริกเกอร์ที่ Keethanjan โพสต์) ฉันไม่ใช่แฟนตัวยงของทริกเกอร์ แต่มันมีประโยชน์อย่างมากในการใช้งานที่ไม่ยุ่งยาก - โค้ดที่มีอยู่ของคุณไม่จำเป็นต้องรู้เกี่ยวกับทริกเกอร์และสิ่งที่ตรวจสอบ

หากข้อกำหนดทางธุรกิจคือ "แสดงสถานะของข้อมูลในวันที่ที่กำหนดในอดีต" หมายความว่าแง่มุมของการเปลี่ยนแปลงตลอดเวลาได้เข้าสู่โซลูชันของคุณแล้ว ในขณะที่คุณสามารถสร้างสถานะของฐานข้อมูลใหม่ได้เพียงแค่ดูตารางการตรวจสอบ แต่ก็ยากและเกิดข้อผิดพลาดได้ง่ายและสำหรับตรรกะฐานข้อมูลที่ซับซ้อนใด ๆ ก็จะไม่สามารถทำได้ ตัวอย่างเช่นหากธุรกิจต้องการทราบว่า "ค้นหาที่อยู่ของจดหมายที่เราควรส่งให้กับลูกค้าที่มีใบแจ้งหนี้ค้างชำระและค้างชำระในวันแรกของเดือน" คุณอาจต้องใช้ตารางตรวจสอบครึ่งโหล

คุณสามารถอบแนวคิดการเปลี่ยนแปลงเมื่อเวลาผ่านไปในการออกแบบสคีมาของคุณได้ (นี่คือตัวเลือกที่สองที่ Keethanjan แนะนำ) นี่เป็นการเปลี่ยนแปลงแอปพลิเคชันของคุณแน่นอนในระดับตรรกะทางธุรกิจและความคงอยู่ดังนั้นจึงไม่ใช่เรื่องเล็กน้อย

ตัวอย่างเช่นหากคุณมีตารางดังนี้:

CUSTOMER
---------
CUSTOMER_ID PK
CUSTOMER_NAME
CUSTOMER_ADDRESS

และคุณต้องการติดตามเมื่อเวลาผ่านไปคุณจะแก้ไขได้ดังนี้:

CUSTOMER
------------
CUSTOMER_ID            PK
CUSTOMER_VALID_FROM    PK
CUSTOMER_VALID_UNTIL   PK
CUSTOMER_STATUS
CUSTOMER_USER
CUSTOMER_NAME
CUSTOMER_ADDRESS

ทุกครั้งที่คุณต้องการเปลี่ยนเรกคอร์ดลูกค้าแทนที่จะอัปเดตเรกคอร์ดคุณตั้งค่า VALID_UNTIL บนเรกคอร์ดปัจจุบันเป็น NOW () และแทรกเร็กคอร์ดใหม่ด้วย VALID_FROM (now) และ null VALID_UNTIL คุณตั้งค่าสถานะ "CUSTOMER_USER" เป็น ID การเข้าสู่ระบบของผู้ใช้ปัจจุบัน (หากคุณต้องการเก็บไว้) หากลูกค้าจำเป็นต้องลบคุณใช้แฟล็ก CUSTOMER_STATUS เพื่อระบุสิ่งนี้ - คุณไม่สามารถลบบันทึกออกจากตารางนี้ได้

ด้วยวิธีนี้คุณจะพบสถานะของตารางลูกค้าในวันที่กำหนดได้ตลอดเวลา - ที่อยู่คืออะไร? พวกเขาเปลี่ยนชื่อหรือไม่? เมื่อเข้าร่วมกับตารางอื่น ๆ ที่มีวันที่ valid_from และ valid_u จนถึงวันที่คล้ายกันคุณสามารถสร้างภาพทั้งหมดในอดีตได้ หากต้องการค้นหาสถานะปัจจุบันคุณค้นหาระเบียนที่มีวันที่ว่าง VALID_UNTIL

มันเทอะทะ (พูดอย่างเคร่งครัดคุณไม่จำเป็นต้อง valid_from แต่จะทำให้การสืบค้นง่ายขึ้นเล็กน้อย) ทำให้การออกแบบและการเข้าถึงฐานข้อมูลของคุณซับซ้อนขึ้น แต่มันทำให้การสร้างโลกใหม่ง่ายขึ้นมาก


แต่จะเพิ่มข้อมูลที่ซ้ำกันสำหรับฟิลด์ที่ไม่ได้รับการอัปเดต? มีวิธีจัดการอย่างไร?
itzmukeshy7

ด้วยปัญหาแนวทางที่สองเกิดขึ้นสำหรับการสร้างรายงานหากมีการแก้ไขบันทึกของลูกค้าในช่วงเวลาหนึ่งทำให้ยากที่จะรับรู้ว่ารายการใดรายการหนึ่งเป็นของลูกค้ารายเดียวกันหรือต่างกัน
Akshay Joshi

คำแนะนำที่ดีที่สุดที่ฉันเคยเห็นสำหรับปัญหานี้
สมควร 7

โอ้และในการตอบกลับความคิดเห็นจะเก็บค่าว่างสำหรับทุกอย่างที่ไม่เปลี่ยนแปลงได้อย่างไร? ดังนั้นเวอร์ชันล่าสุดจะเป็นข้อมูลล่าสุดทั้งหมด แต่ถ้าชื่อเคยเป็น "Bob" เมื่อ 5 วันที่แล้วให้มีแถวเดียวชื่อ = bob และใช้ได้จนถึง 5 วันที่ผ่านมา
สมควร 7

2
ชุดค่าผสมของ customer_id และวันที่เป็นคีย์หลักดังนั้นจึงรับประกันได้ว่าไม่ซ้ำกัน
Neville Kuyt

187

นี่เป็นวิธีง่ายๆในการดำเนินการนี้:

ขั้นแรกสร้างตารางประวัติสำหรับแต่ละตารางข้อมูลที่คุณต้องการติดตาม (ตัวอย่างแบบสอบถามด้านล่าง) ตารางนี้จะมีรายการสำหรับการแทรกอัปเดตและลบคิวรีที่ดำเนินการในแต่ละแถวในตารางข้อมูล

โครงสร้างของตารางประวัติจะเหมือนกับตารางข้อมูลที่ติดตามยกเว้นคอลัมน์เพิ่มเติมสามคอลัมน์: คอลัมน์สำหรับจัดเก็บการดำเนินการที่เกิดขึ้น (เรียกว่า 'การกระทำ') วันที่และเวลาของการดำเนินการและคอลัมน์ เพื่อจัดเก็บหมายเลขลำดับ ('การแก้ไข') ซึ่งจะเพิ่มขึ้นต่อการดำเนินการและจัดกลุ่มตามคอลัมน์คีย์หลักของตารางข้อมูล

ในการทำพฤติกรรมการเรียงลำดับนี้ดัชนีสองคอลัมน์ (คอมโพสิต) จะถูกสร้างขึ้นบนคอลัมน์คีย์หลักและคอลัมน์การแก้ไข โปรดทราบว่าคุณสามารถจัดลำดับได้เฉพาะในกรณีที่เอ็นจิ้นที่ใช้ในตารางประวัติคือ MyISAM ( ดู 'บันทึก MyISAM' ในหน้านี้)

ตารางประวัติค่อนข้างง่ายในการสร้าง ในแบบสอบถาม ALTER TABLE ด้านล่าง (และในแบบสอบถามทริกเกอร์ด้านล่าง) ให้แทนที่ 'primary_key_column' ด้วยชื่อจริงของคอลัมน์นั้นในตารางข้อมูลของคุณ

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

Edit: โอ้ว้าวคนชอบตารางประวัติของฉันเมื่อ 6 ปีที่แล้ว: P

การใช้งานของฉันยังคงฮัมเพลงไปพร้อม ๆ กันการใหญ่ขึ้นและเทอะทะมากขึ้นฉันคิดว่า ฉันเขียนมุมมองและ UI ที่สวยงามเพื่อดูประวัติในฐานข้อมูลนี้ แต่ฉันไม่คิดว่ามันเคยถูกใช้มากนัก มันจะไป

ในการจัดการกับความคิดเห็นบางส่วนตามลำดับ:

  • ฉันใช้งาน PHP ของตัวเองซึ่งเกี่ยวข้องมากกว่าเล็กน้อยและหลีกเลี่ยงปัญหาบางอย่างที่อธิบายไว้ในความคิดเห็น (มีการโอนดัชนีไปอย่างมีนัยสำคัญหากคุณถ่ายโอนดัชนีที่ไม่ซ้ำกันไปยังตารางประวัติสิ่งต่างๆจะพังมีวิธีแก้ไขสำหรับ นี้ในความคิดเห็น) การติดตามโพสต์นี้ไปยังจดหมายอาจเป็นการผจญภัยขึ้นอยู่กับว่าฐานข้อมูลของคุณเป็นอย่างไร

  • หากความสัมพันธ์ระหว่างคีย์หลักและคอลัมน์การแก้ไขดูเหมือนปิดอยู่ก็มักจะหมายความว่าคีย์คอมโพสิตนั้นมีปัญหา มีบางครั้งที่เกิดขึ้นได้ยากและสูญเสียสาเหตุ

  • ฉันพบว่าโซลูชันนี้มีประสิทธิภาพโดยใช้ทริกเกอร์เหมือนเดิม นอกจากนี้ MyISAM ยังเร็วในการแทรกซึ่งเป็นตัวกระตุ้นทั้งหมด คุณสามารถปรับปรุงสิ่งนี้เพิ่มเติมได้ด้วยการจัดทำดัชนีอัจฉริยะ (หรือขาด ... ) การแทรกแถวเดียวลงในตาราง MyISAM ด้วยคีย์หลักไม่ควรเป็นการดำเนินการที่คุณต้องปรับให้เหมาะสมจริง ๆ เว้นแต่คุณจะมีปัญหาสำคัญเกิดขึ้นที่อื่น ตลอดเวลาที่ฉันใช้งานฐานข้อมูล MySQL การใช้งานตารางประวัตินี้เปิดใช้งานอยู่มันไม่เคยเป็นสาเหตุของปัญหาประสิทธิภาพการทำงาน (หลายอย่าง) ที่เกิดขึ้น

  • หากคุณได้รับการแทรกซ้ำให้ตรวจสอบเลเยอร์ซอฟต์แวร์ของคุณสำหรับการค้นหาประเภท INSERT IGNORE อืมตอนนี้จำไม่ได้แล้ว แต่ฉันคิดว่ามีปัญหากับโครงการนี้และธุรกรรมซึ่งในที่สุดก็ล้มเหลวหลังจากเรียกใช้การดำเนินการ DML หลายรายการ สิ่งที่ควรระวังอย่างน้อยที่สุด

  • สิ่งสำคัญคือฟิลด์ในตารางประวัติและตารางข้อมูลจะต้องตรงกัน หรือว่าตารางข้อมูลของคุณไม่มีคอลัมน์มากกว่าตารางประวัติ มิฉะนั้นการค้นหาการแทรก / อัปเดต / เดลในตารางข้อมูลจะล้มเหลวเมื่อการแทรกในตารางประวัติทำให้คอลัมน์ในแบบสอบถามไม่มีอยู่ (เนื่องจาก d. * ในแบบสอบถามทริกเกอร์) และทริกเกอร์ล้มเหลว จะดีมากถ้า MySQL มีบางอย่างเช่นสคีมาทริกเกอร์ซึ่งคุณสามารถเปลี่ยนตารางประวัติได้หากมีการเพิ่มคอลัมน์ลงในตารางข้อมูล ตอนนี้ MySQL มีหรือไม่? ฉันทำปฏิกิริยาในวันนี้: P


3
ฉันชอบวิธีนี้มาก อย่างไรก็ตามหากตารางหลักของคุณไม่มีคีย์หลักหรือคุณไม่รู้ว่าตารางหลักคืออะไรก็ค่อนข้างยุ่งยาก
Benjamin Eckstein

1
เมื่อเร็ว ๆ นี้ฉันพบปัญหาในการใช้โซลูชันนี้สำหรับโครงการเนื่องจากวิธีการคัดลอกดัชนีทั้งหมดจากตารางต้นฉบับไปยังตารางประวัติ (เนื่องจากวิธีการสร้างตาราง ... LIKE .... ใช้งานได้) การมีดัชนีที่ไม่ซ้ำกันในตารางประวัติอาจทำให้แบบสอบถาม INSERT ในทริกเกอร์ AFTER UPDATE เป็น barf ดังนั้นจึงจำเป็นต้องลบออก ในสคริปต์ php ที่ฉันมีสิ่งนี้ฉันค้นหาดัชนีที่ไม่ซ้ำกันในตารางประวัติที่สร้างขึ้นใหม่ (ด้วย "SHOW INDEX FROM data_table WHERE Key_name! = 'PRIMARY' และ Non_unique = 0") จากนั้นจึงลบออก
ปิดชั่วคราว

3
ที่นี่เราจะได้รับข้อมูลซ้ำแทรกในตารางสำรองทุกครั้ง ให้ถ้าเรามี 10 ช่องในตารางและเราอัปเดต 2 แล้วเราจะเพิ่มข้อมูลซ้ำสำหรับส่วนที่เหลือ 8 ช่อง จะเอาชนะมันได้อย่างไร?
itzmukeshy7

6
คุณสามารถหลีกเลี่ยงการใช้ดัชนีต่างๆโดยไม่ได้ตั้งใจโดยเปลี่ยนคำสั่ง create table เป็นCREATE TABLE MyDB.data_history as select * from MyDB.data limit 0;
Eric Hayes

4
@transientclosure คุณจะเสนอให้รับฟิลด์อื่น ๆ ในประวัติที่ไม่ได้เป็นส่วนหนึ่งของข้อความค้นหาเดิมได้อย่างไร เช่นฉันต้องการติดตามว่าใครเป็นผู้ทำการเปลี่ยนแปลงเหล่านั้น สำหรับการแทรกนั้นมีownerฟิลด์อยู่แล้วและสำหรับการอัปเดตฉันสามารถเพิ่มupdatedbyฟิลด์ได้ แต่สำหรับการลบฉันไม่แน่ใจว่าจะทำได้อย่างไรผ่านทริกเกอร์ การอัปเดตdata_historyแถวด้วยรหัสผู้ใช้รู้สึกสกปรก: P
Horse

16

คุณสามารถสร้างทริกเกอร์เพื่อแก้ปัญหานี้ได้ นี่คือบทช่วยสอน (ลิงก์ที่เก็บถาวร)

การตั้งค่าข้อ จำกัด และกฎในฐานข้อมูลดีกว่าการเขียนโค้ดพิเศษเพื่อจัดการงานเดียวกันเนื่องจากจะป้องกันไม่ให้นักพัฒนารายอื่นเขียนแบบสอบถามอื่นที่ข้ามรหัสพิเศษทั้งหมดและอาจทำให้ฐานข้อมูลของคุณมีความสมบูรณ์ของข้อมูลไม่ดี

เป็นเวลานานที่ฉันคัดลอกข้อมูลไปยังตารางอื่นโดยใช้สคริปต์เนื่องจาก MySQL ไม่รองรับทริกเกอร์ในเวลานั้น ตอนนี้ฉันพบว่าทริกเกอร์นี้มีประสิทธิภาพมากขึ้นในการติดตามทุกอย่าง

ทริกเกอร์นี้จะคัดลอกค่าเก่าไปยังตารางประวัติหากมีการเปลี่ยนแปลงเมื่อมีคนแก้ไขแถว Editor IDและlast modจะถูกเก็บไว้ในตารางเดิมทุกครั้งที่มีคนแก้ไขแถวนั้น เวลาตรงกับเวลาที่เปลี่ยนเป็นรูปแบบปัจจุบัน

DROP TRIGGER IF EXISTS history_trigger $$

CREATE TRIGGER history_trigger
BEFORE UPDATE ON clients
    FOR EACH ROW
    BEGIN
        IF OLD.first_name != NEW.first_name
        THEN
                INSERT INTO history_clients
                    (
                        client_id    ,
                        col          ,
                        value        ,
                        user_id      ,
                        edit_time
                    )
                    VALUES
                    (
                        NEW.client_id,
                        'first_name',
                        NEW.first_name,
                        NEW.editor_id,
                        NEW.last_mod
                    );
        END IF;

        IF OLD.last_name != NEW.last_name
        THEN
                INSERT INTO history_clients
                    (
                        client_id    ,
                        col          ,
                        value        ,
                        user_id      ,
                        edit_time
                    )
                    VALUES
                    (
                        NEW.client_id,
                        'last_name',
                        NEW.last_name,
                        NEW.editor_id,
                        NEW.last_mod
                    );
        END IF;

    END;
$$

อีกวิธีหนึ่งคือเก็บฟิลด์ Revision ไว้และอัปเดตฟิลด์นี้เมื่อบันทึก คุณสามารถตัดสินใจได้ว่าค่าสูงสุดคือการแก้ไขล่าสุดหรือ 0 คือแถวล่าสุด ขึ้นอยู่กับคุณ


9

นี่คือวิธีที่เราแก้ไข

ตารางผู้ใช้มีลักษณะเช่นนี้

Users
-------------------------------------------------
id | name | address | phone | email | created_on | updated_on

และความต้องการทางธุรกิจก็เปลี่ยนไปและเราจำเป็นต้องตรวจสอบที่อยู่และหมายเลขโทรศัพท์ก่อนหน้านี้ทั้งหมดที่ผู้ใช้เคยมี สคีมาใหม่มีลักษณะดังนี้

Users (the data that won't change over time)
-------------
id | name

UserData (the data that can change over time and needs to be tracked)
-------------------------------------------------
id | id_user | revision | city | address | phone | email | created_on
 1 |   1     |    0     | NY   | lake st | 9809  | @long | 2015-10-24 10:24:20
 2 |   1     |    2     | Tokyo| lake st | 9809  | @long | 2015-10-24 10:24:20
 3 |   1     |    3     | Sdny | lake st | 9809  | @long | 2015-10-24 10:24:20
 4 |   2     |    0     | Ankr | lake st | 9809  | @long | 2015-10-24 10:24:20
 5 |   2     |    1     | Lond | lake st | 9809  | @long | 2015-10-24 10:24:20

ในการค้นหาที่อยู่ปัจจุบันของผู้ใช้ใด ๆ เราค้นหา UserData ด้วยการแก้ไข DESC และ LIMIT 1

ในการรับที่อยู่ของผู้ใช้ระหว่างช่วงเวลาหนึ่งเราสามารถใช้ created_on bewteen (date1, วันที่ 2)


เป็นวิธีแก้ปัญหาที่ฉันต้องการ แต่ฉันต้องการทราบว่าคุณจะแทรก id_user ในตารางนี้โดยใช้ trigger ได้อย่างไร?
thecassion

1
เกิดอะไรขึ้นกับrevision=1ของid_user=1? ก่อนอื่นฉันคิดว่าการนับของคุณเป็น0,2,3,...แต่แล้วฉันก็เห็นว่าสำหรับid_user=2การนับการแก้ไขคือ0,1, ...
Pathros

1
คุณไม่จำเป็นต้องidและid_userคอลัมน์. Just use a group ID of id` (ID ผู้ใช้) revisionและ
Gajus

6

MariaDB รองรับ System Versioning ตั้งแต่ 10.3 ซึ่งเป็นคุณสมบัติ SQL มาตรฐานที่ทำสิ่งที่คุณต้องการ: เก็บประวัติของบันทึกตารางและให้การเข้าถึงผ่านSELECTแบบสอบถาม MariaDB เป็นส่วนแยกการพัฒนาแบบเปิดของ MySQL คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับ System Versioning ได้จากลิงค์นี้:

https://mariadb.com/kb/en/library/system-versioned-tables/


โปรดสังเกตสิ่งต่อไปนี้จากลิงก์ด้านบน: "mysqldump ไม่อ่านแถวประวัติจากตารางเวอร์ชันดังนั้นข้อมูลประวัติจะไม่ถูกสำรองนอกจากนี้การเรียกคืนการประทับเวลาจะไม่สามารถทำได้เนื่องจากไม่สามารถกำหนดโดยการแทรก / ผู้ใช้ "
Daniel

4

ทำไมไม่ใช้แค่ไฟล์บันทึก bin? หากตั้งค่าการจำลองแบบบนเซิร์ฟเวอร์ Mysql และรูปแบบไฟล์ binlog ถูกตั้งค่าเป็น ROW การเปลี่ยนแปลงทั้งหมดจะถูกบันทึก

สามารถใช้ไลบรารี python ที่เรียกว่า noplay ได้ ข้อมูลเพิ่มเติมที่นี่


2
สามารถใช้ Binlog ได้แม้ว่าคุณจะไม่มี / ต้องการการจำลองแบบก็ตาม Binlog มีกรณีการใช้งานที่เป็นประโยชน์มากมาย การจำลองแบบอาจเป็นกรณีการใช้งานที่พบบ่อยที่สุด แต่ยังสามารถใช้ประโยชน์จากการสำรองข้อมูลและประวัติการตรวจสอบดังที่กล่าวไว้ที่นี่
webaholik

3

แค่ 2 เซ็นต์ของฉัน ฉันจะสร้างโซลูชันที่บันทึกสิ่งที่เปลี่ยนแปลงซึ่งคล้ายกับโซลูชันของชั่วคราว

My ChangesTable จะง่ายมาก:

DateTime | WhoChanged | TableName | Action | ID |FieldName | OldValue

1) เมื่อทั้งแถวมีการเปลี่ยนแปลงในตารางหลักรายการจำนวนมากจะเข้าสู่ตารางนี้ แต่ไม่น่าจะเป็นไปได้มากนักจึงไม่ใช่ปัญหาใหญ่ (โดยปกติผู้คนมักจะเปลี่ยนเพียงสิ่งเดียว) 2) OldVaue (และ NewValue ถ้าคุณ ต้องการ) ต้องเป็น "ประเภทใด ๆ " ที่ยิ่งใหญ่เนื่องจากอาจเป็นข้อมูลใดก็ได้อาจมีวิธีดำเนินการกับประเภท RAW หรือใช้สตริง JSON เพื่อแปลงเข้าและออก

การใช้ข้อมูลขั้นต่ำจัดเก็บทุกสิ่งที่คุณต้องการและสามารถใช้ได้กับทุกตารางในครั้งเดียว ตอนนี้ฉันกำลังค้นคว้าเรื่องนี้ด้วยตัวเอง แต่มันอาจจะเป็นวิธีที่ฉันไป

สำหรับสร้างและลบเพียง ID แถวไม่จำเป็นต้องมีฟิลด์ ในการลบแฟล็กบนตารางหลัก (ใช้งานอยู่?) จะดี


0

วิธีโดยตรงในการทำเช่นนี้คือการสร้างทริกเกอร์บนตาราง กำหนดเงื่อนไขหรือวิธีการทำแผนที่ เมื่อเกิดการอัปเดตหรือลบมันจะแทรกลงในตาราง 'เปลี่ยนแปลง' โดยอัตโนมัติ

แต่ส่วนที่ใหญ่ที่สุดคือถ้าเรามีคอลัมน์จำนวนมากและตารางจำนวนมาก เราต้องพิมพ์ชื่อทุกคอลัมน์ของทุกตาราง เห็นได้ชัดว่ามันเสียเวลา

เพื่อจัดการสิ่งนี้ให้สวยงามยิ่งขึ้นเราสามารถสร้างขั้นตอนหรือฟังก์ชั่นบางอย่างเพื่อดึงชื่อคอลัมน์

เรายังสามารถใช้เครื่องมือส่วนที่ 3 เพื่อทำสิ่งนี้ได้ ที่นี่ฉันเขียนโปรแกรม java Mysql Tracker


ฉันจะใช้ Mysql Tracker ของคุณได้อย่างไร
webchun

1
1. ตรวจสอบว่าคุณมีคอลัมน์ id เป็นคีย์หลักในแต่ละตาราง 2. คัดลอกไฟล์ java ไปยังโลคัล (หรือ IDE) 3. นำเข้า libs และแก้ไขตัวแปรแบบคงที่จากบรรทัดที่ 9-15 ตามการกำหนดค่าและโครงสร้างฐานข้อมูลของคุณ 4. แยกวิเคราะห์และเรียกใช้ไฟล์ java 5. คัดลอกบันทึกคอนโซลและดำเนินการเป็นคำสั่ง Mysql
goforu

create table like tableฉันคิดว่าจำลองคอลัมน์ทั้งหมดได้อย่างง่ายดาย
โจนาธาน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.