mysql中的并发请求问题

时间:2009-06-28 09:01:12

标签: php mysql

我遇到以下问题

function book($memberid, $classid){
if (!book){
 // update the db and change the book variable to true
}
}

我的问题是同时提交了2个请求。 第一个请求通过行if(!book){但尚未更新数据库。同时,第二个请求运行相同的函数,并且如果(!book){也传递该行。因此,结果是错误的。

我想知道如何解决这个并发问题。 锁定数据库?但我担心它会影响性能。

4 个答案:

答案 0 :(得分:1)

为什么需要那个变量?

更新数据库时解决并发问题的标准方法是让数据库通过事务处理它(在某些情况下会影响性能,但代码解决方案也是如此)。

我想看看if(!book)子句中的内容。

编辑:为什么不更改数据库以使(人,类)组合成为唯一键?这样你只是在物理上不能在表中插入两倍相同的值。我还在猜测,因为它取决于数据库的结构。 MySQL也有一个特殊的语法来执行适合这里的条件插入。请检查此url

答案 1 :(得分:0)

如果您create an unique index(person,class),您只需尝试插入新记录,而无需任何先前的标记。如果在(人,类)中已经存在具有相同值的另一条记录,则新记录将被拒​​绝,并且MySQL会引发"duplicate key" error,这可以由您的脚本正确处理:

if ( 1062===mysql_errno() ) {
  echo "you've already made a reservation for this lecture.";
}

答案 2 :(得分:0)

你能用吗

UPDATE x SET y WHERE z
然后只需check affected rows看看是否有任何改变?这样,MYSQL可以在一个平滑的原子事务中有效地执行检查和实际数据更改,而不会出现并发问题。 (我的基础是你使用“更新”这个词而不是“插入”你的Q;如果它是插入这个方法将不起作用,但VolkerK会这样做)

如果你真的必须通过SELECT检查然后通过UPDATE写作2个单独的语句,那么事务是唯一的方法。你提到锁定数据库 - 请注意,这不是唯一可用的选项。如果您使用InnoDB表,则可以使用许多不同的级别。

答案 3 :(得分:0)

更一般而言,如果要通过并发访问来保护一段代码,关于底层操作系统,一种方法是使用编译器随附的库提供的功能。

在C / C ++中,功能类似于:

EnterCriticalSection ([Initialized]Section_ID);
< CODE_TO_PROTECT >
LeaveCriticalSection ([Initialized]Section_ID);

但是,就您而言,也许可以通过以下修改(如果您的语言可用)来提高策略效率:

global: 
bool book = TRUE;

function book($memberid, $classid){
  while (!book); \\ this waits until the variable 'book' isn't TRUE
  // eventually, release the control of the task scheduler with:
  // while (!book) Sleep (1); 
  // performing a check every each millisecond.

  // then, first of all, set the variable to FALSE
  book = FALSE;

  // update the db
  ...
  ...

  // finally, set the variable 'book' again to TRUE...
  book = TRUE;
 }