我计划使用postgres LISTEN / NOTIFY aproach来获取表中记录的插入时间(实际事务提交时间)。为实现这一目标,我计划做以下事情。我在插入时间内发出通知,如下所示。
BEGIN;
INSERT INTO table_name(id, ...) values (id,....);
select pg_notify('test_channel', 'id - ' || id || ' trans start time - ' || now() || ' notify start time - ' || clock_timestamp());
END;
然后我计划使用https://pythonhosted.org/psycopg2/advanced.html#asynchronous-notifications来接收这些通知。
我想知道的是事务提交发生的确切时间(记录可以读取)到微秒级
我知道NOTIFY(pg_notify)实际上在提交事务后立即发送通知,但我无法弄清楚如何找出它发生的确切时间。我在NOTIFY中的时钟时间戳值不是实际的事务提交时间。
我想我收听通知的时间将接近事务提交时间,但我不确定它的接近程度。首先,在我的代码中进行民意调查时会有一段时间(但是很小),其次,我不确定NOTIFY / LISTEN通信本身之间是否存在任何延迟。
有什么想法吗?
UPDATE(问题的完整描述):我们让读者使用“检查点”时间批量选择行,其中每个批次获取上一批次中最后一个时间戳之后的行,我们缺少行。 (原因:时间戳值基于INSERT发生的时间(00.00.00)。在重负载时,如果事务需要更长的时间,它会被插入,比如10秒后(00.00.10),读者将错过这一行(row1)如果它在那10秒内读取并找到一个行,其行的INSERT时间晚于(00.00.05)而不是row1。问题的完整描述类似于本博客中写的那个。{{3 }})
答案 0 :(得分:2)
我想知道的是事务提交发生的确切时间(记录可以读取)到微秒级
当然,PostgreSQL 9.5只是以支持提交时间戳的形式添加了它。见commit timestamps。请注意,您必须启用track_commit_timestamp
才能使用此功能,并且有关提交时间戳的信息不会永久保留,因此相当旧的行只会获得null结果。
您可以在交易期间的任何时候获取带有txid_current()
的交易ID。也许以insert ... returning ...
为例。然后,您可以在提交后在后续查询中查找提交时间戳。
对于旧版本,您应该在clock_timestamp
子句中包含insert ... returning ...
。它将是插入记录的时间,而不是提交时间,但它确实是最接近的记录。
我想我收听通知的时间将接近事务提交时间,但我不确定它的接近程度。
"相当&#34 ;.它将取决于网络延迟,CPU调度滞后等。它肯定不会是微秒准确的。
例如,在Windows上,它最好精确到毫秒,但默认情况下它会精确到最接近的15毫秒计时器滴答。
不要投票。首先,在我的代码中进行民意调查时会有一段时间(无论多么小)
select()
套接字,这样您就可以立即唤醒那里的数据。在Linux上,您最好使用epoll()
系统调用。
第二,我不确定NOTIFY / LISTEN通讯本身之间是否存在任何延迟。
有些,是的,因为事务提交需要时间。因此,在您发出NOTIFY
和将事件发送给听众之间会有一些非零时间。
答案 1 :(得分:1)
now()将始终小于提交事务并且对读者可见的实际时间(除非您将脏读作为隔离级别)。
更好的方法(没有竞争条件的方法)是调用pg_notify()并在事务结束后立即使用clock_timestamp()(仅当事务提交时)。