2016-06-09 95 views
0

下面是Postgres的日誌PostgreSQL的死鎖在插入和更新

Process 10396 waits for RowShareLock on relation 17204 of database 16384; blocked by process 10377. 
Process 10377 waits for ShareLock on transaction 149848948; blocked by process 10396. 
Process 10396: insert into "completed_jobs" ("id", ....... "limitation_code") values ($1, ...... $22) returning "id" 
Process 10377: UPDATE jobs SET status='pending', updated_at=$1 WHERE id=$2 

我從郎去執行這個。所以這是在分佈式環境中。

更新是正常執行,

_, err = tx.Exec("UPDATE jobs SET status='pending', updated_at=$1 WHERE id=$2", time.Now().UTC(), job.Id) 
    if err != nil { 
     log.Println(getMessagePrefix(job, nil), "Error updating job status to pending", err) 
    } 
    err = tx.Commit() 

插入是一個事務中,

tx, _ := db.Begin() 
tx.Exec("UPDATE jobs SET status=$1 WHERE id=$6", status) 
tx.Exec("INSERT INTO completed_jobs SELECT * FROM jobs WHERE id=$1", job.Id) 
tx.Exec("DELETE FROM jobs WHERE id=$1", job.Id) 
err := tx.Commit() 

回答

0

在工作排隊我一般都用下面的戰略,以防止多個進程試圖訪問同一職位。一般來說,你需要交叉事務控制來處理這個問題。

  • 諮詢鎖,它是交叉鎖定自由鎖。這意味着您可以在將它們返回給客戶端之前排除進程內作業。這也避免了等待狀態要求。
  • 與隨機ID的短交易,以防止多個進程可能擊中相同的ID。如果使用索引,這一點也很重要,因爲如果最終得到長時間運行的事務,則可能會在索引的頭部收到大量死元組。

作業隊列系統中的併發提出了大量問題。但是這兩者解決了最糟糕的問題。