2015-10-02 8 views
1

我打算使用postgres LISTEN/NOTIFY aproach獲取表中記錄的插入時間(實際的事務提交時間)。爲了達到這個目的,我打算做以下事情。我在插入時發出通知,如下所示。Postgres LISTEN/NOTIFY - 低延遲,實時?

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來接收這些通知。

我想找出是確切的時間事務提交發生(該記錄可讀取)下降到微secods

據我所知,NOTIFY(pg_notify)實際上之後提交的發送通知該交易,但我無法弄清楚如何找出發生的確切時間。我在NOTIFY中使用的時鐘時間戳值不是實際的事務提交時間。

我猜我聽通知的時間將接近事務提交時間,但我不確定它有多接近。首先,在我的代碼中進行民意調查的時候,有一段時間是在聽(其實它很小),其次,我不確定NOTIFY/LISTEN通信本身之間是否存在任何延遲。

任何想法?

UPDATE(問題完整說明):我們有一個讀者在使用「檢查點」時,每個批次一個批次最後的時間戳之後獲得的行批次選擇行,而我們缺少的行。 (原因:時間戳值基於INSERT發生的時間(00.00.00)。在重負載下,如果事務需要更長的時間,比如插入10秒(00.00.10),讀者將錯過這一行(row1),如果它在10秒鐘內讀取並發現一個行的INSERT時間晚於(row。1)的時間(00.00.05),則該問題的完整描述與此博客中寫入的行爲類似。http://blog.thefourthparty.com/stopping-time-in-postgresql/

+0

呃...爲什麼?你想用這個做什麼?你試圖解決這個問題的根本問題是什麼,你需要它的原因是什麼? –

+0

我更新了我們試圖在說明中解決的問題。 – Chandra

+1

所以你只是試圖實現一個可靠的隊列與多個作家和一個閱讀器?試圖用這種方法修復亂序提交和可見性問題是行不通的。考慮在實際的底層主題上發佈一個新的單獨問題,即當隊列讀取器掃描表時,如何避免丟失行,然後在讀取後正在進行的事務提交。你很早就忽略了我的問題令人沮喪。 –

回答

1

now()將始終小於事務提交併且讀者可見的實際時間(除非您有髒讀作爲隔離級別)。

更好的方法(沒有競爭條件的方法)是在事務結束後立即調用pg_notify()並使用clock_timestamp()(並且只在事務提交時)。

+0

使用'NOTIFY'和'pg_notify()'完全沒有區別。使用'clock_timestamp'而不是'now()'(這是交易的'current_timestamp')是一個很好的建議。我不明白「在交易結束後」的意思。在tx結束後你不能做任何事情,除非你做了另一次交易。 –

+0

你的意思是在插入後設置一個觸發器,它會有NOTIFY語句嗎?根據我的理解,觸發是當前交易的一部分,並會增加整個交易時間的時間?在提交之後我還會如何添加NOTIFY? – Chandra

+0

在交易過程中以及作爲交易的一部分,「插入後」觸發器觸發是正確的。通知被觸發器排隊,然後在提交後交付。 –

2

我想找出是確切的時間事務提交發生(該記錄可讀取)下降到微secods

相當方便,和PostgreSQL 9.5剛剛添加的是,在形式支持提交時間戳。見commit timestamps。請注意,您必須啓用track_commit_timestamp才能使用此功能,並且有關提交時間戳的信息不會永久保存,因此相當舊的行只會得到空結果。

您可以在交易過程中的任何時間獲取交易編號txid_current()。例如,可能使用insert ... returning ...。然後你可以在提交後在後續查詢中查找提交時間戳。

對於舊版本,您應該在insert ... returning ...條款中包含clock_timestamp。這將是插入記錄的時間,而不是提交時間,但這確實是最接近可能的時間。

我猜我聽通知的時間將接近事務提交時間,但我不知道它有多接近。

「相當」。這將取決於網絡延遲,CPU調度滯後等。它肯定不會是微秒準確的。

例如,在Windows上,它最好精確到毫秒,但默認情況下它會精確到最接近的15毫秒計時器滴答。

首先,是在我的代碼民調之間的某個時間,一邊聽(無論多小的)

不要輪詢。 select()套接字讓你在有數據讀取的瞬間醒來。在Linux上,你最好使用系統調用epoll()

第二,我不確定NOTIFY/LISTEN通信本身之間是否有任何滯後。

有些,是的,因爲事務提交需要時間。因此,在您發出NOTIFY和事件發送給聽衆之間有一段非零時間。

+0

總結最後三個答案在你的答案.....因此,如果我們排除事務提交的時間,因爲通知在事務提交後立即發送,如果我使用select()而不是輪詢,唯一的時間在NOTIFY和LISTEN之間產生的延遲是由於網絡延遲,CPU調度等原因造成的。我的理解是否正確?我知道NOTIFY有效負載中的clock_timestamp值沒有事務結束時間。 – Chandra

+0

好吧,提交不是即時的,就可視性而言,它只是原子。如果你正在談論的微秒開始有意義。在commit提交後,在clog中設置提交後發送通知。有關詳細信息,請參閱源代碼。另外,'select()'和'epoll()'不一定是零延遲。事實上,由於內核中的延遲,系統管理中斷等原因,他們可以輕鬆地在數據變得可讀和應用程序被通知之間產生毫秒的延遲。你需要一個實時進程和低延遲的內核纔能有明智的選擇。 –

+0

這聽起來像你試圖使用PostgreSQL作爲實時系統,但事實並非如此。它的設計並非如此。它可能在LWLocks中存在很長的鎖定延遲。它可以在文件系統操作期間阻塞關係擴展鎖。在檢查點期間,它可以被緩衝器引腳延遲。各種各樣的事情意味着,即使延遲時間通常很低,它們也不是*有界的,而且總是不是很低。如果你有很多負載和運氣不好,你可能會在提交和處理通知之間出現很大的延遲。你永遠不會知道你的方法。這不可靠。 –