10

我有一个 C# 客户端应用程序,它使用 Npgsql 在 PostgreSQL 9.1.4 中调用 plpgsql 函数。该功能需要很长时间,我想以某种方式向客户报告进度。我该怎么做?

LISTEN/NOTIFY 机制听起来很适合这个,除了整个事情在事务中运行并且 NOTIFY 事件直到事务结束才发送,这对我来说没用。

我尝试过的另一件事是 RAISE NOTICE,我可以在客户端上处理它,但即使是那些通知似乎也被缓冲了一段时间并分批发送。有总比没有好,但并不理想。有什么办法可以“刷新”它们,以便立即将它们发送给客户?

4

4 回答 4

8

没有什么比发出通知更好的了。

这些信号没有被缓冲——它们是异步的——你的应用程序中的通知处理可能有问题。

于 2012-08-15T13:09:44.670 回答
8

除了@Pavel 关于 的优秀观点之外RAISE NOTICE,还有另一种用于监控 Pg 中的查询进度的经典技术。这有点像黑客,但它非常有效。

您可以利用对序列的更改随处可见的事实,将函数的进度暴露给外部。要么使用硬编码序列并确保函数不会被并发调用,要么将进度监控序列名称传递给函数。

您的函数可以nextval(seqname)在每次迭代时调用,感兴趣的各方可以SELECT last_value FROM seqname从另一个会话中检查序列的状态。

您可以通过设置来使序列成为完成的倒计时

create sequence test maxvalue 2147483647 increment by -1;

setval('seqname', num_items)在函数开始时调用。nextval然后,每次通话都会倒计时至零。顺便说一句, 2147483647 是maxint

不用说这不是可移植的,并且不能保证SELECT序列中的 ing 将始终以这种方式工作。不过,这很方便。

于 2012-08-15T23:40:23.710 回答
1

最简单的方法是将您的 pgsql 函数拆分为多个子函数,而不是按顺序调用它们,应用程序端,管理应用程序中的事务范围。

于 2012-08-15T11:36:00.457 回答
0

您还可以使用:

EXECUTE 'COPY (SELECT ''progress: ' || progress_variable || ''') TO ''d:\progress.txt''';

在您的函数内部将当前进度写入文本文件。

于 2014-08-22T10:08:48.147 回答