2015-10-08 36 views
5

大多數RDBMS允許獲取所選行上的共享排他鎖。例如,PostgreSQL有這樣的語法:爲什麼無法通過顯式鎖定查詢語法獲取謂詞鎖

SELECT * 
FROM post 
WHERE id=10 
FOR SHARE; 

使用FOR SHARE,我們甚至可以在READ_COMMITTED隔離級別獲取共享鎖,並且可以在不實際使用REPEATABLE_READ事務隔離來防止非重複讀現象。

但是爲了防止幻像讀取,SERIALIZABLE是唯一的方法。爲什麼沒有明確的鎖定語法來獲取謂詞鎖定呢?

據我所知,我不記得在Oracle,SQL Server,MySQL或PostgreSQL中看到任何這樣的構造。

+0

因爲我記得FOR SHARE與SELECT FOR UPDATE具有相同的語義。您將收到READ LOCK以讀取涉及選擇的所有表格。 另一方面,SERIALIZABLE lvl也爲您提供了WRITE LOCK。另外,SELECT FOR UPDATE在Oracle中具有相同的語義,例如 – ivanenok

+1

FOR SHARE獲取讀鎖,而FOR UPDATE則爲您提供寫鎖。當使用SERIALIZABLE時,數據庫同時獲取所有檢索到的行上的共享鎖(以防止模糊讀取)以及範圍/謂詞鎖(以防止幻像讀取)。 –

+1

爲什麼要在每個查詢中強制執行事務隔離級別,而不僅僅是使用事務隔離級別?在Oracle中,您總是可以對SCN使用閃回查詢以避免幻讀(如果將事務隔離級別設置爲可串行化,這就是Oracle正在做的事情)。這不需要任何形式的鎖定或任何其他會話阻塞。但它不會具有拋出ORA-08177的相同行爲:無法對不可序列化的修改序列化針對此事務錯誤的訪問。 –

回答

2

在PostreSQL中,可序列化隔離級別基於所謂的Serializable Snapshot Isolation,它使用謂詞鎖定而不是實際的鎖定,但是用於監視可能產生序列化異常的條件。該機制僅在可序列化級別上工作;沒有辦法在較低級別使用謂詞鎖。

但是爲了防止幻像讀取,實際上PostgreSQL中實際上只需要可重複讀取隔離級別(儘管SQL標準提到隔離級別)。詳情請參閱the documentation

至於Oracle,它根本沒有謂詞鎖。其Serializable隔離級別使用快照隔離(與PostgreSQL中的可重複讀取相同),它可以防止幻像讀取,但允許other serialization anomalies

我沒有關於SQL Server和MySQL的信息。

1

標準沒有指定謂詞鎖定,或者必須使用謂詞鎖定來實現SERIALIZABLE。它只規定了異常SERIALIZABLE必須阻止...並且大多數DBMS實際上並沒有完全遵守。

在PostgreSQL的情況下,沒有明確的謂詞鎖定語法,因爲沒有謂詞鎖定。 PostgreSQL對SERIALIZABLE使用更樂觀的鎖定方式,它跟蹤事務之間的依賴關係,並在檢測到循環依賴時中止。這並不遵循鎖的語義,並且明確地做不太有用。