我有一个生成交易并执行它们的软件。我想根据执行的查询占查询总数的简单比例异步检查事务进度。我能够读取stdout
和stderr
生成的psql
,所以我想一个解决方案可以打印到stdout
一些自定义消息,如“进度:3/8”(或另一个自定义文本字符串)。
我曾考虑过执行“日志查询”,该查询将有关查询进度的信息存储在适当的表中,但该表在事务完成之前不可用,这使我无法检查事务进度。
目前我尝试了以下操作(假设在交易中有 3 个查询来做一些事情):
BEGIN;
CREATE OR REPLACE FUNCTION progress(curr int, total int) RETURNS float AS $$
BEGIN
RAISE NOTICE '___PROGRESS___%', curr/total::float;
RETURN curr/total::float;
END;
-- First query
SELECT ... FROM ...;
-- Log the progress
SELECT * FROM progress(1,3);
-- Second query
SELECT ... FROM ...;
-- Log progress
SELECT * FROM progress(2,3);
-- Third query
SELECT ... FROM ...;
-- Log progress
SELECT * FROM progress(3,3);
COMMIT;
Run Code Online (Sandbox Code Playgroud)
我使用以下语法从 bash 文件执行脚本:
res=$((psql -U username -d db -h localhost --log-file=plog.log -f "the transaction above") 2>&1>clog.log)
Run Code Online (Sandbox Code Playgroud)
我使用前面的 bash 命令从类似上述事务的事务中得到三个输出:plog.log
,clog.log
和$res
bash 变量。我将发布其中的一些摘录,以明确它们的内容。
....
********* QUERY **********
SELECT * from progress(1, 3);
**************************
progress
-------------------
0.333333333333333
(1 row)
...
********* QUERY **********
SELECT * from progress(2, 3);
**************************
progress
-------------------
0.6666666666666667
(1 row)
...
********* QUERY **********
SELECT * from progress(3, 3);
**************************
progress
-------------------
1
(1 row)
Run Code Online (Sandbox Code Playgroud)
...
progress
-------------------
0.333333333333333
(1 row)
...
progress
-------------------
0.6666666666666667
(1 row)
...
progress
-------------------
1
(1 row)
Run Code Online (Sandbox Code Playgroud)
$res
变量(psql
返回值)psql:/path/to/script.sql:11: NOTICE: ___PROGRESS___0.333333333333333
psql:/path/to/script.sql:16: NOTICE: ___PROGRESS___0.666666666666667
psql:/path/to/script.sql:21: NOTICE: ___PROGRESS___1
Run Code Online (Sandbox Code Playgroud)
问题是我无法实时访问$res
变量的内容。我可以改为访问clog.log
and的内容plog.log
,因此 的使用RAISE NOTICE
根本没有意义,因为它没有出现在clog.log
and 中,plog.log
而只出现在$res
.
我应该坚持解析clog.log
还是plog.log
为了SELECT
从progress()
函数中找到输出值(删除该函数中的RAISE NOTICE
语句,因为它无用)还是有替代方法?我错过了什么吗?
谢谢
RAISE NOTICE
是正确的方法。
RAISE NOTICE
输出未出现的原因clog.log
是您的标准错误重定向在 shell 级别是错误的。
你要:
psql --log-file=plog.log -f file.sql >clog.log 2>&1
Run Code Online (Sandbox Code Playgroud)
这样,它将标准输出重定向到标准输出clog.log
,然后将标准错误重定向到该标准输出。
问题中的完成方式:2>&1>clog.log
由于顺序错误而无法实现,如 bash 手册中所述:
请注意,重定向的顺序很重要。例如,命令
ls > 目录列表 2>&1
将标准输出(文件描述符 1)和标准错误(文件描述符 2)定向到文件目录列表,而命令
ls 2>&1 > 目录列表
仅将标准输出定向到文件 dirlist,因为在标准输出重定向到 dirlist 之前,标准错误已生成标准输出的副本。
在我们的系统中,我们使用 dblink 并写入同一个数据库。这是 Oracle 自治事务的另一种方法。
这里我使用DB链接的概念来实现日志记录的异步提交。这与Oracle中的自治事务的概念相同。在数据库链接内完成的提交不会导致主事务中的提交。
实际数据通过命令“PERFORM PUBLIC.dblink_exec”写入日志表并立即提交。
当主程序仍在执行时,您可以通过从不同会话查询日志表来跟踪主程序的进度,无论执行数小时后是否出错,日志数据仍保持提交状态。
#1: Confirm dblink extension
#2: Create DDLs
CREATE TABLE dblink_log (ID serial, message TEXT);--Table to store the logs
GRANT ALL ON TABLE core.dblink_log TO PUBLIC;--Permission to write as a dblink
GRANT ALL ON TABLE core.dblink_log_id_seq TO PUBLIC;
#3
/*Test block to write to a table and commit while
the main transaction is still in progress*/
DO$$
DECLARE
open_connections TEXT [] := PUBLIC .dblink_get_connections () ;
--Cannot connect more than once before closing
my_dblink_name TEXT := 'logging_dblink' ;
--Define a name for your db link connection
BEGIN
--If the connection doest not exists, create one
IF open_connections IS NULL
OR NOT open_connections @> ARRAY [ my_dblink_name ] THEN
PERFORM PUBLIC .dblink_connect (
my_dblink_name,
'host=127.0.0.1 port=5432 dbname=dbname user=user password=password'
) ;
raise notice 'New db link connection made' ;
ELSE
raise notice 'Db link connection exists, re-using' ;
END IF ;
FOR i IN 1..10 loop
PERFORM PUBLIC.dblink_exec (
my_dblink_name,
'BEGIN;
INSERT INTO core.dblink_log (message)
VALUES (''Executing loop #' || i || ''') ;
COMMIT;'
) ;
perform pg_sleep(10) ;-- Execute select * from core.dblink_log
-- in a different session
END loop ;
END $$;
#4: From a different session verify record core.dblink_log is populated with data
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
11522 次 |
最近记录: |