未处理来自 pyodbc 查询的最后一条记录(到使用 stomp 的消息传递系统)
Posted
技术标签:
【中文标题】未处理来自 pyodbc 查询的最后一条记录(到使用 stomp 的消息传递系统)【英文标题】:Last record from a pyodbc query doesn't process (to messaging system using stomp) 【发布时间】:2022-01-22 12:25:38 【问题描述】:我正在查询一个返回 38 条记录的数据库。在下面的示例中,所有 38 条都打印,但最后一条记录没有发送到消息系统,只有前 37 条。我在这里缺少什么???
cnxn = pyodbc.connect('DRIVER=ODBC Driver 17 for SQL Server;' + connectionString)
cnxn.autocommit = True
cursor = cnxn.cursor()
sql = (sql statement that returns 38 records)
cursor.execute(sql)
print("Connected")
row = cursor.fetchone()
while row:
conn = stomp.Connection([('this.that.sys', '61616')])
conn.connect('user', 'pass', wait=True)
print("Send " + row.id)
conn.send(destination='test1.topic::test1.test1.queue', body=row.payload)
row = cursor.fetchone()
conn.disconnect()
这会输出所有 38 个 ID 的列表,但最后一个 Payload 不会发布到队列中。
我做了更多的测试。这很奇怪。这似乎取决于记录。它们在 7KB 到 15KB 之间。如果我尝试某两个,只发布第一个。某某三,全部发表。再确定三个,最后一个又不发表了。
如何调试?
编辑:我做了更多的实验。 Stomp 不保证交货吗?我没有收到任何错误,但有时消息只是没有到达,尤其是最后一条。我稍微重构了我的代码,这似乎有点帮助。我不知道...
cursor.execute(sql)
print("Connected")
row = cursor.fetchone()
print("First " + row.id)
i = 1
try:
conn = stomp.Connection([('this.that.sys', '61616')])
conn.connect('user', 'pass', wait=True)
while row:
print(str(i))
print("Send " + row.id + " " + row.status)
conn.send('test1.topic::test1.test1.queue', row.payload)
row = cursor.fetchone()
i = i + 1
conn.disconnect()
except Exception as e:
print("Error: %s" % e)
【问题讨论】:
您使用什么库来发送 STOMP 消息? send 方法是否异步执行?如果是这样,那么disconnect
可能会在发送实际发生之前被调用。
嗨贾斯汀。谢谢。该库仅称为 stomp.py。好想法。我在 conn.disconnect() 之前添加了 time.sleep(1),并做了一些实验而没有丢失最后一条消息。棘手。
为什么是 fetchone 而不是 fetchall?
STOMP 协议支持receipt
header,您可以使用它从代理那里获得您的SEND
帧已成功处理的回复。我不是 100% 确定 stomp.py 支持这一点,但它应该支持,因为它是协议规范的一部分。
另外,它可能值得activating trace logging for STOMP on the broker。然后您可以准确地看到代理从客户端接收到的内容(例如,如果它过早地接收到 DISCONNECT
帧)。
【参考方案1】:
send
方法是否异步执行?如果是这样,那么disconnect
可能会在发送实际发生之前被调用。因此,您可以尝试延迟调用disconnect
方法。
还值得注意的是,STOMP 协议支持receipt
header,您可以使用它从代理处获得回复,以确保您的 SEND 帧已成功处理。我不能 100% 确定 stomp.py 支持这一点,但它应该支持,因为它是协议规范的一部分。
此外,在代理上可能值得activating trace logging for STOMP。然后您可以准确地看到代理从客户端接收到的内容(例如,如果它过早地接收到 DISCONNECT
帧)。
最后,您绝对不应该通过连接和断开连接来发送一条消息。这是一个众所周知的反模式,应该尽可能避免。您的第二个代码 sn-p 在这方面更好。
【讨论】:
【参考方案2】:我会改变它:
cnxn = pyodbc.connect('DRIVER=ODBC Driver 17 for SQL Server;' + connectionString)
cnxn.autocommit = True
cursor = cnxn.cursor()
sql = (sql statement that returns 38 records)
cursor.execute(sql)
print("Connected")
rows = cursor.fetchall()
for row in rows:
conn = stomp.Connection([('this.that.sys', '61616')])
conn.connect('user', 'pass', wait=True)
print("Send " + row.id)
conn.send(destination='test1.topic::test1.test1.queue', body=row.payload)
conn.disconnect()
【讨论】:
连接和断开以发送单个消息是众所周知的反模式,应尽可能避免。 我的回答与有关数据获取的问题有关,而您的评论与他的问题无关 据我所知,问题实际上与数据获取无关。他清楚地说他正在获取所有 38 条记录。问题是只有 37 个被发送到消息代理。因此,失败与通过 STOMP 客户端发送消息有关,这就是我的评论所要解决的问题。为什么您认为问题在于获取数据? 如果你已经阅读了整个问题,你会注意到他只尝试了一次连接和断开连接,问题仍然存在 我了解维护单个连接并不能解决问题。我从没想过会这样。然而,事实仍然是,连接和断开连接以发送单个消息是一种众所周知的反模式,应尽可能避免。以上是关于未处理来自 pyodbc 查询的最后一条记录(到使用 stomp 的消息传递系统)的主要内容,如果未能解决你的问题,请参考以下文章
在 pyodbc 中执行 SELECT 查询时,来自 ODBC MS Access 驱动程序的“系统资源超出”错误