如何查找过去一小时内添加或更新的MySQL视图或触发器?

时间:2016-11-23 07:57:09

标签: mysql

我需要跟踪数据库更改。可以从相关的INFORMATION_SCHEMA表中获取表,函数和存储过程的此信息。但在视图和触发器的情况下,似乎不是CREATED或MODIFIED DateTime的数据。如何实现这一目标?

3 个答案:

答案 0 :(得分:5)

对于触发器的“已创建”日期/时间,CREATED中有INFORMATION_SCHEMA.TRIGGERS字段。但根据MySQL documentation,这只能在MySQL 5.7.2或更高版本中正确填充:

  

创建:创建触发器的日期和时间。这是一个   TIMESTAMP(2)值(以百分之一秒为单位)   对于在MySQL 5.7.2或更高版本中创建的触发器,对于触发器为NULL   在5.7.2之前创建。

但遗憾的是,没有等效的“更新”或“已删除”日期/时间列,INFORMATION_SCHEMA.VIEWS表没有任何这些。我对可能的解决方法的第一个想法是在相关的INFORMATION_SCHEMA表上创建触发器,但不幸的是,这似乎不可能,因为INFORMATION_SCHEMA表实际上更像是“视图”(但不是基于实际表格)。因此,以下“次佳”解决方案......

解决方法:“快照”表格

使用每小时运行一次的MySQL事件调度程序创建一个预定事件,并运行查询以将INFORMATION_SCHEMA.TRIGGERSINFORMATION_SCHEMA.VIEWS表的内容复制到本地数据库中的“快照”表中:

-- Remove existing event of this name if there is one
DROP EVENT IF EXISTS update_snapshots;

DELIMITER $$
CREATE EVENT update_snapshots ON SCHEDULE EVERY 1 HOUR 
    DO BEGIN
        -- Drop the current snapshot table (if there is one)
        DROP TABLE IF EXISTS triggers_snapshot;
        DROP TABLE IF EXISTS views_snapshot;

        -- Recreate snapshot tables
        CREATE TABLE triggers_snapshot AS SELECT * FROM INFORMATION_SCHEMA.TRIGGERS;
        CREATE TABLE views_snapshot AS SELECT * FROM INFORMATION_SCHEMA.VIEWS;
    END $$
DELIMITER ;

-- Turn the MySQL event scheduler on
SET GLOBAL event_scheduler = ON;

-- Show all events (to check it was created successfully and its status)
SHOW EVENTS;

然后,在任何时候都可以查询当前INFORMATION_SCHEMA表,并使用this one等技术与快照进行比较:

SELECT  'new' AS `status`, s.*
FROM    INFORMATION_SCHEMA.TRIGGERS s
WHERE   ROW(s.TRIGGER_CATALOG, s.TRIGGER_SCHEMA, s.TRIGGER_NAME, s.EVENT_MANIPULATION,
            s.EVENT_OBJECT_CATALOG, s.EVENT_OBJECT_SCHEMA, s.EVENT_OBJECT_TABLE,
            s.ACTION_ORDER, s.ACTION_CONDITION, s.ACTION_STATEMENT, s.ACTION_ORIENTATION,
            s.ACTION_TIMING, s.ACTION_REFERENCE_OLD_TABLE, s.ACTION_REFERENCE_NEW_TABLE,
            s.ACTION_REFERENCE_OLD_ROW, s.ACTION_REFERENCE_NEW_ROW, s.CREATED, s.SQL_MODE,
            s.DEFINER, s.CHARACTER_SET_CLIENT, s.COLLATION_CONNECTION, 
            s.DATABASE_COLLATION) NOT IN (SELECT * FROM triggers_snapshot)
UNION ALL
SELECT  'old' AS `status`, t.*
FROM    triggers_snapshot t
WHERE   ROW(t.TRIGGER_CATALOG, t.TRIGGER_SCHEMA, t.TRIGGER_NAME, t.EVENT_MANIPULATION,
            t.EVENT_OBJECT_CATALOG, t.EVENT_OBJECT_SCHEMA, t.EVENT_OBJECT_TABLE,
            t.ACTION_ORDER, t.ACTION_CONDITION, t.ACTION_STATEMENT, t.ACTION_ORIENTATION,
            t.ACTION_TIMING, t.ACTION_REFERENCE_OLD_TABLE, t.ACTION_REFERENCE_NEW_TABLE,
            t.ACTION_REFERENCE_OLD_ROW, t.ACTION_REFERENCE_NEW_ROW, t.CREATED, t.SQL_MODE,
            t.DEFINER, t.CHARACTER_SET_CLIENT, t.COLLATION_CONNECTION, 
            t.DATABASE_COLLATION) NOT IN (SELECT * FROM INFORMATION_SCHEMA.TRIGGERS)

...和...

SELECT  'new' AS `status`, s.*
FROM    INFORMATION_SCHEMA.VIEWS s
WHERE   ROW(s.TABLE_CATALOG, s.TABLE_SCHEMA, s.TABLE_NAME, s.VIEW_DEFINITION,
            s.CHECK_OPTION, s.IS_UPDATABLE, s.DEFINER, s.SECURITY_TYPE,
            s.CHARACTER_SET_CLIENT, s.COLLATION_CONNECTION)
        NOT IN (SELECT * FROM views_snapshot)
UNION ALL
SELECT  'old' AS `status`, t.*
FROM    views_snapshot t
WHERE   ROW(t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME, t.VIEW_DEFINITION,
            t.CHECK_OPTION, t.IS_UPDATABLE, t.DEFINER, t.SECURITY_TYPE,
            t.CHARACTER_SET_CLIENT, t.COLLATION_CONNECTION)
        NOT IN (SELECT * FROM INFORMATION_SCHEMA.VIEWS)

<强>限制

这些不会确切地告诉您何时进行了更改并且没有完全覆盖最后一小时 - 仅限于自上次快照以来的时间,这可能是过去一小时内的任何时间。如果需要更高的准确度,可以减少快照间隔 - 但这会增加复杂性,因为可能需要维护多个快照并使用正确的快照进行比较。

答案 1 :(得分:1)

转到您的数据目录并检查修改日期时间

答案 2 :(得分:1)

如果它只是纯粹的结构变化,你只需要跟踪它们,那么另一种方法是使用mysqldump,它将为你提供所有当前的结构:

skip-comments

使用mysqldump --no-data --skip-comments dbname > /tmp/schema1.sql # (wait) mysqldump --no-data --skip-comments dbname > /tmp/schema2.sql diff /tmp/schema1.sql /tmp/schema2.sql 选项,它随着时间的推移会保持一致,只有在结构发生变化时才会改变。你可以区分它:

mysqldump --no-data --skip-comments dbname > schema.sql && git commit -m "MySQL schema change" schema.sql

甚至可以将一个文件放入一个版本控制系统中,这样你就可以使用hooks&amp;其他&#39;更改触发器&#39;:

class DocumentAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        super(DocumentAdmin, self).save_model(request, obj, form, change)
        obj.set_statistics()

显然,这些方法并不能为您提供有关何时,或者为何/为何进行更改的任何信息。