【问题标题】:How to find MySQL Views or Triggers that have been added or updated in the last hour?如何查找最近一小时内添加或更新的 MySQL 视图或触发器?
【发布时间】:2016-12-20 22:44:13
【问题描述】:

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

【问题讨论】:

  • No mysql 不支持这样的跟踪器。我可能会建议您将这些触发器和视图放在一个表中。在表更改时,您将运行触发器来更改特定的触发器/视图代码。在此之前,您必须将之前的触发器/视图转储到 dump 触发器/视图表中。
  • 您使用的是哪个版本的 MySQL?

标签: mysql


【解决方案1】:

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

CREATED:创建触发器的日期和时间。这是一个 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;

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

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)

限制

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

【讨论】:

  • 通过使用上面的代码,我们无法获得更新的视图。实际上我需要在开发人员之间同步数据库,所以我需要找到更新或创建的视图、触发器、函数、过程
【解决方案2】:

进入你的数据目录,查看修改后的日期时间

【讨论】:

    【解决方案3】:

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

    mysqldump --no-data --skip-comments dbname
    

    使用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
    

    显然,这些方法不会为您提供有关更改的确切时间或更改的人员/原因的任何信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-06
      • 1970-01-01
      • 2016-12-09
      • 2013-09-25
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 1970-01-01
      相关资源
      最近更新 更多