innodb 中的并发
我有一个这样的代码
Reserve.php
$r=mysql_query("select count(*) from ticket");
$rec=mysql_fetch_array($r);
if ($rec[0]==0)
{
insert into ticket values .....
}
我只有 1 张票。 两个用户请求reserve.php。
“a”用户请求 Reserve.php 且可用票证为 0 。但在插入之前,对于“b”用户,可用票证还为 0。所以两个用户预订票。
表是Innodb。 如何防止这种情况?事务、锁表还是什么?
i have a code like this
reserve.php
$r=mysql_query("select count(*) from ticket");
$rec=mysql_fetch_array($r);
if ($rec[0]==0)
{
insert into ticket values .....
}
i have 1 ticket only.
two users request reserve.php.
"a" user request reserve.php and available ticket is 0 . but before insert, for "b" user available ticket is 0 yet. so two users reserve ticket.
table is Innodb.
how to prevent this? transaction , lock table or what?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这些情况下,我通常只使用 UPDATE 语句并检查有多少记录受到更新的影响 (mysql_affected_rows)。
如果其他人首先递减计数器,则不会发生更新,并且您不会向用户提供票证。应启用自动提交,以便更新是一个独立的“事务”。
或者,您可以将 SELECT 更改为 SELECT ... FOR UPDATE
http://dev.mysql.com/doc/refman /5.0/en/innodb-locking-reads.html
In these situations I usually just use an UPDATE statement and check how many records were affected (mysql_affected_rows) by the update.
If someone else decremented the counter first, then no update occurs and you don't give the user a ticket. Autocommit should be enabled so the update is a self-contained "transaction".
Alternatively, you can change your SELECT to be SELECT ... FOR UPDATE
http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html
我会在单个事务中完成此操作,无需往返应用程序级别 -
SELECT count() ....
和INSERT INTO
均在单个命令中发送来自 PHP 并嵌入到带有EXCLUSIVE LOCK
的TRANSACTION
中I would do it in a single transaction, without a roundtrip back to the application level - both
SELECT count() ....
andINSERT INTO
being sent in a single command from PHP and embedded into aTRANSACTION
withEXCLUSIVE LOCK