2012-05-07 44 views
0

我已閱讀本插入新的節點: Transaction safe insertion of node in nested set?嵌套集模型(分層數據)mysql的併發用戶的一致方式

,但我擔心的是嵌套集模型中插入新的節點鎖定。 我想插入一個新的節點在我的樹類別,但我想確保它插入的新節點沒有損壞。 MySQL中使用的引擎是InnoDb。 至於其他的問題說:

BEGIN; -- or whatever API your framework has for starting a transaction 
    SELECT @myLeft := lft FROM myTable WHERE ID = $id FOR UPDATE; 
    UPDATE myTable SET rgt = rgt + 2 WHERE rgt > @myLeft;  
    UPDATE myTable SET lft = lft + 2 WHERE lft > @myLeft;  
    INSERT INTO myTable(title, lft, rgt) VALUES($title, @myLeft + 1, @myLeft + 2); 
COMMIT; -- or whatever API your framework has for commiting a transaction 

我的問題是,如果併發用戶嘗試在同一棵樹上插入新的節點,做了交易就足夠了更新和調整左,其他節點的對不對? 如果user1添加新節點(在transaction1中執行)並且同時user2添加新節點(在transaction2中執行),我確定user2在用戶2插入新節點之前讀取帶有由user1添加的節點的更新樹? 因此,100個用戶在同一時間插入新節點,最後用戶必須等待,只要預覽用戶完成總是有一致性樹?

回答

0

InnoDB進行行級鎖定。因此更新的行將在事務處理期間被鎖定。這可能導致阻塞和死鎖。

如果正在更新一行InnoDB將無法獲取行上的鎖再次更新。這有效地序列化交易。請注意,事務隔離級別可以控制看到這個鏈接http://dev.mysql.com/doc/refman/5.1/en/dynindex-isolevel.html

這裏還有一篇關於如何在innodb引擎中尋找死鎖的有趣文章http://www.xaprb.com/blog/2006/07/31/how-to-analyze-innodb-mysql-locks/

如果嵌套集正在進行大量更新,以確保您具有正確的隔離級別並將您的語句包裝在事務中就足夠了。但是,它可能會產生需要編碼的鎖定,阻塞和死鎖問題。

+0

我很沮喪的鎖定,阻塞和死鎖,因爲我不能接受用戶等待很長時間或鎖定模擬故障服務。如果我不鎖定並僅使用事務,那麼樹可能會損壞,如果我使用事務並且我使用鎖可能會阻止所有事務。不同的方式或解決方案更小的邪惡? – paganotti

+0

確實。不過,我認爲讓用戶等待的時間比擁有他們不信任的損壞數據庫長一點。有辦法讓innodb跑得更快。例如,在單獨的RAID陣列上安裝innodb。這將允許innodb表擁有專用的IO。您需要對其進行壓力測試,然後設置用戶期望值。如果你告訴用戶1000萬人同時插入記錄的速度會變慢,你可能會減少投訴。 – Namphibian

+0

可以更正確使用SELECT ...鎖定共享模式?根據文檔「SELECT ... LOCK IN SHARE MODE」設置共享模式鎖定在任何被讀取的行上,其他會話可以讀取行,但在事務提交之前不能修改它們,如果這些行中的任何行被另一個事務那還沒有提交,你的查詢會等到這個事務結束,然後使用最新值。「如果user1添加節點,我可以鎖定正在添加節點的樹的行,其他用戶已經可以讀取數據,但同時其他用戶不能修改數據,直到user1進程中的事務處於運行狀態 – paganotti