具有复杂可配置条件的触发器

时间:2014-03-04 09:04:54

标签: mysql configuration triggers

一些背景

我们有一个系统可选择集成到其他几个系统。我们的系统将数据从MySQL数据库转移到其他系统。不同的客户想要传输不同的数据为了不向这些外部系统触发不必要的传输(当没有相关数据发生变化时),我们有一个“导出”表,其中包含任何客户感兴趣的所有信息,以及运行在文件中定义的SQL查询的服务进行比较导出表中的数据到其他表中的数据并根据需要更新导出表,这个解决方案由于以下几个原因我们并不满意:

  • 没有客户使用这些列的一小部分,尽管每列至少有一个客户使用。
  • 随着数据库的增长,该服务正在对系统造成越来越大的压力。有些服务器会在此服务比较数据时完全冻结,这可能需要2分钟(!),即使没有客户拥有特别大量的数据(所有相关表中的最大行数约为15000行)。我们担心如果我们的客户拥有大量数据,可能会发生什么。通过创建一些索引和改进SQL查询可以提高性能,但我们觉得这样可以从错误的方向攻击问题。
  • 它不是很灵活,也不是可扩展的。每当客户有兴趣转移其他客户之前没有感兴趣的数据(这种情况经常发生)时,必须添加新列,感觉...... icky。我不知道它到底有多重要,但我们目前在这张表中最多有37列,而且它还在不断增长。

我们想做什么

相反,我们希望有一个非常精简的“导出”表,它只包含最小的信息,即更新的行的表和主键,此行应导出的系统,以及一些时间戳。每当更新已配置为保证更新的列时,每个相关表中的触发器都将更新此导出表。应该从另一个表中读取此配置(将来某个时候,可以从我们的Web GUI配置),看起来像这样:

+--------+--------+-----------+
| system |  table |  column   |
+--------+--------+-----------+
| 'sys1' | 'tbl1' | 'column1' |
+--------+--------+-----------+
| 'sys2' | 'tbl1' | 'column2' |
+--------+--------+-----------+

现在,当更新行时,tbl1中的触发器将从此表中读取。上面的配置应该意味着如果tbl1中的column1已更改,则应更新sys1的导出行,如果column2也已更改,则还应更新sys2的导出行等。

到目前为止,这一切似乎都可行,虽然当你不是SQL天才时有点棘手。但是,我们希望能够定义一些更复杂的条件,至少像“column3 ='Apple'OR column3 ='Banana'”,这就是问题的核心...... < / p>

所以,总结一下:

  • 允许以这种方式配置触发器的最佳方法是什么?
  • 我们疯了吗?触发器是正确的方式来到这里,还是我们应该坚持我们的服务,抨击一些索引并吸收它?或者还有第三种选择吗?
  • 我们期望看到多少性能提升? (这都值得吗?)

1 个答案:

答案 0 :(得分:0)

这实际上是不可能的,因为SQL不支持动态SQL。因此,我们想出了从PHP读取配置表并生成“静态”触发器。我们将尝试使用2个表,一个用于列,一个用于条件,如下所示:

Columns
+--------+--------+-----------+
| system |  table |  column   |
+--------+--------+-----------+
| 'sys1' | 'tbl1' | 'column1' |
+--------+--------+-----------+
| 'sys2' | 'tbl1' | 'column2' |
+--------+--------+-----------+

Conditions
+--------+--------+-------------------------------------------+
| system |  table |                  condition                |
+--------+--------+-------------------------------------------+
| 'sys1' | 'tbl1' | 'column3 = "Apple" OR column3 = "Banana"' |
+--------+--------+-------------------------------------------+

然后在PHP(伪代码)中构建一个这样的语句:

DROP TRIGGER IF EXISTS `tbl1_AUPD`;

CREATE TRIGGER `tbl1_AUPD` AFTER UPDATE ON tbl1 FOR EACH ROW
    BEGIN
    IF (*sys1 columns changed*) AND (*sys1 condition1*) THEN
        updateExportTable('sys1', 'tbl1', NEW.primary_key, NEW.timestamp);
    END IF;
    IF (*sys2 columns changed*) THEN
        updateExportTable('sys2', 'tbl1', NEW.primary_key, NEW.timestamp);
    END IF;
END;

这对我们来说似乎是最好的解决方案,甚至可能比我要求的更好,但如果有人有更好的建议,我会全力以赴!