我有一个C#客户端应用程序,它使用Npgsql在PostgreSQL 9.1.4中调用plpgsql函数。该功能需要很长时间,我想以某种方式向客户报告进度。我该怎么做?
LISTEN / NOTIFY机制听起来很完美,除了整个事情在一个事务中运行,NOTIFY事件直到事务结束才发送,这对我来说是没用的。
我尝试过的另一件事是RAISE NOTICE,我可以在客户端上处理,但即使是那些通知似乎也会缓冲一段时间并分批发送。它总比没有好,但不理想。有什么方法可以“冲洗”它们,所以它们会立即发送给客户吗?
答案 0 :(得分:7)
除了@ 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
始终以这种方式工作。但它很方便。
答案 1 :(得分:6)
没有比RAISE NOTICE更好的了。
这些信号没有被缓冲 - 它们是异步的 - 你的应用程序中的通知处理可能存在问题。
答案 2 :(得分:1)
最简单的方法是将pgsql函数拆分为多个子函数,而不是按顺序调用它们,应用程序端,管理应用程序中的事务范围。
答案 3 :(得分:0)
您也可以使用:
EXECUTE 'COPY (SELECT ''progress: ' || progress_variable || ''') TO ''d:\progress.txt''';
在函数内部,将当前进度写入文本文件。