2011-06-07 53 views
16

它是不是從MySQL documentation完全清楚InnoDB引擎是否實現真正的序列化隔離snapshot isolation,這往往容易混淆稱爲「序列化」了。哪一個?MySQL/InnoDB是否實現真正的可序列化隔離?

如果MySQL InnoDB沒有,是否有任何完全免費的,生產質量的RDBMS呢?

其中「真序列化隔離」是指不存在不只讀異常按照SQL標準,而且還寫入歪斜異常,進一步詳細here說明。

+2

我很喜歡這個。我們需要功能X,但絕對不想爲它付費。 – Kibbee 2011-06-07 17:53:06

+6

很高興我讓你快樂一點,@Kibbee。 – 2011-06-07 17:58:07

+0

如果你定義你的意思是「真正的可序列化的隔離」,也許人們可以稍微澄清一下。 – Kibbee 2011-06-07 18:22:35

回答

9

有沒有完全免費的,生產質量的RDBMS呢?

Postgres支持真正的序列化隔離starting with version 9.1。它當然符合「完全自由」和「生產質量」的要求。

+1

這不再是真的?看到註釋regileros上面的答案 - MySQL似乎已經解決了5.5中的問題。 – 2012-07-09 19:13:01

+0

@PiotrBlasiak它可能是具體的例子是固定的,但除非MySQL公佈真正的隔離,我期望它只實現較小的變體。但是,我將刪除我的關於MySQL的聲明,因爲它現在不支持。 – 2012-07-09 21:03:36

-5

我不相信MySQL實現了可序列化的隔離,據我所知,它將需要回滾的能力,而這絕對不支持。欲瞭解更多信息,請閱讀here

+0

就在那篇文章的頂部,它指出它已經過時,並且不代表關於MySQL的最新數據。儘管MyISAM表不支持回滾或交易,但InnoDB確實支持回滾事務。 – Kibbee 2011-06-07 19:27:49

+0

我知道MySQL + InnoDB支持事務;問題只在於它們的「可序列化」交易究竟意味着什麼。 – 2011-06-07 21:28:51

+0

MySQL確實支持事務。 MyISAM表處理程序不支持*行級別鎖定*,但InnoDB也修復了這一問題。 – Zds 2011-11-02 10:36:23

-2

閱讀鏈接you provided的更多信息,它表示使用「可重複讀取」模式(innodb的默認設置)可以消除讀取異常,正如您提到的您的一項要求。另外,閱讀你的第二個鏈接,似乎處理寫入異常將轉移到最終用戶。在文章中他們提到了Oracle的Select for Update,其中MySQL also supports。我不確定這是否符合您的要求,但它應該會對您有所幫助。

+0

是的......儘管第二個鏈接解釋了*快照隔離*所做的事情,而不是MySQL是否執行快照隔離或真正的可序列化隔離,所以我仍然不確定。 – 2011-06-08 10:27:32

10

UPDATE:

看評論,這似乎是固定在MySQL 5.5,這些例子中,我們仍然有一個表鎖和下一鍵鎖不能被愚弄的指數,據我所知。

原文:

找到你的問題昨天我想知道的InnoDB的MVCC seriability模型爲好。

所以我做了一些測試。 MySQL 5.1.37。對於可序列化問題的一個很好的測試是postgrESQL 9.0 MVCC documentation中提供的一章,在本章中可串行化隔離與真正可串行化如果沒有執行謂詞鎖定,我們可以看到MVCC模型對可串行化的限制。

因此,讓我們測試它在MySQL:

CREATE TABLE t1 (
class integer, 
value integer 
) ENGINE=InnoDB; 

INSERT INTO t1 (`class`,`value`) VALUES 
    (1,10), 
    (1,20), 
    (2,100), 
    (2,200); 

現在我們將打開兩個不同的連接有兩個並行事務(T1和T2):

T1:

SET TRANSACTIOn ISOLATION LEVEL SERIALIZABLE; 
BEGIN; 
SELECT SUM(value) FROM t1 WHERE class = 1; 

結果爲30.

T2:

SET TRANSACTIOn ISOLATION LEVEL SERIALIZABLE; 
BEGIN; 
SELECT SUM(value) FROM t1 WHERE class = 2; 

結果是300

現在到了串行化問題。如果T1插入一行,使得T2的選擇無效(這裏T2的確如此)。

T1:

INSERT INTO t1 (`class`,`value`) VALUES (2,30); 

==>等待(鎖定就位)

T2:

INSERT INTO t1 (`class`,`value`) VALUES (1,300); 

==>錯誤1213(40001):嘗試鎖定時發現死鎖;嘗試重新啓動事務

T1現在成功在他插入,t2有一個ROLLBACK,良好的可串行化

這將在PostgreSQL 9.0上失敗(9.1版本正在改變,但這是另一個問題)。 其實只有一個的交易可以在表上執行插入。即使我們試圖在class=3上插入。

INSERT INTO t1 (`class`,`value`) VALUES (3,30); 

我們會看到一個等待的鎖,並在出現問題時出現死鎖。看起來我們在MySQL中有一個謂詞鎖定... 但實際上它是InnoDB中的next-key locking實現。

Innodb執行行鎖,並在索引上鎖定一些間隔。這裏我們沒有索引表,看起來像MySQL決定鎖定表。

因此,讓我們嘗試測試下一個鍵鎖定,看看這是否強制可串行化。首先回滾正在運行的事務(T1)。然後創建一個索引。

CREATE index t1class ON t1 (class); 

現在重做測試。 成功,序列化仍然執行。好消息。

但是,隨着索引就位,我認爲下一個鍵鎖定和行鎖定在索引上。這意味着我們應該能夠執行插入,如果它不影響並行事務... 並且這裏出現了大問題

T1:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
BEGIN; 
SELECT SUM(value) FROM t1 WHERE class = 1; 

結果是30。

T2:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
BEGIN; 
SELECT SUM(value) FROM t1 WHERE class = 2; 

結果是300。

在這裏,我們會去做的T1無關插入,現在我們有一個指標,這將成功:

T1:

INSERT INTO t1 (`class`,`value`) VALUES (3,30); 

既可以執行插入(在這裏我做了只有一個),這很正常。預測鎖定不適用,在class=3上沒有進行SELECT查詢。看起來像下一個鍵鎖定執行更好,如果我們給它良好的索引(插入沒有表鎖)。

現在我們嘗試插入在下一個鍵鎖,在T2的行匹配選擇(類= 2):

T1:

INSERT INTO t1 (`class`,`value`) VALUES (2,30); 

哎喲。它成功

T2:

INSERT INTO t1 (`class`,`value`) VALUES (1,300); 

==>等待。那裏仍然有鎖。希望。

T1:

COMMIT; 

T2:(其中鎖已消失了,插入件由)

SELECT SUM(value) FROM t1 WHERE class = 2; 
COMMIT; 

仍然具有300在這裏。似乎可序列化已經消失。

select * from t1; 
+-------+-------+ 
| class | value | 
+-------+-------+ 
|  1 | 10 | 
|  1 | 20 | 
|  2 | 100 | 
|  2 | 200 | 
|  3 | 30 | <-- test 
|  2 | 30 | <-- from trans1 
|  1 | 300 | <-- from trans2 ERROR! 
+-------+-------+ 

結果:通過插入行影響我們欺騙了下一鍵鎖定機制並行事務查詢之前插入新行無關。或者至少這是我從我的測試中瞭解到的。所以我會說,不相信真正的可串行化引擎。當你有聚合函數在一個事務中最好的事情是手動鎖表,將您的可串行化問題轉化爲真正的唯一一個人的情況,沒有驚喜!示例中的其他可串行性問題是約束驗證(在操作後檢查金額仍爲正數),您是否也擁有這些情況下的鎖定。

+2

我不明白。它在MySQL 5.5中仍然以這種方式工作嗎? – 2012-05-15 04:57:37

+0

@Seun Osewa:沒錯,我在5.5版本中試過,似乎表格被鎖定,也許錯誤的'索引優化'已被刪除。我再也找不到錯誤的序列化示例。 – regilero 2012-05-18 10:02:47

+0

我在這裏得到了一些downvotes,這很有趣,沒有評論,只是downvotes ...也許一個MySQL開發。 – regilero 2014-09-10 16:32:02

1

您確定您使用的是「可序列化」事務嗎?可以肯定的是,你必須使用「SET session TRANSACTION ISOLATION LEVEL SERIALIZABLE;」這樣整個會話就變成可序列化的,而不僅僅是下一個事務。

我與在5.5.29 OSX

測試,當我嘗試插入(3,30)在T1,階級創建了索引之後,交易將等待和鎖等待超時後中止。 (T2仍在進行中)

相關問題