跨rou的cx_Oracle CQN回调用法

2024-10-02 20:40:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用python编写一个flask网页,它维护来自oracledb(v11.2)的缓存查询结果。我想使用连续查询通知(CQN)在缓存失效时获取通知。我可以注册CQN通知侦听器,但是当表更改时,不会调用我的回调。请注意,数据库外部托管在AWS上,我的dev(以及最终的prod)计算机位于公司路由器后面的局域网上。在

我使用以下代码注册CQN回调:

import cx_Oracle
def CQNCallback(message):
    print("Callback triggered.")

ops = cx_Oracle.OPCODE_INSERT | cx_Oracle.OPCODE_DELETE | cx_Oracle.OPCODE_UPDATE
conn = cx_Oracle.connect('userID','passwd','IP:port/ID',events=True)
subs = conn.subscribe(callback = CQNCallback, operations=ops, rowids = False, timeout=3000)
subs.registerquery('select * from MYTABLE')

此代码成功执行,我在DB USER_CHANGE_NOTIFICATION_REGS表中看到一个新条目:

^{pr2}$

“网关”是我公司网关/路由器的公共IP地址,端口56824似乎是由cx Oracle分配的。 为了验证我的dev机器是否在监听这些通知,我运行netstat并查看计算机是否正在侦听IPv4和6上的56824端口

Proto  Local Address     Foreign Address    State
TCP    0.0.0.0:56824     <devComputer>:0    LISTENING
TCP    [::]:56824        <devComputer>:0    LISTENING

但是,当我手动更新或插入(并提交!)使用SQLDeveloper更改MYTABLE时,我的回调从未被调用,我不知道为什么(我确保在进行更改时注册没有超时)。在

我的猜测是:我怀疑DB似乎使用了与本地进程相同的端口号——这表明存在NAT问题。可能通知的tcp连接是由数据库发起的,它正在向发送通知消息网关:56824。如果是这样,路由器可能不知道该如何处理消息,因此会丢弃它。如果是这种情况,我如何配置cx®Oracle以正确处理中间路由器?在

我发现一个OTN线程表明这是oracle11.2.0.1(https://community.oracle.com/thread/2292328?tstart=0)中的已知错误。我想我的新任务是说服数据库管理员升级数据库,然后再试一次。我现在的问题是,“贿赂/说服数据库管理员升级甲骨文系统的最佳方式是什么,而他从2009年起就不必考虑在这个系统上进行升级,而不需要被告知‘去捣碎沙子’?”在


Tags: 代码dev数据库网关计算机公司路由器conn
1条回答
网友
1楼 · 发布于 2024-10-02 20:40:34

通过执行两个任务,我能够使用上述代码的测试版本接收更改通知:

  1. 调用上面链接中提供的“设置事件”黑客。这很好,因为即使我不能说服DBA将服务器软件更新到11.2.0.4,我仍然可以继续前进。在
  2. 在路由器上设置端口转发,将指定端口上的传入连接转发到我的内部IP。我可以在家里的笔记本电脑上控制这一点,但我需要说服公司的IT支持人员在工作时为我的生产服务器实现端口转发。在

如果没有你原来的网络入侵通知(2)你就不能用你原来的网络入侵通知。原因是本地客户机没有打开一个用于传递更改的长期连接,而是从数据库端启动更改通知连接,并为每个更改通知创建一个新连接

然后我能够在工作局域网上实现上面的2个步骤,并成功地触发了我的回调代码。我需要通过修改订阅创建为订阅指定一个固定端口,以便在公司防火墙上正确实现端口转发:

subs = conn.subscribe(callback = CQNCallback, operations=ops, rowids = False, timeout=3000, port=50000)

我学到的另一件事可以帮助其他人,那就是你不能仅仅关闭pythonshell或ctrl-c代码,这些代码使用cxu-Oracle注册更改通知。您需要显式地调用“delsubs”,否则订阅将保持在数据库中永久注册(永远?)没有机制来移除它。要在开发期间绕过此限制,请确保显式指定订阅的短超时。这样,如果您错误地按下ctrl-c,您只需等待订阅超时一小段时间,就可以继续工作了。我不打算对生产代码使用超时,但我还不确定如何能够清理崩溃时产生的孤立订阅。在

这有效地解决了这个问题。要实现这一点仍然存在一些问题,比如Oracle拒绝处理通知端口上的FIN和RST,但这将是另一个问题的主题。在

相关问题 更多 >