2012-05-07 43 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