【问题标题】:Getting events from a database从数据库中获取事件
【发布时间】:2009-05-01 16:58:05
【问题描述】:

我不太熟悉数据库以及它们在 CRUD 操作之外提供的功能。

我的研究使我找到了触发因素。基本上看起来触发器提供了这种类型的功能:

(来自Wikipedia

通常有三个触发事件会导致触发器“触发”:

  • INSERT 事件(新记录被插入到数据库中)。
  • UPDATE 事件(因为正在更改记录)。
  • DELETE 事件(因为正在删除记录)。

我的问题是:当使用某种触发器语义更新/删除/插入记录时,数据库是否可以通过某种方式在 Java 中通知我(最好包括更改的数据)?

对于这个问题有什么替代解决方案?如何监听数据库事件?

我想这样做的主要原因是这样的场景

我有 5 个客户端应用程序,它们都在不同的进程中/存在于不同的 PC 上。它们都共享一个公共数据库(在本例中为 Postgres)。

假设一个客户更改了所有 5 个客户都“感兴趣”的数据库中的一条记录。我正在尝试想办法让客户“通知”更改(最好附上受影响的数据) 而不是他们每隔一段时间查询数据。

【问题讨论】:

  • 我很想知道您为什么要这样做;你确定要这样做吗?
  • 为什么要删除之前的问题? (stackoverflow.com/questions/809793 10 人)
  • 因为它是 postgres 特定的并且没有得到响应。

标签: java database database-design events triggers


【解决方案1】:

使用 Oracle,您可以在表上设置触发器,然后让触发器发送 JMS 消息。 Oracle 有两种不同的 JMS 实现。然后,您可以拥有一个使用 JDBC 驱动程序“侦听”消息的进程。我已经使用这种方法将更改推送到我的应用程序与轮询。 如果您使用的是 Java 数据库 (H2),您还有其他选择。在我当前的应用程序 (SIEM) 中,我在 H2 中有使用 JMX 发布更改事件的触发器。

【讨论】:

  • 请问H2怎么样?我真的不明白
  • H2 允许您用 Java 编写触发器并将其附加到表中。文档中有几个示例。
【解决方案2】:

不要混淆数据库(包含数据)和该数据上的事件。

触发器是一种方式,但通常您的应用程序中会有一个持久层。该层可以选择在某些事情发生时触发事件——比如 JMS 主题。

触发器是最后一道防线,因为那时您是在对关系项目进行操作,而不是对数据进行“事件”操作。 (例如,“更新”实际上可以映射到“公司更改法定名称”事件)如果您依赖数据库,则必须将插入和更新映射回现实生活中的事件......你已经知道了!

然后,您可以在这些通知之上添加其他内容(例如事件流处理)以查找其他人感兴趣的事件。

詹姆斯

【讨论】:

  • 注意:“5 个客户端应用程序 [...] 跨不同的 PC”不共享一个(实例)持久层。有时访问数据库的不仅仅是您的应用程序。
  • 你怎么知道的? - 在任何情况下,让多个不同的应用程序访问单个数据库都会大大增加您的复杂性 - 通常最好使用单一访问 api - 否则几乎不可能进行版本控制
【解决方案3】:

嗯。所以你正在使用 PostgreSQL 并且你想“监听”事件并在它们发生时得到“通知”?

http://www.postgresql.org/docs/8.3/static/sql-listen.html http://www.postgresql.org/docs/8.3/static/sql-notify.html

希望这会有所帮助!

【讨论】:

  • 这个功能是否存在于 mySQL 和 Oracle 中?
【解决方案4】:

从数据库调用外部进程是非常特定于供应商的。

就在我的脑海中:

  • SQLServer 可以从以下位置调用 CLR 程序 触发器,

  • postgresql 可以调用任意 C 动态加载的函数,

  • MySQL 可以调用任意 C 函数, 但它们必须编译进去,

  • 如果设置,Sybase 可以进行系统调用 这样做。

【讨论】:

  • Sybase SQL Anywhere 支持 Java、C/C++ 和我相信 .NET 中的存储过程和用户​​函数
【解决方案5】:

最简单的做法是让插入/更新/删除触发器在某个日志表中创建一个条目,并让您的 java 程序监视该表。日志表中的好列应该是 EVENT_CODE、LOG_DATETIME 和 LOG_MSG。

除非您需要非常高的性能或需要处理 100K 的记录,否则这可能就足够了。

【讨论】:

  • 这是一种简单的轮询机制,效率极低,通常应避免使用。我认为 dubdubdubdot 正在寻找其他可能性。
【解决方案6】:

我认为你混淆了两件事。它们都是高度特定于数据库供应商的。

第一个我称之为“触发器”。我确信至少有一个数据库供应商认为触发器与此不同,但请耐心等待。触发器是可以附加到表的服务器端代码。例如,您可以在表 X 中的每次更新时运行 PSQL 存储过程。有些数据库允许您用真正的编程语言编写这些,而其他数据库只允许使用它们的 SQL 变体。触发器通常相当快速且可扩展。

另一个我称之为“事件”。这些是在数据库中触发的触发器,允许您在客户端程序中定义事件处理程序。 IE,只要客户端数据库有更新,就会在程序中触发 updateClientsList。例如,使用 python 和 firebird 参见http://www.firebirdsql.org/devel/python/docs/3.3.0/beyond-python-db-api.html#database-event-notification

我相信之前使用监视器的建议是使用其他数据库实现此功能的等效方法。也许是甲骨文?另一个答案中提到的 MSSQL 通知服务也是另一个实现。

我什至要说你最好真正知道为什么你希望数据库通知你的客户端程序,否则你应该坚持使用服务器端触发器。

【讨论】:

    【解决方案7】:

    您要问什么完全取决于您使用的数据库以及您用于与数据库通信的框架。

    如果您使用 Hibernate 之类的东西作为持久层,它有一组侦听器和拦截器,您可以使用它们来监控进出数据库的记录。

    【讨论】:

    • Hibernate 案例需要注意的是,它只会在同一进程中通知您进行数据库调用。
    【解决方案8】:

    根据您使用的数据库,这里有几种不同的技术。一种想法是轮询数据库(我确定您正在尝试避免)。基本上你可以每隔一段时间检查一次更改。

    另一种解决方案(如果您使用的是 SQL Server 2005)是使用通知服务,尽管这种技术据说在 SQL 2008 中被替换(我们还没有看到纯粹的替换,但微软已经公开谈论过) .

    【讨论】:

      【解决方案9】:

      如果您使用的是 Oracle,请查看此previous post

      【讨论】:

        【解决方案10】:

        这通常是标准客户端/服务器应用程序的用途。如果所有的插入/更新/删除都通过服务器应用程序,然后服务器应用程序会修改数据库,那么客户端应用程序可以更容易地找出所做的更改。

        【讨论】:

        • 问题是在客户端/服务器应用程序之外修改数据库时。如果您使用的是 ORM (Hibernate),则必须有一种方法在从外部源修改数据库时使其缓存无效。
        • 客户端/服务器是指两层架构,当涉及到数据库时,数据库就是服务器层。您所指的架构将是三层架构。添加应用服务器只会将问题转移到这个新层。
        • 在这种情况下,我指的是客户端/服务器,就像在客户端应用程序和服务器应用程序中一样。我不在乎实际上有多少层。关键是服务器应用程序通知客户端应用程序更改比数据库通知客户端应用程序更改要容易得多。
        【解决方案11】:

        如果您使用的是 postgresql,它可以从 JDBC 客户端侦听 notifications

        【讨论】:

          【解决方案12】:

          我建议使用最后更新的时间戳列,以及可能更新记录的用户,然后让客户端检查他们的本地记录时间戳与持久记录的时间戳。

          在我看来,添加回调/触发功能所增加的复杂性是不值得的,除非得到数据库后端和使用的客户端库的支持,例如为 SQL Server 2005 提供的通知服务与 ADO 一起使用。网。

          【讨论】:

          • 这是值得的,因为您建议的是一种简单的轮询机制,效率极低,通常应避免使用。我认为 dubdubdubdot 正在寻找其他可能性。
          猜你喜欢
          • 1970-01-01
          • 2017-10-14
          • 2010-10-09
          • 2016-03-13
          • 2013-06-23
          • 1970-01-01
          • 1970-01-01
          • 2016-03-06
          • 1970-01-01
          相关资源
          最近更新 更多