mysql - 如何查找最近一小时内添加或更新的 MySQL Views 或 Triggers?

标签 mysql

我需要跟踪数据库更改。已经可以从相关的 INFORMATION_SCHEMA 表中获取表、函数和存储过程的信息。但在 View 和触发器的情况下,似乎没有 CREATED 或 MODIFIED DateTime 的数据。如何实现?

最佳答案

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

CREATED: The date and time when the trigger was created. This is a TIMESTAMP(2) value (with a fractional part in hundredths of seconds) for triggers created in MySQL 5.7.2 or later, NULL for triggers created prior to 5.7.2.

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

解决方法:“快照”表

使用每小时运行一次的 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)

限制

这些不会告诉您更改的确切时间,也不会准确涵盖最后一个小时 - 仅包含自上次快照以来的时间,可能是最后一个小时内的任何时间。如果需要比这更高的准确性,则可以减少快照间隔 - 但这会增加复杂性,因为可能需要维护多个快照并使用正确的快照进行比较。

关于mysql - 如何查找最近一小时内添加或更新的 MySQL Views 或 Triggers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40758842/

相关文章:

javascript - 我在命令提示符下从 MySQL 获取值。但是这些值如何在聊天机器人中显示呢?

mysql - 如何删除 'duplicate'记录?

python - 使用 Python 3 从 Mysql 检索和选择二进制值

Mysql转义函数;使用选择查询生成更新查询

python - Mysql和python数据太长

MySQL继承?

mysql - 将 INDEX 应用于外键的正确方法

mysql - 如何在knexjs中按计算列排序

mysql - 我如何获取查询列表及其执行计数

javascript - Rails 使用变量运行 sql 查询