如何实现基于数据库锁定的防止重复的保护
在使用InnoDB存储引擎的Web应用程序中,我无法在以下情况下充分利用数据库锁定。如何实现基于数据库锁定的防止重复的保护
有3个表格,我会称它们为aa
,ar
和ai
。
aa
拥有基本记录,让我们说文章。 ar
保存与每个aa
记录有关的信息,并且aa
和ar
之间的关系是1:m
。
ar
的记录存储在aa
的记录被读取时第一次被存储。问题是当两个请求在(几乎)相同时从aa
(它还没有将其相关记录存储在ar
中)读取记录时发起,ar
记录被复制。
下面是一个伪代码,以帮助了解情况:
阅读要求
aa
记录。扫描
ar
表以确定给定的aa
记录是否已存储任何内容。 (假设它没有。)请参阅
ai
以便找出在给定的aa
记录中要存储在ar
中的内容。 (ai
似乎有点风马牛不相及,但我发现它也有参与锁定...可能是错误的。)插入几行
ar
这里是我想达到的目标:
- 阅读请求的
aa
记录。
使用或不使用交易,LOCK ar
,所以任何后续请求试图读取ar
将等待AT这一点直到这个顺序完成。
扫描
ar
表,以发现如果给定aa
记录已经存储了什么。 (假设它没有。)问题是,如果有两个同时发生的请求,两个发现对于给定的aa
记录在ar
中没有记录,并且它们都继续插入相同的行两次。否则,如果存在,则会中断此序列并且不会发生INSERT。咨询
ai
为了找出在给定的aa
记录中要存储在ar
中的内容。 (ai
似乎有点不相关,但我发现它也必须参与锁定...可能是错误的。)插入几行
ar
解除锁定ON ar
似乎很简单,我是在避免重复失败。我正在测试Bash shell中一个简单命令的同时请求(使用wget)。
我已经花了一段时间学习如何锁定InnoDB引擎在这里http://dev.mysql.com/doc/refman/5.5/en/innodb-lock-modes.html和这里http://dev.mysql.com/doc/refman/5.5/en/innodb-locking-reads.html如何工作,并尝试了几种方法来利用锁,仍然没有运气。
我希望整个ar
表被锁定(因为我想阻止来自多个请求的INSERT发生)导致进一步尝试与此表交互以等待,直到第一个锁被释放。但是只有一处提到“整个表”被锁定在文档中(第一个链接页面中的“意图锁定”部分),但没有进一步讨论,或者我无法知道如何实现它。
任何人都可以指出正确的方向吗?
SET tx_isolation='READ-COMMITTED';
START TRANSACTION;
SELECT * FROM aa WHERE id = 1234 FOR UPDATE;
这确保了一次只有一个线程可以访问aa
中的给定行。根本不需要锁定ar
表,因为任何其他想要访问行1234的线程都将等待。
然后查询ar
以找出相应的aa
存在哪些行,并决定是否要插入更多行到ar
。
请记住,aa
中的行仍处于锁定状态。因此,快速完成工作,成为一名优秀的公民,迅速做出承诺。
COMMIT;
这允许下一个等待同一行aa
的线程继续进行。通过使用READ-COMMITTED
,它将能够在ar
中看到刚提交的新行。
感谢您的提示,并看似亲水平的答复。我马上给它一下,如果它有效,就更新你。 – marekful 2014-10-16 20:00:10
当然(虽然问题已经太长了),但真实的生活情况要复杂得多,而且在请求过程中涉及许多其他查询。到目前为止,我遇到了'一般错误:2014无法执行查询,而其他未缓冲的查询处于活动状态',但不会放弃,这似乎是要走的路。 – marekful 2014-10-16 20:15:33
@MarcellFülöp,你可能喜欢阅读我的回答[MySQL的错误原因2014无法执行查询,而其他未缓冲的查询处于活动状态](http://stackoverflow.com/questions/17434102/causes-of-mysql-error-2014 -cannot-execute-queries-while-other-unbuffered-queries/17582620#17582620) – 2014-10-16 21:47:52