如何实现基于数据库锁定的防护重复保护

时间:2014-10-16 19:34:04

标签: mysql innodb database-locking

在使用InnoDB存储引擎的Web应用程序中,我无法在以下场景中充分利用数据库锁定。

有3个表格,我会称之为aaarai

aa保存基本记录,让我们说文章。 ar包含与每个aa记录相关的信息,aaar之间的关系为1:m

ar中的记录在第一次首次读取aa的记录时存储。问题是当两个请求(几乎)相同时从aa读取记录(其ar中尚未存储其相关记录)时,ar记录是重复的。

这是一个有助于了解情况的伪代码:

  • 阅读请求的aa记录。

  • 扫描ar表以查明给定的aa记录是否已存储任何内容。 (假设没有。)

  • 请参阅ai,以了解ar对于给定的aa记录要存储的内容。 (ai似乎有点无关紧要,但我发现它也必须参与锁定......可能是错误的。)

  • ar

  • 中插入几行

这是我想要实现的目标:

  • 阅读请求的aa记录。

有或没有使用交易,锁定ar,所以任何后续请求都要在ar之前阅读,在这一点完成之前等待这一点。

  • 扫描ar表以查明给定的aa记录是否已存储任何内容。 (假设它没有。)问题是,在两个同时发出的请求的情况下,两者都发现ar中没有给定aa记录的记录,并且它们都继续插入相同的行两次。否则,如果有,则此序列被中断且不会发生INSERT。

  • 请参阅ai,以了解ar对于给定的aa记录要存储的内容。 (ai似乎有点无关紧要,但我发现它也必须参与锁定......可能是错误的。)

  • ar

  • 中插入几行

释放ar

上的锁定

看起来很简单,我没有成功避免重复。我正在测试来自Bash shell中的简单命令的同时请求(使用wget)。

我花了一段时间来学习如何使用InnoDB引擎({3}}和http://dev.mysql.com/doc/refman/5.5/en/innodb-lock-modes.html完全锁定,并尝试了几种方法来使用锁,但仍然没有运气。

我希望整个ar表被锁定(因为我想阻止INSERT发生多个请求)导致进一步尝试与此表交互以等到第一个锁被释放。但是,只有一个提及"整个表"被锁定在文档中(第一个链接页面中的Intention Locks部分),但没有进一步讨论,或者我无法确定如何实现它。

有人能指出正确的方向吗?

1 个答案:

答案 0 :(得分:1)

SET tx_isolation='READ-COMMITTED';
START TRANSACTION;
SELECT * FROM aa WHERE id = 1234 FOR UPDATE;

这确保了一次只有一个线程可以访问aa中的给定行。根本不需要锁定ar表,因为任何其他可能想要访问第1234行的线程都会等待。

然后查询ar以找出相应aa的存在行,并决定是否要向ar插入更多行。

请记住,aa中的行仍处于锁定状态。因此,通过快速完成工作成为一个好公民,并立即进行COMMIT。

COMMIT;

这允许等待同一行aa的下一个线程继续进行。使用READ-COMMITTED,它将能够在ar中看到刚刚提交的新行。