2016-01-20 34 views
7

上的可序列化的隔離違規我有一個非常大的Redshift數據庫,其中包含數十億行HTTP請求數據。Redshift:表

我有一個表稱爲requests其中有幾個重要的領域:

  • ip_address
  • city
  • state
  • country

我每運行一次Python進程這一天抓住了所有的d仍然沒有進行地理編碼的行(還沒有任何城市/州/國家信息),然後嘗試通過Google的Geocoding API對每個IP地址進行地理編碼。

這個過程(僞)看起來是這樣的:

for ip_address in ips_to_geocode: 
    country, state, city = geocode_ip_address(ip_address) 
    execute_transaction(''' 
     UPDATE requests 
     SET ip_country = %s, ip_state = %s, ip_city = %s 
     WHERE ip_address = %s 
    ''') 

運行此代碼,我經常會收到這樣的錯誤如下:

psycopg2.InternalError: 1023 
DETAIL: Serializable isolation violation on table - 108263, transactions forming the cycle are: 647671, 647682 (pid:23880) 

我假設這是因爲我有其他進程不斷記錄HTTP請求到我的表中,所以當我嘗試執行我的UPDATE語句時,它無法選擇所有行與我想要更新的IP地址。

我的問題是:我能做些什麼來以一種理智的方式更新這些記錄,以便定期停止失敗?

回答

3

您的代碼違反了Redshift的可序列化隔離級別。在關閉所有打開的事務之前,您需要確保您的代碼不試圖在同一個表上打開多個事務。

您可以通過鎖定每個事務中的表來實現此目的,以便在打開的事務處理關閉之前,其他任何事務都不能訪問該表進行更新。不知道你的代碼是如何架構的(同步或異步),但這會增加運行時間,因爲每個鎖都會強制其他人等待事務結束。

參見:http://docs.aws.amazon.com/redshift/latest/dg/r_LOCK.html

0

要麼當你在同一個表第二更新你開始一個新的會話,或者你必須「提交」一旦交易完成。

您可以在開始更新之前編寫set autocommit = on。

0

剛剛得到了我的代碼相同的問題,這就是我如何固定它:第一

第一件事,這是好事,知道這個錯誤代碼意味着您正試圖在紅移做的併發操作。例如,當你在第一次查詢之前對錶執行第二次查詢時,就會出現這種錯誤(這是我的情況)。

好消息是:有一個簡單的方法來序列化紅移操作!你只需要使用LOCK命令。以下是redshift LOCK command的亞馬遜文檔。它的工作原理基本上是讓下一個操作等到​​上一個操作關閉。請注意,使用這個命令你的腳本自然會變慢一點。最後,我的實際解決方案是:我在查詢消息之前插入了LOCK命令(在同一個字符串中,用';'分隔)。事情是這樣的:

LOCK table_name; SELECT * from ...

,你應該是好去!我希望它能幫助你。