<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[php文件锁(转)]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Php/Js/Shell/Go]]></category>
<pubDate>Sat, 18 Aug 2012 01:55:17 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	锁：这种在脚本重复跑，加上文件锁是最有效的方法，以下介绍Php的文件锁使用方法。<br/><br/><br/>bool flock ( int handle, int operation [, int &amp;wouldblock] );<br/>flock() 操作的 handle 必须是一个已经打开的文件指针。operation 可以是以下值之一：<br/>要取得共享锁定（读取程序），将 operation 设为 LOCK_SH（PHP 4.0.1 以前的版本设置为 1）<br/>要取得独占锁定（写入程序），将 operation 设为 LOCK_EX（PHP 4.0.1 以前的版本中设置为 2）<br/>要释放锁定（无论共享或独占），将 operation 设为 LOCK_UN（PHP 4.0.1 以前的版本中设置为 3）<br/>如果你不希望 flock() 在锁定时堵塞，则给 operation 加上 LOCK_NB（PHP 4.0.1 以前的版本中设置为 4）<br/>建两个文件<br/>(1) a.php<br/>?<br/>$file = &quot;temp.txt&quot;;&nbsp;&nbsp;&nbsp;&nbsp;<br/>$fp = fopen($file , &#039;w&#039;);&nbsp;&nbsp;&nbsp;&nbsp;<br/>if(flock($fp , LOCK_EX))&#123;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; fwrite($fp , &quot;abc&#92;n&quot;);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; sleep(10);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; fwrite($fp , &quot;123&#92;n&quot;);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;flock($fp , LOCK_UN);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;<br/>fclose($fp);&nbsp;&nbsp; <br/>(2) b.php<br/>?<br/>$file = &quot;temp.txt&quot;;&nbsp;&nbsp;&nbsp;&nbsp;<br/>$fp = fopen($file , &#039;r&#039;);&nbsp;&nbsp;&nbsp;&nbsp;<br/>echo fread($fp , 100);&nbsp;&nbsp;&nbsp;&nbsp;<br/>fclose($fp);&nbsp;&nbsp; <br/>运行 a.php 后，马上运行 b.php ，可以看到输出：<br/>abc<br/>等 a.php 运行完后运行 b.php ，可以看到输出：<br/>abc<br/>123<br/>显然，当 a.php 写文件时数据太大，导致时间比较长时，这时 b.php 读取数据不完整<br/>修改 b.php 为：<br/>?<br/>$file = &quot;temp.txt&quot;;&nbsp;&nbsp;&nbsp;&nbsp;<br/>$fp = fopen($file , &#039;r&#039;);&nbsp;&nbsp;&nbsp;&nbsp;<br/>if(flock($fp , LOCK_EX))&#123;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;echo fread($fp , 100);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;flock($fp , LOCK_UN);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&#125; else&#123;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;Lock file failed...&#92;n&quot;;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;<br/>fclose($fp);&nbsp;&nbsp; <br/>运行 a.php 后，马上运行 b.php ，可以发现 b.php 会等到 a.php 运行完成后(即 10 秒后)才显示：<br/>abc<br/>123<br/>读取数据完整，但时间过长，他要等待写锁释放。<br/>修改 b.php 为：<br/>?<br/>$file = &quot;temp.txt&quot;;&nbsp;&nbsp;&nbsp;&nbsp;<br/>$fp = fopen($file , &#039;r&#039;);&nbsp;&nbsp;&nbsp;&nbsp;<br/>if(flock($fp , LOCK_SH &#124; LOCK_NB))&#123;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;echo fread($fp , 100);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;flock($fp , LOCK_UN);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&#125; else&#123;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;echo &quot;Lock file failed...&#92;n&quot;;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&#125;&nbsp;&nbsp;&nbsp;&nbsp;<br/>fclose($fp);&nbsp;&nbsp; <br/>运行 a.php 后，马上运行 b.php ，可以看到输出：<br/>Lock file failed…<br/>证明可以返回锁文件失败状态，而不是向上面一样要等很久。<br/>结论：<br/>建议作文件缓存时，选好相关的锁，不然可能导致读取数据不完整，或重复写入数据。<br/>file_get_contents 好像选择不了锁，不知道他默认用的什么锁，反正和不锁得到的输出一样，是不完整的数据。<br/>我是要做文件缓存，所以只需要知道是否有写锁存在即可，有的话就查数据库就可以了。<br/>测试环境：Linux(Ubuntu 6) , PHP 5.1.2 , Apache 2<br/>再转：<br/>文件锁有两种：共享锁和排他锁，也就是读锁(LOCK_SH)和写锁(LOCK_EX) <br/>文件的锁一般这么使用：<br/>$fp = fopen(&quot;filename&quot;, &quot;a&quot;);&nbsp;&nbsp; <br/>flock($fp, LOCK_SH) or die(&quot;lock error&quot;)&nbsp;&nbsp; <br/>$str = fread($fp, 1024);&nbsp;&nbsp; <br/>flock($fp, LOCK_UN);&nbsp;&nbsp; <br/>fclose($fp);&nbsp;&nbsp;<br/><br/>注意fwrite之后，文件立即就被更新了，而不是等fwrite然后fclose之后文件才会更新，这个可以通过在fwrite之后fclose之前读取这个文件进行检查 <br/><br/>但是什么时候使用lock_ex什么时候使用lock_sh呢？ <br/><br/>读的时候： <br/>如果不想出现dirty数据，那么最好使用lock_sh共享锁。可以考虑以下三种情况： <br/>1. 如果读的时候没有加共享锁，那么其他程序要写的话（不管这个写是加锁还是不加锁）都会立即写成功。如果正好读了一半，然后被其他程序给写了，那么读的后一半就有可能跟前一半对不上（前一半是修改前的，后一半是修改后的） <br/>2. 如果读的时候加上了共享锁（因为只是读，没有必要使用排他锁），这个时候，其他程序开始写，这个写程序没有使用锁，那么写程序会直接修改这个文件，也会导致前面一样的问题 <br/>3. 最理想的情况是，读的时候加锁(lock_sh),写的时候也进行加锁(lock_ex),这样写程序会等着读程序完成之后才进行操作，而不会出现贸然操作的情况 <br/><br/>写的时候： <br/>如果多个写程序不加锁同时对文件进行操作，那么最后的数据有可能一部分是a程序写的，一部分是b程序写的 <br/>如果写的时候加锁了，这个时候有其他的程序来读，那么他会读到什么东西呢？ <br/>1. 如果读程序没有申请共享锁，那么他会读到dirty的数据。比如写程序要写a,b,c三部分，写完a,这时候读读到的是a，继续写b，这时候读读到的是ab，然后写c，这时候读到的是abc. <br/>2. 如果读程序在之前申请了共享锁，那么读程序会等写程序将abc写完并释放锁之后才进行读。 <br/>还有一篇也写得不错的博文：<br/>http://hxsdit.com/1110
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] php文件锁(转)]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>