【问题标题】:concurrency in innodbinnodb 中的并发
【发布时间】:2011-06-23 04:25:42
【问题描述】:

我有这样的代码

reserve.php

$r=mysql_query("select count(*) from ticket");
$rec=mysql_fetch_array($r);
if ($rec[0]==0)
{
insert into ticket values .....
}

我只有一张票。 两个用户请求reserve.php。

"a" 用户请求reserve.php 并且可用票是 0 。但在插入之前,对于“b”用户可用的票是 0。所以两个用户订票。

表是 Innodb。 如何防止这种情况?事务,锁表还是什么?

【问题讨论】:

    标签: php mysql concurrency innodb


    【解决方案1】:

    在这些情况下,我通常只使用 UPDATE 语句并检查更新影响了多少记录(mysql_affected_rows)。

     UPDATE tickets SET ticket_count=ticket_count-1 WHERE ticket_id=123 AND ticket_count>0
    

    如果其他人先递减计数器,则不会发生更新,并且您不会给用户一张票。应该启用自动提交,以便更新是一个独立的“事务”。

    或者,您可以将 SELECT 更改为 SELECT ... FOR UPDATE http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html

    【讨论】:

    • 在select for update和insert之前需要使用set tranaction吗?
    • 我认为是的。 “当事务提交或回滚时,LOCK IN SHARE MODE 和 FOR UPDATE 读取设置的锁被释放”。
    【解决方案2】:

    我会在单个事务中执行此操作,而无需返回到应用程序级别 - SELECT count() ....INSERT INTO 在 PHP 的单个命令中发送并嵌入到带有 EXCLUSIVE LOCKTRANSACTION

    【讨论】:

    • 如何设置独占锁?。如果 2 个用户同时看到交易怎么办?
    • 正如 Brent 所指出的 - 在 MySQL 中 EXCLUSIVE LOCK 被称为 SELECT ... FOR UPDATE
    猜你喜欢
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 2014-03-30
    • 2014-11-18
    • 2018-07-05
    • 1970-01-01
    • 2018-08-04
    • 2012-01-13
    相关资源
    最近更新 更多