【问题标题】:Polling a database versus triggering program from database?轮询数据库与从数据库触发程序?
【发布时间】:2012-08-17 02:35:20
【问题描述】:

我有一个过程,其中在应用程序服务器中运行的程序必须访问 Oracle 数据库服务器中的表,只要该表中至少存在一行。每行数据都与请求程序执行的一些数字运算的客户端相关。该程序只能以串行方式执行此数字运算(即一次针对一个客户端,而不是并行处理多个客户端)。

因此,需要通知程序何时数据库中有数据可供其处理。我也可以

  1. 让程序轮询数据库,或者
  2. 让数据库触发程序。

问题 1:是否有任何传统观点认为一种方法可能比另一种更好?

问题 2:我想知道程序是否有任何问题一次“运行”几个月(服务器中的任何进程是否会停止或中断程序运行?- 如果是这样,我不知道我会如何学习除非来自愤怒的客户,否则会有问题)。任何人都有在服务器上运行程序很长时间没有问题的经验?或者,如果服务器确实崩溃了,有没有办法在服务器重新启动后在其上自动启动一个(即 C 语言可执行文件)程序,从而不需要人专门启动它?

任何建议表示赞赏。

更新 1:客户端正在等待结果,但几秒钟的额外延迟(来自轮询)不会破坏交易。

【问题讨论】:

  • 就我而言,“取决于程序的编写情况”应该是“程序是否正确编写”。内存泄漏是一个错误。您不应该根据潜在的错误做出设计决定。
  • 2) 没有意义。没有“C 程序”之类的东西。只有程序。 C 是一种可以编写程序的语言,但是一旦编译,程序就是程序。如果您的操作系统可以运行程序,那么它也可以运行“C 程序”,如果它告诉您它将在 30 分钟后杀死它们,那么无论它们是否用 C 编写,它都会杀死它们。也就是说,如果你编写了糟糕的代码,你可以通过消耗太多资源使程序在运行一段时间后死掉。
  • @Kerrek 刚刚编辑以删除对 C 的引用,因为问题并不是特定于语言的
  • 好吧,也许我过于关注我使用 C 编码这一事实。感谢 Code Bling 的编辑。问题归结为,“是运行一个不断轮询数据库的程序,还是让数据库触发程序的执行更好?”
  • ggkmath,我想这取决于数据库更新的频率,但你不一定要连续运行。您必须权衡轮询与事件驱动的优势。通常事件驱动的响应速度更快,更轻量级(内存和 CPU),但也有其他成本。一方面,维护两个相互依赖的不同语言的链接代码库(一个是您的主程序,另一个通常在数据库上运行)可能是一场噩梦。说了这么多,我相信你会在下面得到一些很棒的实际答案! :)

标签: database oracle


【解决方案1】:

我想给出一个更笼统的答案...

没有每次都适用的正确答案。有时您需要一个触发器,有时最好轮询。

但是……10 次中的 9 次,轮询比触发更有效、安全和快速

这真的很简单。触发器需要为每个镜头实例化一个程序,无论其性质如何。在大多数情况下,这只是效率不高。有些人会争辩说,当响应时间是一个因素时,这是必需的,但即便如此,有一半的时间轮询更好,因为:

1) 资源:使用触发器,比如 100 条消息,您将需要 100 个线程的资源,1 个线程处理一个包含 100 条消息的数据包,您需要 1 个程序的资源。

2) 监控:处理数据包的线程可以在定义的数据包大小上不断报告所消耗的时间,清楚地表明它是如何执行的,以及何时以及如何影响性能。尝试使用十亿个触发器来跳跃……

3) 速度:实例化线程并分配它们的资源非常昂贵。如果您为每个触发器打开事务,请不要让我开始。处理 100 个消息包的简单程序总是比启动 100 个触发器快得多……

3) 反应时间:通过轮询,您无法对在线事物做出反应。因此,允许使用轮询的唯一例外是当用户等待消息被处理时。但是你需要非常小心,因为如果你有很多客户端同时做同样的事情,那么触发可能会比你在哪里进行快速轮询时响应更晚。

我的 2cts。这是很难学到的..

【讨论】:

    【解决方案2】:

    1) 让程序轮询数据库,因为您不希望您的数据库能够启动宿主程序(因为您必须确保只有“您的”程序可以以这种方式开始)。

    在 Oracle 中执行此操作的经典(也是最方便的 IMO)方法是通过 DBMS_ALERT package

    第一个程序会发出一个带有特定名称的警报,并传递一条可选消息。注册警报的第二个程序将等待并在第一个程序提交后立即接收它。回滚第一个程序会取消警报。

    当然,您可以有许多会话发出信号并等待警报。但是,警报是一种序列化设备,因此如果一个程序发出警报信号,则发出相同警报名称的其他程序将被阻止,直到第一个程序提交或回滚。

    Table DBMS_ALERT_INFO 包含所有已注册警报的会话。您可以使用它来检查警报处理是否有效。

    2) 自动启动或后台执行取决于您的主机平台和操作系统。在 Windows 中,您可以使用 SRVANY.EXE 将任何可执行文件作为服务运行。

    【讨论】:

      【解决方案3】:

      我建议使用 C 程序来轮询数据库,并在出现任何问题时使用 monit 等实用程序重新启动 C 程序。您的 C 程序可以偶尔触摸一个文件以表明它仍在正常运行,并且 monit 可以监视该文件。 Monit 还可以直接检查进程并确保它没有使用太多内存。

      有关更多信息,您可以查看我对其他问题的回答:

      When a new row in database is added, an external command line program must be invoked

      或者,如果人们没有坐等计算完成,您可以使用 cron 作业 定期(例如每分钟)运行 C 程序。这样就不需要 monit 了,因为你的 C 程序会一直启动和停止。

      【讨论】:

      • 谢谢大卫,就我而言,客户正在等待结果。您的链接基本上说明了我正在尝试做的事情。 C 程序将处理第一行,然后在完成后删除该行,使之前的第二行成为第一行,然后 C 程序将处理,等等。我打算让程序定期更新数据库中的某些字段(例如心跳字段)只是为了表明它运行良好,但使用外部文件也应该可以。
      • 是的,文件很好,因为您不必更改数据库架构,并且可以通过monit轻松监控。
      【解决方案4】:

      您可能想查看 Oracle 的“更改通知”:

      http://docs.oracle.com/cd/E11882_01/appdev.112/e25518/adfns_cqn.htm

      不过,我不知道它与“常规”C 程序的集成情况如何。

      它也可以通过 .Net 和 Java/JDBC 获得

      http://docs.oracle.com/cd/E11882_01/win.112/e23174/featChange.htm
      http://docs.oracle.com/cd/E11882_01/java.112/e16548/dbchgnf.htm

      【讨论】:

        【解决方案5】:

        有一些简单的作业管理器,例如 gearman,您可以使用它们将作业消息从数据库发送到工作人员。 Gearman 有一个 MySQL 用户定义的函数接口,所以也很容易为 oracle 构建一个。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-22
          • 2011-01-16
          • 1970-01-01
          • 1970-01-01
          • 2012-11-18
          • 2018-10-01
          相关资源
          最近更新 更多