1

我们使用 MySQL 和 Innodb 引擎存储。我们有一个“事件”环境,可以在一个表上发送多个并发请求。基本上,它的工作原理是这样的:我们有一个 find_or_insert 函数可以做到这一点: - find() -> 在结果上,如果为空 -> 插入 -> 在结果上 find()

我们使用的是非阻塞 MySQL 驱动程序,所以基本上,当我们同时启动这个小算法不止一次时,它会在插入第一个结果之前运行所有的发现......等等。

不幸的是,我们收到这些错误:“尝试获取锁定时发现死锁;尝试重新启动事务”

任何人都可以帮忙吗?

[编辑]:另外,我实际上不明白为什么 MySQL 需要锁定表只是为了在这里插入一个新元素。最初我虽然自动增量是这里的罪魁祸首,所以我删除了它......但我仍然得到错误。有没有办法防止 MySQL 在插入时锁定表?

4

3 回答 3

1

尝试mysql 参考手册进行诊断和解决。听起来您正在制作缓存。一个可能的原因可能是很多客户端同时点击表试图创建“第一个版本”(即点击“如果为空插入”)。也许您可以添加一个伪随机延迟或协调创建者,这样您就不会收到大量对数据库的并发创建调用?

编辑:你看过这个页面吗?似乎您需要设置一个 my.cnf 设置以使用 innodb 禁用每个表的锁。不过,我主要建议的是,您的测试可能无法表示,因为它可能包含比实际情况高得多的作者百分比。如果你用一个空表启动 100 个线程,它们都会在创建时立即阻塞(即使可能是相同的值)。这比在平均情况下要糟糕得多,在这种情况下,您可以更好地分布键、更少的未命中和更高的读取百分比。如果这是预期的行为(即您将拥有此行为),我建议在创建语句中添加退避策略。

于 2009-05-15T18:33:49.650 回答
0

您需要这些请求一次发生一个,因此可能停止使用该非阻塞驱动程序。或者实现你自己的阻塞机制。等待一个完成,然后再进行下一个。

你没有说这是不合理的,或者你出于某种原因需要这些事情这么快地进行。

于 2009-05-15T18:42:26.837 回答
0

我正在更改我的答案以反映该问题已被修改。现在听起来这只是并发插入的问题,而不是对查找行为的依赖。

据我了解,InnoDB 对插入进行行锁定,您不能将其关闭。但是,您 [edit] 无法使用 INSERT DELAYED。我刚刚读到这在 InnoDB 上不可用。

http://dev.mysql.com/doc/refman/5.0/en/insert-delayed.html

也许围绕所有写入的显式 LOCK TABLES 将覆盖默认锁定行为。如果在写事件发生的时间间隔内没有对表进行其他操作,这可能会起作用。

http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html

于 2009-05-15T18:58:35.487 回答