代码之家  ›  专栏  ›  技术社区  ›  siryx

如何为表创建变更日志?

  •  2
  • siryx  · 技术社区  · 7 年前

    当某个字段发生更改时,我需要创建表行的更改历史记录。所以我想做的是在表更新时创建一个触发器。当现场 txta 更改,我希望将整行复制到 debug 这是的克隆版本 msser_210 最后添加了datetime列,没有数据。我想补充一点 NOW()

    DELIMITER $$
    CREATE TRIGGER history_trigger
    BEFORE UPDATE ON msser_210
        FOR EACH ROW
            BEGIN
            IF OLD.txta != NEW.txta
            THEN
                INSERT INTO `debug_history` (`idpm`,`posn`,`prnb`,`doid`,`ofcr`,`pidm`,`hitm`,`sitm`,`item`,`dsca`,`igid`,`kitm`,`leng`,`widt`,`hght`,`thik`,`radi`,`quas`,`wght`,`effc`,`colr`,`bdat`,`edat`,`back`,`cuid`,`intb`,`aggr`,`unqu`,`oqua`,`unsq`,`stoc`,`allo`,`hall`,`tqan`,`bqan`,`pkey`,`pric`,`cvqs`,`unsp`,`disc`,`dart`,`ksid`,`anhg`,`txta`,`txti`,`mndn`, `changedate`) VALUES (OLD.idpm,OLD.posn,OLD.prnb,OLD.doid,OLD.ofcr,OLD.pidm,OLD.hitm,OLD.sitm,OLD.item,OLD.dsca,OLD.igid,OLD.kitm,OLD.leng,OLD.widt,OLD.hght,OLD.thik,OLD.radi,OLD.quas,OLD.wght,OLD.effc,OLD.colr,OLD.bdat,OLD.edat,OLD.back,OLD.cuid,OLD.intb,OLD.aggr,OLD.unqu,OLD.oqua,OLD.unsq,OLD.stoc,OLD.allo,OLD.hall,OLD.tqan,OLD.bqan,OLD.pkey,OLD.pric,OLD.cvqs,OLD.unsp,OLD.disc,OLD.dart,OLD.ksid,OLD.anhg,OLD.txta,OLD.txti, OLD.mndn, NOW());
        END IF;
    END;
    $$
    

    我之所以想这样做是因为我们有一个(可能)带有bug的php脚本,它将相同的文本字符串写入数据库的每个字段,但我们不知道它发生的时间或原因,也不知道它发生的是哪个脚本。有没有更优雅的解决方案?

    更新:我在phpMyAdmin中找到了“跟踪更改”的选项,但显然它不跟踪我们的php发布的程序 UPDATE DROP CREATE TABLE 不过,PHP的语句是可以跟踪的。如果我发布 更新 通过phpMyAdmin,它被跟踪。长话短说,我带着扳机回到了最初的计划。

    2 回复  |  直到 7 年前
        1
  •  1
  •   wally    7 年前

    使现代化 :根据OP的评论,显然上下文非常具体。对于无法访问(或无法反馈和指导开发团队)代码的基础架构团队,需要一种机制来记录生产数据库中的表更改。

    :

    触发器可能很难调试,尤其是因为它们是透明的,而且对于刚看过你的代码的人来说,触发器在幕后执行某些操作从来都不明显。(我是凭经验说的。)它们也会在 replicated 、多主机和群集安装。(同样,我是根据经验说的。)此外,如果他们由于一些不相关的原因(例如,他们写的表坏了)而失败,那么 全部的 事务可以/将失败(InnoDB)-这可能不是您想要的。(尤其是非必要的“调试”功能。)

    您还可以选择其他几个选项,我要强调其中两个选项:

    如果您非常以数据为中心,并且在数据库中已经有了业务逻辑(这是一个备受争议的话题,我不是在这里争论您应该或者不应该在数据库中有业务逻辑),那么通过存储过程对数据库进行读写具有明显的优势。

    任何 可以将逻辑插入这些存储过程中,以便 交易不安全 call sp_insert_tablename(123, 'abc') )事务安全可以通过数据库来实现。

    数据抽象层/库

    使用这两种选项,请确保适当地处理错误场景。

        2
  •  0
  •   siryx    7 年前

    这个 debug_history 是从原始表中通过pypMyAdmin克隆的。它手动添加了一个额外的changedate列。

    ALTER TABLE debug_history ADD COLUMN changedate DATETIME DEFAULT NULL;
    

    INSERT INTO -用于重建的文件中的语句 msser_210 并改变了数值。

    ALTER TABLE debug_history DROP PRIMARY KEY;
    ALTER TABLE debug_history ADD COLUMN changenumber INT NOT NULL PRIMARY KEY AUTO_INCREMENT;
    

    txta txta公司 txta_old 并创建了一个新列 txta_new .

    ALTER TABLE debug_history CHANGE txta txta_old TEXT NOT NULL $$
    ALTER TABLE debug_history ADD COLUMN txta_new TEXT NOT NULL AFTER txta_old $$
    

    DROP TRIGGER history_trigger
    DELIMITER $$
    CREATE TRIGGER history_trigger
    BEFORE UPDATE ON msser_210
        FOR EACH ROW
            BEGIN
            IF OLD.txta != NEW.txta
            THEN
                INSERT INTO `debug_history` (`idpm`,`posn`,`prnb`,`doid`,`ofcr`,`pidm`,`hitm`,`sitm`,`item`,`dsca`,`igid`,`kitm`,`leng`,`widt`,`hght`,`thik`,`radi`,`quas`,`wght`,`effc`,`colr`,`bdat`,`edat`,`back`,`cuid`,`intb`,`aggr`,`unqu`,`oqua`,`unsq`,`stoc`,`allo`,`hall`,`tqan`,`bqan`,`pkey`,`pric`,`cvqs`,`unsp`,`disc`,`dart`,`ksid`,`anhg`,`txta_old`,`txta_new`,`txti`,`mndn`, `changedate`) VALUES (OLD.idpm,OLD.posn,OLD.prnb,OLD.doid,OLD.ofcr,OLD.pidm,OLD.hitm,OLD.sitm,OLD.item,OLD.dsca,OLD.igid,OLD.kitm,OLD.leng,OLD.widt,OLD.hght,OLD.thik,OLD.radi,OLD.quas,OLD.wght,OLD.effc,OLD.colr,OLD.bdat,OLD.edat,OLD.back,OLD.cuid,OLD.intb,OLD.aggr,OLD.unqu,OLD.oqua,OLD.unsq,OLD.stoc,OLD.allo,OLD.hall,OLD.tqan,OLD.bqan,OLD.pkey,OLD.pric,OLD.cvqs,OLD.unsp,OLD.disc,OLD.dart,OLD.ksid,OLD.anhg,OLD.txta,NEW.txta,OLD.txti, OLD.mndn, NOW());
            END IF;
        END;
    $$