当某个字段发生更改时,我需要创建表行的更改历史记录。所以我想做的是在表更新时创建一个触发器。当字段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;
$$
我之所以要这样做,是因为我们(可能)有一个php脚本,其中有一个bug,它将相同的文本字符串写入数据库的每个字段,但我们不知道它何时或为什么发生,也不知道它执行的是哪个脚本。有没有更优雅的解决方案?
更新:我在phpMyAdmin中找到了“Track Changes”选项,但显然它没有跟踪我们的程序php发出的
UPDATE
查询,但是来自php的DROP
和CREATE TABLE
语句被跟踪了。如果我通过phpMyAdmin发出UPDATE
,它将被跟踪。长话短说,我带着扳机回到了原来的计划。更新2:自己找到答案
最佳答案
更新:根据OP的评论,显然上下文非常具体。一个不能访问(或者不能反馈和指导开发团队的)代码的基础架构团队需要一种机制,通过这种机制可以将表更改记录到生产数据库中。
有关使用触发器的警告:
触发器可能很难调试,尤其是因为它们是透明的,而且对于代码的新用户来说,触发器在幕后执行某些操作是不明显的。(我从经验上讲)它们还可能导致replicated、多主机和群集安装出现问题。(再说一遍,我是从经验上讲的)同样,如果它们因为一些不相关的原因而失败(例如,它们写入的表被破坏了),整个事务可以/将失败(InnoDB)-这可能不是您想要的。(尤其是非必要的“调试”功能。)
否则,触发器是完全有效的工具。在你的特定场景中,可能是最好的选择。
您还可以选择其他几个选项,其中有两个我要强调:
存储过程作为数据访问层
如果您非常以数据为中心,并且您已经在数据库中拥有了业务逻辑(这是一个备受争议的话题,我在这里不是说您应该或不应该在数据库中拥有业务逻辑),那么通过存储过程读写数据库具有明显的优势。
任何事务绑定的逻辑都可以插入到这些存储过程中,这样事务不安全的调用方(PHP是一个常见的示例)只需要调用1个查询(call sp_insert_tablename(123, 'abc')
),并且事务安全性可以由数据库强制执行。
临时调试逻辑可以添加到这些存储过程中,并由设置表、会话变量、最终参数中的标志启用/禁用,无论您需要什么。
数据抽象层/库
类似的原则。为您的客户机找到一个数据抽象层(假设您有权更改它的内部结构)。对于PHP或.NET web应用程序,有几个流行的选项,所有这些选项都允许您重写(通过代码继承扩展)save/delete操作,以执行您想要的任何其他操作—与存储过程完全相同(但在客户端的模型中保持逻辑)。
如果你想要一个具体的例子,你需要给我们更多关于你使用的栈/语言/框架的信息
使用这两个选项时,请确保正确处理错误场景。
关于mysql - 如何为表创建更改日志?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45586556/