论坛首页 编程语言技术论坛

php同步方案2-飞机票问题

浏览 15382 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-10-06   最后修改:2011-10-06
PHP
问题是:飞机票销售系统,现在只剩一张票了,两个请求同时到来

请注意:以下解决方案要求mysql表引擎必须是innodb。

$db = getdb();
$db->query('SET AUTOCOMMIT=0');
$db->query('START TRANSACTION'); 

$sql = " select id from air_ticket where isactive=1 and batch='today' for update";//查今天的有效飞机票,for update 是重点。
$result = $db->fetchOne($sql); //因为顾客只想买一张票
if ($result) { //还有票
   $db->query("update air_ticket set isactive=0 where  batch='today' and id=". $result); //发了一张票
} 
$db->query('COMMIT');
$db->query('SET AUTOCOMMIT=1');

if ($result) {
  echo "您购买的机票id是".$result;
} else {
   echo '对不起,机票已卖完';
}

   发表时间:2011-10-07   最后修改:2011-10-07
还有一种做法,乐观法:

开启事务:

直接减1,

检查剩余机票是否是负数。

如果是回滚,并告诉用户错误。

如果不是,提交事务。


不过这个做法有并发的隐患,不好,只能用于允许一些错误的场合。
可能要把事务隔离级别设为不可重复读,或脏读以看到别的事务的修改。
0 请登录后投票
   发表时间:2011-10-07  
同步方案一的方法是同步,for update的方法是用innodb的行锁。

究竟该用哪种,取决于项目中的别的代码。

如果操作机票表只有很少的几个文件,可以同步
如果操作机票表只有文件很多,同步不过来(因为那样系统太卡了),只能行锁。

如果写操作并发少,行锁,
写操作并发多,行锁会影响别的写操作,那么同步可以。
(针对这一点,如果用行锁,需要适当分表)

需要同步的代码很少,系统能很快执行完,优先同步,同步正确率应该高,理论上是这样。
反之只能行锁。


0 请登录后投票
   发表时间:2011-10-08  
for update
0 请登录后投票
   发表时间:2011-10-10  
剩一张票了,两个请求同时到来。

把两个请求放到队列中。先到先得。
0 请登录后投票
   发表时间:2011-10-10  
jinhanjiang 写道
剩一张票了,两个请求同时到来。

把两个请求放到队列中。先到先得。

  是的 这个时候就可以玩玩NODE JS
0 请登录后投票
   发表时间:2011-10-10  
mysql 高版本可以用这个来模拟排队
SELECT GET_LOCK
0 请登录后投票
   发表时间:2011-10-10  
jinhanjiang 写道
剩一张票了,两个请求同时到来。

把两个请求放到队列中。先到先得。


一般来说订机票要立刻看到结果,就是不异步,那么实际上还是同步了。

同步 的情况就跟调用mysql的get_lock差不多。
0 请登录后投票
   发表时间:2011-10-13  
for update很容易造成死锁,不建议用

如果允许失败,可以这样
$db->query("update air_ticket set isactive=0 where  batch='today' and isactive=1 and id=". $result);
update时增加 isactive=1

0 请登录后投票
   发表时间:2011-10-14  
synchronized
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics