0

0

php中原子操作与文件锁flock的介绍(代码示例)

不言

不言

发布时间:2019-01-28 10:00:48

|

2903人浏览过

|

来源于博客园

转载

本篇文章给大家带来的内容是关于php中原子操作与文件锁flock的介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

php原子操作,文件锁flock,数据库事务

php没有继承posix标准支持的unix锁,只封装了一个linux系统调用flock(信号量也能做成锁),按理也是可以使用锁机制的,虽然效率低一点。
php脚本是运行在fastcgi容器中,而fastcgi是多进程的,所以如果php程序访问了临界资源,势必造成程序结果的不正确性。
估计还要考虑下fastcgi容器的问题

问题描述:黑客用的工具刷我们的后台
取消订单时会有退款,黑客并发取消订单,导致多次退款
如果请求一个一个来,哪怕间隔100毫秒,也是没有问题的

一个PHP处理过程是: 读退款标志,发现没退款, 退款,然后设置已退款标志
问题是多个请求同时到了,读出来的退款标志都是未退款,所以多个请求都退款了
同一个php文件,被同时请求多次,是同一时刻

立即学习PHP免费学习笔记(深入)”;

用php文件锁flock 我们试了不行,还是用C++队列
用C++监听了一个端口,直接接收HTTP包,然后返回HTTP格式的包,PHP程序中用curl访问我这个C程序.
相当于远程调用了,可以部署到其他服务器做分布式了

很多时候,我们并没有考虑我们php代码的并行能力,尤其是在我们的php代码对某个资源可读可写的时候。但这并不是说php的所有操作就都是原子的,事务的,可并行的。由于php脚本是运行在fastcgi容器中,而fastcgi是多进程的,所以如果php程序访问了临界资源,势必造成程序结果的不正确性。

解决问题的办法是使用锁机制。php没有继承posix标准支持的unix锁:比如记录锁fcntl,线程锁等,而只封装了一个linux系统调用flock(信号量也能做成锁),flock形式为flock($fp,$type),其中$fp为文件句柄,而$type为:
/* 当一个文件的打开方式是可读可写的,通常需要向文件加入锁机制 */

1. LOCK_SH 共享锁:
通常为进程向文件请求读操作时需加共享锁。共享锁可支持任意个进程间的读操作,如果写一个加了共享锁的文件则进程阻塞进入SLEEP状态值到共享锁解锁

2. LOCK_EX 独占锁:
通常为进程向文件的写操作加独占锁,一旦文件加上了该锁,则其他任意进程访问该文件时都会阻塞,直到解锁为止。

3. LOCK_UN 解锁:
为加锁的文件句柄解锁

这样的加锁方式必然可以保证加锁程序块的原子性,但同时也牺牲了程序的效率,因此,我们实际的程序中应该在程序的加锁和解锁代码间嵌入尽量少的程序逻辑(尤其是独占锁),保证程序尽快解锁。

最后,附上加上锁机制以后的程序:

Kubit.ai
Kubit.ai

一个AI驱动的产品分析平台,为产品和数据团队构建

下载

普通情况运行该程序,产生正确的结果。

用什么方法可以在业务批量操作时保证原子性呢?
例如:删除多条文章,但在中间有一条已经被删除了,假设这里会出现错误,那如何让整个操作回滚,并定位错误信息呢?
数据库的事务保证原子性但不能定位错误信息,但遇到无法使用事务的场景,应该怎么做呢?

利用数据库的事务来做是最合理的,错误信息可以记录啊,有操作失败抛出错误。
应用逻辑来保证,就是每操作一次做下记录,成功失败都做下记录。中间出错,可以把成功的回滚。一般我们删除是假删除,所以很容易。如果真删除,记录时要记录完整信息。

PHP用文件锁模拟进程锁,实现原子操作
用PHP实现原子操作,而PHP本身并没有提供进程锁机制,用PHP文件锁机制,通过文件锁模拟进程锁实现原子操作。

原子操作的代码之前,使用排他锁打开某个文件,代码如下:

$fp = fopen( LOCK_FILE_PATH, "r" );
if (!$fp) {
 echo "Failed to open the lock file!"; 
 exit(1);//异常处理
 }
flock ( $fp, LOCK_EX );

原子操作的代码之后,对该文件解锁,并关闭文件,代码如下:

flock ( $fp, LOCK_UN );
fclose ( $fp );

整体伪代码为:

define("LOCK_FILE_PATH", "/tmp/lock");
if( !file_exists(LOCK_FILE_PATH) ){ 
$fp = fopen( LOCK_FILE_PATH, "w" );
fclose ( $fp );
}
$fp = fopen( LOCK_FILE_PATH, "r" );
if (!$fp) {
echo "Failed to open the lock file!";
exit(1);//异常处理
}
flock ( $fp, LOCK_EX );
//此处添加原子操作代码
flock ( $fp, LOCK_UN );
fclose ( $fp );

以上便可实现PHP原子操作,避免冲突。

php原子操作与mysql原子操作

原子操作常用的方法就是通过数据回滚来实现,用 PHP 来实现数据库回滚操作相当简单:
1, 建立数据库连接
2, mysql_query('BEGIN'); 开启事务
3, $SQL = "..."; 
mysql_query($SQL); 做相应的数据库操作
4, 判断回滚条件:
if(mysql_errno) 

print mysql_error(); 
mysql_query('ROLLBACK'); 出错就回滚 
exit(); 

5,可以重复上述步骤 3 及步骤 4 的操作, 开始的过程(中间可以加入其他操作,不局限于数据库更新,但是注意,最好不要让一个事务时间过长,因为它锁定所有你用到的表,会影响其他程序使用) 
你也可以在几条正确的sql更新语句后故意写一句错误的,看看是否回滚了。
6, 结束回滚操作
mysql_query('COMMIT'); 能够到这里,代表上述数据库操作都没有错,正式提交执行

这就是用 PHP 实现原子操作的整个过程,需要特别注意的是建立支持数据回滚操作的表结构,
另外,除 commit 外也有其它办法可以结束回滚操作。


相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

63

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

31

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

73

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

20

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

24

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

7

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

4

2026.01.13

交互式图表和动态图表教程汇总
交互式图表和动态图表教程汇总

本专题整合了交互式图表和动态图表的相关内容,阅读专题下面的文章了解更多详细内容。

49

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

11

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.6万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 6.9万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号