1

我正在使用嵌套集将分层数据存储在 MyISAM 表中;该表由每个用户的几个层次结构集组成。每个用户将是唯一一个写入其各自树的人,但其他用户可以读取它们。节点删除/插入要求同一树中的其他行更新其 lft 和 rgt 值,可能有数百行。

为了做到这一点,我需要获得一个表写锁,更新树中的其他节点,删除/插入行并解锁表。

我想知道的是——表锁是否可以扩展到数百个并发用户?数千?

在这种情况下,InnoDB 的行锁会更有效吗?(锁定几百行,主要由用户自己使用)

如果我要使用行锁,是否需要添加显式逻辑来处理死锁错误?

4

1 回答 1

5

好吧,两个引擎之间的锁定原理是不同的。

使用 MyISAM,全表锁定的原因是写入通常应该很快。写入只需要两个操作(锁定表,然后将行写入磁盘)。由于这个原因,MyISAM 的性能确实受磁盘速度的限制。

使用 InnoDB,它变得有点复杂。由于它完全符合 ACID,因此每次写入都需要 4 个步骤(锁定行、写入事务日志、写入行到磁盘、写入事务日志)。请注意,它会写入磁盘 3 次。所以这意味着(在实践中)InnoDB 写入将比 MyISAM 写入花费 3 倍的时间。这是行级锁定的一个原因(事务是另一个)。

但这并不容易。使用 MyISAM,表锁需要一个用于该表的信号量。因此,对内存使用和速度的影响充其量是微不足道的。然而,对于 InnoDB,它需要一个索引和每行一个信号量。它需要一个索引来加速“检查”以查看该行是否已经有锁。现在,如果您同时更新 1 行或 10 行,差别不大。但是,当您谈论数百万行时,差异可能并非微不足道(无论是在内存使用情况还是在速度方面,因为它需要横向锁定要锁定的每一行的锁定“索引”)。

还有一个额外的权衡。由于 InnoDB 符合 ACID,因此如果出现断电(或其他崩溃),您永远不会处于不一致的状态。数据库中没有未提交的事务数据,也没有已提交的事务损坏(如果检测到要修复的内容,它将自动运行事务日志)。使用 MyISAM,写入过程中的断电(或崩溃)会使表处于不一致的状态,您对此无能为力。如果你关心你的数据,InnoDB 会更好。但是,有了良好的二进制日志和备份系统,您应该能够恢复 MyISAM,但这需要一些手动干预......

现在,话虽如此,你关于哪个规模更好的问题真的很难。首先,您的大部分作品都是处理一两行吗?如果是这样,InnoDB 和行级锁定将倾向于更好地扩展。如果您同时执行大量查询更新大量行(数万甚至更多),您会注意到 MyISAM 往往具有更好的性能。

至于您的死锁问题,MySQL 将为您定位并处理它们(但它不会执行其中一个查询,因此您可能需要一些异常处理代码来重试查询或其他内容)。内部系统将防止死锁...

现在,另一个注意事项。既然 MySQL 在一个 db 中支持多个引擎,为什么不把你的数据放到 InnoDB 中,然后做一个 MyISAM 连接表来处理嵌套的集合数据呢?将育儿信息存储在数据表中(通过parent_id机制)。这样,您的所有数据都在符合 ACID 的数据库中,但是您可以通过使用更快的(用于读取和大量写入)MyISAM 用于嵌套集逻辑来提高速度......

于 2010-06-19T12:19:32.210 回答