php如何解决并发问题,PHP如何解决并发问题

PHP如何解决并发问题

有个问题:

一个进程开启事务对表的某一行做了修改,但还没有提交,另一个进程查询该行数据,获取到的是原始的,这时候上面的事物提交了,我再用这个原始数据的时候就有问题……

那我们该怎么解决这个问题呢?

1、文件锁

如果对该表的更新或插入只有一个文件,这种方式是可以解决的

实现方式如下:

public static functioncbInventoryReserve() {$LOCK_FILE_PATH = $_SERVER[‘DOCUMENT_ROOT‘]."wmsinventoryapi/inventory/InventoryReserve.php";$fp = fopen( $LOCK_FILE_PATH, "r");if (!$fp) {die("Failed to open the lock file!");

}flock ( $fp,LOCK_EX );//需要进行的操作

$params = Flight::request()->getBody();$params = json_decode($params, true);if (! is_array($params) || empty($params)) {

Flight::sendRouteResult(array("error_code" => "40002","error_info" => "params empty"));

}$result = \Inventory\InventoryEngine::getInstance()->inventoryReserve($params);flock ( $fp,LOCK_UN );fclose ( $fp);

Flight::sendRouteResult($result);

}

函数说明  flock()会依参数operation所指定的方式对参数fd所指的文件做各种锁定或解除锁定的动作。此函数只能锁定整个文件,无法锁定文件的某一区域。

参数  operation有下列四种情况:

LOCK_SH 建立共享锁定。多个进程可同时对同一个文件作共享锁定。

LOCK_EX 建立互斥锁定。一个文件同时只有一个互斥锁定。

LOCK_UN 解除文件锁定状态。

LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。通常与LOCK_SH或LOCK_EX 做OR(|)组合。

单一文件无法同时建立共享锁定和互斥锁定,而当使用dup()或fork()时文件描述词不会继承此种锁定。

返回值  返回0表示成功,若有错误则返回-1,错误代码存于errno。

换言之:

使用共享锁LOCK_SH,如果是读取,不需要等待,但如果是写入,需要等待读取完成。

使用独占锁LOCK_EX,无论写入/读取都需要等待。

LOCK_UN,无论使用共享/读占锁,使用完后需要解锁。

LOCK_NB,当被锁定时,不阻塞,而是提示锁定。

为了更好的移植性,对于文件的打开与关闭我选择了fopen和fclose的组合,但flock的第一个参数要求的是int类型的文件描述符。这里对fopen返回的FILE类型的文件指针进行转换,转换为int型的文件描述符 (假设open函数返回的文件描述符为fd,而fopen返回的文件指针为*fp,则fd等价于fp->_fileno).

2、序列化接口(对象序列化)

所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。unserialize()函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

classA {public $one = 1;public functionshow_one() {echo $this->one;

}

}//page1.php:

include("classa.inc");$a = newA;$s = serialize($a);//把变量$s保存起来以便文件page2.php能够读到

file_put_contents(‘store‘, $s);//page2.php:

// 要正确了解序列化,必须包含下面一个文件

include("classa.inc");$s = file_get_contents(‘store‘);$a = unserialize($s);//现在可以使用对象$a里面的函数 show_one()

$a->show_one();?>

3、select *** for update

Select …forupdate语句是我们经常使用手工加锁语句。通常情况下,select语句是不会对数据加锁,妨碍影响其他的DML和DDL操作。同时,在多版本一致读机制的支持下,select语句也不会被其他类型语句所阻碍。

借助for update子句,我们可以在应用程序的层面手工实现数据加锁保护操作。

for update子句的默认行为就是自动启动一个事务,借助事务的锁机制将数据进行锁定。

开启一个事务使用for update

start transaction;

select sum(quantity) from ws_inventory_item where inventory_item_id=86 for update;

再开启另一个事务时,做update 操作的时,只能等待上面的事务,commit才能执行;

start transaction;update ws_inventory_item set quantity = quantity + 1 where inventory_item_id = 86;

原文:http://www.cnblogs.com/sdgf/p/5740998.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值