<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>闫鹏 blog &#187; 程序员</title>
	<atom:link href="http://www.mirecle.com/category/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://www.mirecle.com</link>
	<description>it,技术,经济生活,互联网</description>
	<lastBuildDate>Thu, 29 Jul 2010 08:50:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>sql运行简单封装</title>
		<link>http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html</link>
		<comments>http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html#comments</comments>
		<pubDate>Fri, 23 Jul 2010 09:06:39 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[代码库]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96133</guid>
		<description><![CDATA[作为一个QA，我本来是很少写代码的，不过这段代码用的次数比较多，每次用的时候都改一些，比较烦，所以整理了一个通用的，作为个人代码库的第一块石头吧 升级于2010-7-26，修复bug class sql_runner{ private static $_arr_self = array(); private $_addr = false; private $_user = false; private $_passwd = false; private $_db_connection = false; static function get_instance($addr, $user, $passwd){ $key = $addr.'#'.$user.'#'.$passwd; if(false === array_key_exists($key, self::$_arr_self)){ sql_runner::$_arr_self[$key] = new sql_runner($addr, $user, $passwd); } return sql_runner::$_arr_self[$key]; } private function __construct($addr, $user, $passwd){ $this->_addr = $addr; [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
<li><a href='http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html' rel='bookmark' title='Permanent Link: 利用语言的动态特性减少switch'>利用语言的动态特性减少switch</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>作为一个QA，我本来是很少写代码的，不过这段代码用的次数比较多，每次用的时候都改一些，比较烦，所以整理了一个通用的，作为个人代码库的第一块石头吧<br />
升级于2010-7-26，修复bug</p>
<pre class="brush: php">
class sql_runner{

	private static $_arr_self = array();

	private $_addr = false;
	private $_user = false;
	private $_passwd = false;
	private $_db_connection = false;

	static function get_instance($addr, $user, $passwd){
		$key = $addr.'#'.$user.'#'.$passwd;
		if(false === array_key_exists($key, self::$_arr_self)){
			sql_runner::$_arr_self[$key] = new sql_runner($addr, $user, $passwd);
		}

		return sql_runner::$_arr_self[$key];
	}

	private function __construct($addr, $user, $passwd){
		$this->_addr = $addr;
		$this->_user = $user;
		$this->_passwd = $passwd;
	}

	public function run_sql($sql){

		if(false === $this->_db_connection || !mysql_ping($this->_db_connection)){
			UB_LOG_DEBUG("connecting db $this->_addr, $this->_user");
			$this->_db_connection = mysql_connect($this->_addr, $this->_user, $this->_passwd);

			if(false === $this->_db_connection){
				UB_LOG_FATAL("connect db failed: ".mysql_error());
				return false;
			}else{
				mysql_set_charset('latin1;', $this->_db_connection);
			}
		}

		$result = false;
		$result = mysql_query($sql, $this->_db_connection);
		if(false === $result){
			UB_LOG_FATAL("[$sql] execute failed:". mysql_error($this->_db_connection)."\n");
			return false;
		}

		$result_arr = array();
		if(is_resource($result)){
			while($row = mysql_fetch_assoc($result)){
				$result_arr[] = $row;
			}
			mysql_free_result($result);
		}

		UB_LOG_DEBUG("[$sql] execute succed, selected result:".print_r($result_arr, true));
		return $result_arr;
	}

}

/**for log functions*/
if(!function_exists('UB_LOG_DEBUG')){
	function UB_LOG_DEBUG($log){
		print($log);
	}
}
if(!function_exists('UB_LOG_FATAL')){
	function UB_LOG_FATAL($log){
		print($log);
	}
}
</pre>
本文永久链接:<a href="http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html">http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
<li><a href='http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html' rel='bookmark' title='Permanent Link: 利用语言的动态特性减少switch'>利用语言的动态特性减少switch</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>sigterm sigint sigkill 区别</title>
		<link>http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html</link>
		<comments>http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html#comments</comments>
		<pubDate>Thu, 20 May 2010 12:02:03 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96096</guid>
		<description><![CDATA[我看网上应该有不少搜索这个区别的问题，但是回答的都不全面，其中sigterm与sigint尤其有一点区别比较重要，但大都没有提及，今天我就遇到了这个问题，纠结了20分钟才搞明白咋回事。 首先，对于说这几个信号都是终止程序运行的说法不太准确，因为程序收到信号后，如果不对信号处理，就会导致程序退出，但如果程序捕获信号进行处理，按照它的逻辑，它是不一定会退出的。 在这三个信号中，sigkill是不能被捕获的，程序收到这个信号后，一定会退出。这就是kill -9一定能保证将程序杀死的原因。 下面说一下sigterm与sigint的区别，其中有一点区别区别很多文章都没有提及，也是我写这篇blog的原因（如果人家都写了，我就不用写了呗） 信号 产生方式 对进程的影响 sigint 通过ctrl+c将会对当进程发送此信号 信号被当前进程树接收到，也就是说，不仅当前进程会收到信号，它的子进程也会收到 sigterm kill命令不加参数就是发送这个信号 只有当前进程收到信号，子进程不会收到。如果当前进程被kill了，那么它的子进程的父进程将会是init，也就是pid为1的进程 下面这两个代码片段就能够验证这种情况(注意使用pcntl的时候，一定要declare ticks，要不然会杯具的发现函数没有被调用，进程不退出，信号发过去没有作用。php手册竟然没有强调这一点)： 文件：loadhelper.php #为了pcntl能够截获信号 declare(ticks = 1); $arr_processes = array(); function terminate($signo){ echo "aaaaaaaaaaa\n"; } pcntl_signal(SIGTERM, "terminate", true); pcntl_signal(SIGINT, "terminate", true); foreach($argv as $key =&#62; $operation){ if(0 === $key){ continue; } $pipes = array(); $process = proc_open($operation, array(), &#38;$pipes); if(false === [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html' rel='bookmark' title='Permanent Link: 文件grep-选出两个文件中相同/不同的内容'>文件grep-选出两个文件中相同/不同的内容</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>我看网上应该有不少搜索这个区别的问题，但是回答的都不全面，其中sigterm与sigint尤其有一点区别比较重要，但大都没有提及，今天我就遇到了这个问题，纠结了20分钟才搞明白咋回事。</p>
<p>首先，对于说这几个信号都是终止程序运行的说法不太准确，因为程序收到信号后，如果不对信号处理，就会导致程序退出，但如果程序捕获信号进行处理，按照它的逻辑，它是不一定会退出的。</p>
<p>在这三个信号中，sigkill是不能被捕获的，程序收到这个信号后，一定会退出。这就是kill -9一定能保证将程序杀死的原因。</p>
<p>下面说一下sigterm与sigint的区别，其中有一点区别区别很多文章都没有提及，也是我写这篇blog的原因（如果人家都写了，我就不用写了呗）</p>
<table border="0">
<tbody>
<tr>
<td>信号</td>
<td>产生方式</td>
<td>对进程的影响</td>
</tr>
<tr>
<td>sigint</td>
<td>通过ctrl+c将会对当进程发送此信号</td>
<td>信号被当前进程树接收到，也就是说，不仅当前进程会收到信号，它的子进程也会收到</td>
</tr>
<tr>
<td>sigterm</td>
<td>kill命令不加参数就是发送这个信号</td>
<td>只有当前进程收到信号，子进程不会收到。如果当前进程被kill了，那么它的子进程的父进程将会是init，也就是pid为1的进程</td>
</tr>
</tbody>
</table>
<p>下面这两个代码片段就能够验证这种情况(注意使用pcntl的时候，一定要declare ticks，要不然会杯具的发现函数没有被调用，进程不退出，信号发过去没有作用。php手册竟然没有强调这一点)：</p>
<p>文件：loadhelper.php</p>
<pre class="brush:php">
#为了pcntl能够截获信号
declare(ticks = 1);

$arr_processes = array();

function terminate($signo){
    echo "aaaaaaaaaaa\n";
}

pcntl_signal(SIGTERM, "terminate", true);
pcntl_signal(SIGINT, "terminate", true);

foreach($argv as $key =&gt; $operation){

    if(0 === $key){
        continue;
    }   

    $pipes = array();
    $process = proc_open($operation, array(), &amp;$pipes);
    if(false === $process){
        exit(-1);
    }
    $arr_processes[] = $process;
}

while(true){
    sleep(100);
}
</pre>
<p>文件：child.php</p>
<pre class="brush:php">
declare(ticks=1);

pcntl_signal(SIGINT, "terminate");
pcntl_signal(SIGTERM, "terminate");

function terminate($signo){
    echo "test_child\n";
}

while(true){
    sleep(100);
}
</pre>
<p>使用命令php loadhelper.php &#8220;php test.php&#8221;可以启动这个测试。<br />
1.输入ctrl+c发送sigint可以看到，父进程与子进程的terminate都得到了执行，都有输出，但父进程不会退出，因为子进程还没有退出<br />
2.通过kill向父进程的pid发送sigterm，可以看到，只有父进程输出</p>
<p>遗留问题：</p>
<p>父进程（loadhelper）接受到一次信号后，如果在terminate函数中调用exit，它还是不能退出的，因为还有子进程没有退出。但是从此以后它就不能再接收信号了（子进程还是能够接收到sigint），可能是exit使进程进入了待回收状态，具体还 需要后续在分析一把。</p>
本文永久链接:<a href="http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html">http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html' rel='bookmark' title='Permanent Link: 文件grep-选出两个文件中相同/不同的内容'>文件grep-选出两个文件中相同/不同的内容</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>php中getopt的缺陷及修复</title>
		<link>http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html</link>
		<comments>http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html#comments</comments>
		<pubDate>Mon, 17 May 2010 07:55:49 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96094</guid>
		<description><![CDATA[在这里，我不得不再一次感叹php语言库函数的山寨与不专业。getopt函数就是一个典型的例子，通常用的时候，大家可能觉得没有什么，但在某些情况 下，就真的让人很囧。一个简单的函数，稍微多花几分钟就弄得更好一些了，但这个语言有个随意的开端，就有个随意的实现啊。 在linux中，使用getopt时候，有两种情况： 1.取得的参数解析成字符串：“php test_arg.php -c abc”，这种情况c参数取得的结果就是abc这个字符串 2.取得的参数解析成数组：“php test_arg.php -c abc -c abc123”，这种情况c参数取得的结果就是包含abc与abc123的数组 但是遇到这种情况呢：“php test_arg.php -c abc*”？由于linux的shell已经帮程序做了输入参数的解析，这时候c参数得到的既不是abc*这个结果也不是一个数组，而是被shell展开成了很多文件名后的第一个。 可能getopt用的童鞋很少，但这种山寨的设计，实在太让人憋屈了，自己花个10分钟写一个就比它的要好，为了避免大家重复劳动，分享一个代码片段 function mygetopt(){ global $argv; $result = array(); $current_key = false; foreach($argv as $opt){ $matches = array(); if(1 === preg_match("/^-{1,2}(.*)$/", $opt, $matches)){ $current_key = $matches[1]; if(false === isset($result[$current_key])){ $result[$current_key] = false; } }else if (false !== $current_key){ if(false [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
<li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
<li><a href='http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html' rel='bookmark' title='Permanent Link: sigterm sigint sigkill 区别'>sigterm sigint sigkill 区别</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>在这里，我不得不再一次感叹php语言库函数的山寨与不专业。getopt函数就是一个典型的例子，通常用的时候，大家可能觉得没有什么，但在某些情况 下，就真的让人很囧。一个简单的函数，稍微多花几分钟就弄得更好一些了，但这个语言有个随意的开端，就有个随意的实现啊。</p>
<p>在linux中，使用getopt时候，有两种情况：</p>
<p>1.取得的参数解析成字符串：“php test_arg.php -c abc”，这种情况c参数取得的结果就是abc这个字符串</p>
<p>2.取得的参数解析成数组：“php test_arg.php -c abc -c abc123”，这种情况c参数取得的结果就是包含abc与abc123的数组</p>
<p>但是遇到这种情况呢：“php test_arg.php -c abc*”？由于linux的shell已经帮程序做了输入参数的解析，这时候c参数得到的既不是abc*这个结果也不是一个数组，而是被shell展开成了很多文件名后的第一个。</p>
<p>可能getopt用的童鞋很少，但这种山寨的设计，实在太让人憋屈了，自己花个10分钟写一个就比它的要好，为了避免大家重复劳动，分享一个代码片段</p>
<pre  class="brush:php">
   function mygetopt(){
        global $argv;
        $result = array();

        $current_key = false;
        foreach($argv as $opt){

            $matches = array();
            if(1 === preg_match("/^-{1,2}(.*)$/", $opt, $matches)){
                $current_key = $matches[1];

                if(false === isset($result[$current_key])){
                    $result[$current_key] = false;
                }
            }else if (false !== $current_key){

                if(false === $result[$current_key]){
                    $result[$current_key] = $opt;
                }else{
                    if(false === is_array($result[$current_key])){
                        $result[$current_key] = array($result[$current_key]);
                    }
                    $result[$current_key][] = $opt;
                }
            }
        }   

        return $result;
    }
</pre>
<p>为了方便使用，将新版本的getopt函数设置为不接受任何参数，但是解析的结果可以输出所有的参数内容。因为php官方的getopt函数使用后，也无非是对输出的数组进行foreach之后进行switch，还不如方便点，直接解析所有呢。除了这一点，这个getopt函数的输出结果与php官方的完全一致</p>
<p>php官方getopt函数参考文档：<a href="http://cn.php.net/manual/en/function.getopt.php" target="_blank">http://cn.php.net/manual/en/function.getopt.php</a></p>
本文永久链接:<a href="http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html">http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
<li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
<li><a href='http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html' rel='bookmark' title='Permanent Link: sigterm sigint sigkill 区别'>sigterm sigint sigkill 区别</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php中&amp;符号的滥用与它引发的bug</title>
		<link>http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html</link>
		<comments>http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html#comments</comments>
		<pubDate>Fri, 07 May 2010 10:46:36 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96090</guid>
		<description><![CDATA[php中，使用&#38;表明这个引用是指针，这样在两个引用可以指向同一个内存空间。但其实不使用&#38;的情况下，php也是写时拷贝的，zend引擎只有在修改的时候才会发生内存拷贝，不修改的话是不会产生消耗的。在实际使用中，我还发现使用&#38;符号反而性能会降低。 在不需要修改的情况下，建议尽量不要使用&#38;符号，否则不仅降低效率，还有可能造成出现bug。今天查看最近对测试框架的升级，就踩上了simpletest上面的一个bug，请看simpletest中，想testsuit加上case的函数： function addTestCase(&#38;$test_case) { $this-&#62;_test_cases[] = &#38;$test_case; } 这么简单的函数，我想大家一般都会认为没有问题吧，正常情况下它都能很好的工作，但是如果你这样用，就bug了： foreach($arr_cases as $case){ $this-&#62;test_suit-&#62;addTestCaseOpenTest($case); } 你会发现_test_cases这个数组里面，只哟foreach最终的那个元素，因为函数都是接受的值引用，foreach改变$case的值，就把已经传入_test_cases数组的内容都给改写了，于是就悲剧了。对于simpletest来说，它并不需要修改用户的case程序，这样做值引用显然是多此一举，还产生了bug。 关于性能降低，用一个简单的代码测试一下就知道了 $a = array('a','c','n'); function printArray(&#38;$arr) { print(count($arr)); } for($i=0;$i&#60;100000;$i++){ printArray($a); } 用time命令跑一次，把printArray的&#38;符号去掉再跑一次，可以看到大致下面的结果（机器不同，结果不同啊） 带有&#38;符号 不带有&#38;符号 real    0m0.183s user    0m0.130s sys     0m0.053s real    0m0.160s user    0m0.101s sys     0m0.060s 可见使用&#38;反而会使性能下降的，所以除非有必要，不建议使用&#38;符号 本文永久链接:http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html [发表评论] 您可能会喜欢:sql运行简单封装 php中getopt的缺陷及修复 php反射效果:基类访问子类数据


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>php中，使用&amp;表明这个引用是指针，这样在两个引用可以指向同一个内存空间。但其实不使用&amp;的情况下，php也是写时拷贝的，zend引擎只有在修改的时候才会发生内存拷贝，不修改的话是不会产生消耗的。在实际使用中，我还发现使用&amp;符号反而性能会降低。</p>
<p>在不需要修改的情况下，建议尽量不要使用&amp;符号，否则不仅降低效率，还有可能造成出现bug。今天查看最近对测试框架的升级，就踩上了simpletest上面的一个bug，请看simpletest中，想testsuit加上case的函数：</p>
<pre class="brush:php">function addTestCase(&amp;$test_case) {
     $this-&gt;_test_cases[] = &amp;$test_case;
}</pre>
<p>这么简单的函数，我想大家一般都会认为没有问题吧，正常情况下它都能很好的工作，但是如果你这样用，就bug了：</p>
<pre class="brush:php">foreach($arr_cases as $case){
     $this-&gt;test_suit-&gt;addTestCaseOpenTest($case);
}</pre>
<p>你会发现_test_cases这个数组里面，只哟foreach最终的那个元素，因为函数都是接受的值引用，<strong>foreach改变$case的值，就把已经传入_test_cases数组的内容都给改写了</strong>，于是就悲剧了。对于simpletest来说，它并不需要修改用户的case程序，这样做值引用显然是多此一举，还产生了bug。</p>
<p>关于性能降低，用一个简单的代码测试一下就知道了</p>
<pre class="brush:php">
$a = array('a','c','n'); 

function printArray(&amp;$arr)
{
    print(count($arr));
}

for($i=0;$i&lt;100000;$i++){
    printArray($a);
}</pre>
<p>用time命令跑一次，把printArray的&amp;符号去掉再跑一次，可以看到大致下面的结果（机器不同，结果不同啊）</p>
<table border="0">
<tbody>
<tr>
<td>带有&amp;符号</td>
<td>不带有&amp;符号</td>
</tr>
<tr>
<td>real    0m0.183s<br />
user    0m0.130s<br />
sys     0m0.053s</td>
<td>real    0m0.160s<br />
user    0m0.101s<br />
sys     0m0.060s</td>
</tr>
</tbody>
</table>
<p>可见使用&amp;反而会使性能下降的，所以除非有必要，不建议使用&amp;符号</p>
本文永久链接:<a href="http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html">http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>paxos算法解决单点问题与资源定位</title>
		<link>http://www.mirecle.com/2010/04/29/paxos-algorithm-to-solve-the-problem-and-the-resources-to-locate-a-single-point.html</link>
		<comments>http://www.mirecle.com/2010/04/29/paxos-algorithm-to-solve-the-problem-and-the-resources-to-locate-a-single-point.html#comments</comments>
		<pubDate>Thu, 29 Apr 2010 05:36:15 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96083</guid>
		<description><![CDATA[今天早茶的topic。介绍了paxos算法与zookeeper相关的内容，可以解决单点问题觉得还挺实用的。这个算法由三个不同类型的实体，通过投票的方式决策出一个值传播到网络中，实现分布式数据的统一，使各个节点不会各自为政。 paxos是一种比较主流的算法，google与微软的集群都用这个，具体参与进来的有三个实体： 1.提议者：提议者发起新的提议，比如设置某个值。每个提议都有个编号。提议者根据参与者的反馈，多数参与者赞同的提议就获得通过。 2.参与者：参与者对提议者的提议进行投票，将投票结果反馈给提议者。当有多个提议时，参与者倾向于接受编号大的提议。例如已经接受编号n的，此时收到了编号为n-1的提议，就会拒绝 3.接受者：接受提议者与参与者的决策（获得投票通过的提议）。 一个典型的也是最简单的流程： Client Proposer Acceptor Learner &#124; &#124; &#124; &#124; &#124; &#124; &#124; X--------&#62;&#124; &#124; &#124; &#124; &#124; &#124; Request &#124; X---------&#62;&#124;-&#62;&#124;-&#62;&#124; &#124; &#124; Prepare(N) &#124; &#124;&#60;---------X--X--X &#124; &#124; Promise(N,{Va,Vb,Vc}) &#124; X---------&#62;&#124;-&#62;&#124;-&#62;&#124; &#124; &#124; Accept!(N,Vn) &#124; &#124;&#60;---------X--X--X------&#62;&#124;-&#62;&#124; Accepted(N,Vn) &#124;&#60;---------------------------------X--X Response &#124; &#124; &#124; &#124; &#124; &#124; &#124; 如图，为了简单理解，可以认为proposer与acceptor是相同功能server构成的一个集群，client可以认为是一个外部的用户，发送一个请求到集群后，集群中的一个server扮演提议者角色发起一个提议，后面的三个accepto进行投票，投票反馈给提议者后发现获得通过，acceptor将信息扩散给接受者。这样整个集群中就针对这个提议达成了一致。 根据这个算法，接受者收到的信息是顺序的，不会产生乱序的问题。所以对于需要序列化的服务，就可以使用这种方式将单点整成多点，避免运维风险。 还有一些更复杂情况以及一个极端情况请见参考资料吧，另外： 1.集群中有多少个节点，首先就是各个节点就是要知道的。集群中要想增加一个新的节点比较麻烦 [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2009/10/13/mysql-study-notes-1.html' rel='bookmark' title='Permanent Link: mysql学习笔记-1'>mysql学习笔记-1</a></li>
<li><a href='http://www.mirecle.com/2009/09/04/apple-store-model.html' rel='bookmark' title='Permanent Link: apple商店模式？'>apple商店模式？</a></li>
<li><a href='http://www.mirecle.com/2009/07/15/i-have-the-vision-of-automated-testing-framework.html' rel='bookmark' title='Permanent Link: 我对自动化测试框架的愿景'>我对自动化测试框架的愿景</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>今天早茶的topic。介绍了paxos算法与zookeeper相关的内容，可以解决单点问题觉得还挺实用的。这个算法由三个不同类型的实体，通过投票的方式决策出一个值传播到网络中，实现分布式数据的统一，使各个节点不会各自为政。</p>
<p>paxos是一种比较主流的算法，google与微软的集群都用这个，具体参与进来的有三个实体：</p>
<p>1.提议者：提议者发起新的提议，比如设置某个值。每个提议都有个编号。提议者根据参与者的反馈，多数参与者赞同的提议就获得通过。</p>
<p>2.参与者：参与者对提议者的提议进行投票，将投票结果反馈给提议者。当有多个提议时，参与者倾向于接受编号大的提议。例如已经接受编号n的，此时收到了编号为n-1的提议，就会拒绝</p>
<p>3.接受者：接受提议者与参与者的决策（获得投票通过的提议）。</p>
<p>一个典型的也是最简单的流程：</p>
<pre>
 Client   Proposer      Acceptor     Learner
   |         |          |  |  |       |  |
   X--------&gt;|          |  |  |       |  |  Request
   |         X---------&gt;|-&gt;|-&gt;|       |  |  Prepare(N)
   |         |&lt;---------X--X--X       |  |  Promise(N,{Va,Vb,Vc})
   |         X---------&gt;|-&gt;|-&gt;|       |  |  Accept!(N,Vn)
   |         |&lt;---------X--X--X------&gt;|-&gt;|  Accepted(N,Vn)
   |&lt;---------------------------------X--X  Response
   |         |          |  |  |       |  |
</pre>
<p>如图，为了简单理解，可以认为proposer与acceptor是相同功能server构成的一个集群，client可以认为是一个外部的用户，发送一个请求到集群后，集群中的一个server扮演提议者角色发起一个提议，后面的三个accepto进行投票，投票反馈给提议者后发现获得通过，acceptor将信息扩散给接受者。这样整个集群中就针对这个提议达成了一致。</p>
<p>根据这个算法，接受者收到的信息是顺序的，不会产生乱序的问题。所以对于需要序列化的服务，就可以使用这种方式将单点整成多点，避免运维风险。</p>
<p>还有一些更复杂情况以及一个极端情况请见参考资料吧，另外：</p>
<p>1.集群中有多少个节点，首先就是各个节点就是要知道的。集群中要想增加一个新的节点比较麻烦</p>
<p>2.当集群中有效的节点数是少数时，算法会失效</p>
<p>zookeeper是用来协调分布式应用的，用于维护资源信息，它的关键算法就是用的paxos来做的。当然，在其上也有一些更复杂的内容。提供服务的节点作为client链接到zookeeper上面，与zookeeper保持心跳。当client宕机，zookeeper中的一个服务节点发现后就会通过投票流程来判定这个client挂掉了，其它依赖于这个client的服务作为算法中的接受者，收到挂掉的信息后，将依赖改到其它的client上面去。当然，也存在client断开zookeeper中的一个节点后连到zookeeper的另外一个节点，但因为算法保证了发送给client断开与联通消息的顺序，也是可以满足需求的。</p>
<p>在我看来，zookeeper的最大作用是使资源配置服务器本身从单点变为多点，避免了单点运维的问题。对于paxos算法还是很不错的，对于需要将系统中需要将命令序列化，而又希望避免服务单点是一个非常有效的方法。</p>
<p>参考资料：<br />
1.<a href="http://en.wikipedia.org/wiki/Paxos_algorithm" target="_blank">Paxos algorithm</a><br />
2.<a href="http://hadoop.apache.org/zookeeper/" target="_blank">zookeeper</a></p>
本文永久链接:<a href="http://www.mirecle.com/2010/04/29/paxos-algorithm-to-solve-the-problem-and-the-resources-to-locate-a-single-point.html">http://www.mirecle.com/2010/04/29/paxos-algorithm-to-solve-the-problem-and-the-resources-to-locate-a-single-point.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/04/29/paxos-algorithm-to-solve-the-problem-and-the-resources-to-locate-a-single-point.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2009/10/13/mysql-study-notes-1.html' rel='bookmark' title='Permanent Link: mysql学习笔记-1'>mysql学习笔记-1</a></li>
<li><a href='http://www.mirecle.com/2009/09/04/apple-store-model.html' rel='bookmark' title='Permanent Link: apple商店模式？'>apple商店模式？</a></li>
<li><a href='http://www.mirecle.com/2009/07/15/i-have-the-vision-of-automated-testing-framework.html' rel='bookmark' title='Permanent Link: 我对自动化测试框架的愿景'>我对自动化测试框架的愿景</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/04/29/paxos-algorithm-to-solve-the-problem-and-the-resources-to-locate-a-single-point.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>利用语言的动态特性减少switch</title>
		<link>http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html</link>
		<comments>http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html#comments</comments>
		<pubDate>Wed, 21 Apr 2010 06:44:42 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96075</guid>
		<description><![CDATA[以前也曾写过这样的代码，但没有特殊注意过，今天大家讨论收银台的问题时候，再提起这样的设计，却感觉非常有效。 因为分支很多，使用switch-case几乎是不可避免的，而这对与代码的维护与理解却不是一件很好的事情，在增加分支的时候，也是一种比较郁闷的事情。利用语言的动态特性与模块化的设计，可以在一定程度上减轻这种问题。 class A{}; class B{}; $arr_actions = array( 'a' => 'A', 'b' => 'B', ); function do_action_no_switch($action){ global $arr_actions; if(!array_key_exists($action, $arr_actions)){ return false; } $job = new $arr_actions[$action]; //job->do... } do_action_no_switch('a'); 本文永久链接:http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html [发表评论] 您可能会喜欢:更换域名为www.mirecle.com 成都九寨归来 地震


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2009/11/05/replacement-of-the-domain-name-www-mirecle-com.html' rel='bookmark' title='Permanent Link: 更换域名为www.mirecle.com'>更换域名为www.mirecle.com</a></li>
<li><a href='http://www.mirecle.com/2010/06/22/chengdu-jiuzhaigou-return.html' rel='bookmark' title='Permanent Link: 成都九寨归来'>成都九寨归来</a></li>
<li><a href='http://www.mirecle.com/2010/03/03/earthquake.html' rel='bookmark' title='Permanent Link: 地震'>地震</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>以前也曾写过这样的代码，但没有特殊注意过，今天大家讨论收银台的问题时候，再提起这样的设计，却感觉非常有效。</p>
<p>因为分支很多，使用switch-case几乎是不可避免的，而这对与代码的维护与理解却不是一件很好的事情，在增加分支的时候，也是一种比较郁闷的事情。利用语言的动态特性与模块化的设计，可以在一定程度上减轻这种问题。</p>
<pre class="brush:php">
class A{};
class B{};

$arr_actions = array(
    'a' => 'A',
    'b' => 'B',
);

function do_action_no_switch($action){

    global $arr_actions;

    if(!array_key_exists($action, $arr_actions)){
        return false;
    }   

    $job = new $arr_actions[$action];

    //job->do...
}

do_action_no_switch('a');
</pre>
本文永久链接:<a href="http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html">http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2009/11/05/replacement-of-the-domain-name-www-mirecle-com.html' rel='bookmark' title='Permanent Link: 更换域名为www.mirecle.com'>更换域名为www.mirecle.com</a></li>
<li><a href='http://www.mirecle.com/2010/06/22/chengdu-jiuzhaigou-return.html' rel='bookmark' title='Permanent Link: 成都九寨归来'>成都九寨归来</a></li>
<li><a href='http://www.mirecle.com/2010/03/03/earthquake.html' rel='bookmark' title='Permanent Link: 地震'>地震</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/04/21/reduce-the-use-of-the-dynamic-nature-of-language-switch.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php中set names与mysql_set_charset</title>
		<link>http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html</link>
		<comments>http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html#comments</comments>
		<pubDate>Tue, 13 Apr 2010 03:18:52 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96072</guid>
		<description><![CDATA[今天看到大家在讨论，发现这是个很严重而又容易疏忽的问题，我以前也一直是用set names，遂记录下来，也提醒自己一把。 1.set names与mysql_set_charset有什么区别？ 一般情况下, 使用”SET NAMES”就足够了, 也是可以保证正确的. 那么为什么手册又要说推荐使用 mysqli_set_charset(PHP&#62;=5.0.5)呢。手册里面也没有明确说明。我们可以看下php扩展的源代码： //php-5.2.11-SRC/ext/mysqli/mysqli_nonapi.c line 342 PHP_FUNCTION(mysqli_set_charset) { MY_MYSQL *mysql; zval *mysql_link; char *cs_name = NULL; unsigned int len; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis() , "Os", &#38;mysql_link, mysqli_link_class_entry, &#38;cs_name, &#38;len) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &#38;mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); if (mysql_set_character_set(mysql-&#62;mysql, cs_name)) { //** 调用libmysql的对应函数 RETURN_FALSE; } RETURN_TRUE; } 可以看到php的mysql扩展是直接调用了mysql的mysql_set_character_set函数，接下来看看mysql的代码 //mysql-5.1.30-SRC/libmysql/client.c, line [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html' rel='bookmark' title='Permanent Link: php中&#038;符号的滥用与它引发的bug'>php中&#038;符号的滥用与它引发的bug</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>今天看到大家在讨论，发现这是个很严重而又容易疏忽的问题，我以前也一直是用set names，遂记录下来，也提醒自己一把。</p>
<p>1.set names与mysql_set_charset有什么区别？</p>
<p>一般情况下, 使用”SET NAMES”就足够了, 也是可以保证正确的. 那么为什么手册又要说推荐使用 mysqli_set_charset(PHP&gt;=5.0.5)呢。手册里面也没有明确说明。我们可以看下php扩展的源代码：</p>
<pre class="brush:php">
//php-5.2.11-SRC/ext/mysqli/mysqli_nonapi.c line 342
PHP_FUNCTION(mysqli_set_charset)
{
    MY_MYSQL            *mysql;
    zval                *mysql_link;
    char                *cs_name = NULL;
    unsigned int        len;
    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis()
                , "Os", &amp;mysql_link, mysqli_link_class_entry, &amp;cs_name, &amp;len) == FAILURE) {
        return;
    }
    MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &amp;mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
    if (mysql_set_character_set(mysql-&gt;mysql, cs_name)) {
                //** 调用libmysql的对应函数
        RETURN_FALSE;
    }
    RETURN_TRUE;
}
</pre>
<p>可以看到php的mysql扩展是直接调用了mysql的mysql_set_character_set函数，接下来看看mysql的代码</p>
<pre class="brush:c">//mysql-5.1.30-SRC/libmysql/client.c, line 3166:
int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
{
  struct charset_info_st *cs;
  const char *save_csdir= charsets_dir;
  if (mysql-&gt;options.charset_dir)
    charsets_dir= mysql-&gt;options.charset_dir;
  if (strlen(cs_name) &lt; MY_CS_NAME_SIZE &amp;&amp;
     (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
  {
    char buff[MY_CS_NAME_SIZE + 10];
    charsets_dir= save_csdir;
    /* Skip execution of "SET NAMES" for pre-4.1 servers */
    if (mysql_get_server_version(mysql) &lt; 40100)       return 0;     sprintf(buff, "SET NAMES %s", cs_name);     if (!mysql_real_query(mysql, buff, strlen(buff)))     {       mysql-&gt;charset= cs;
    }
  }
  //以下省略
</pre>
<p>可以看到，除了调用real_query设置set names，还设置了mysql的charset变量。</p>
<p>2.这样有什么影响？</p>
<p>mysql_real_escape_string会受到影响，它与mysql_escape_string的区别就 是,  它会考虑”当前”字符集。如果仅仅使用set names，mysql_real_escape_string可能会失效。</p>
<p>例子：</p>
<pre class="brush:php">$mysqli = new mysqli("localhost", "user", "pass", "test", 3306);

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

$mysqli-&gt;query('SET NAMES gbk'); //使用set names设置字符集
$city = chr(0xbf).chr(0x5c); //0xbf5c是个有效的gbk字符，模拟用户输入
$city = $mysqli-&gt;real_escape_string ($city);//使用real_escape进行过滤

/* this query will fail, cause we didn't escape $city */
 if (!$mysqli-&gt;query("INSERT into myCity(name) VALUES ('$city')")) {
    print "INSERT into myCity (name) VALUES ('$city')\n";
    printf("Error: %s\n", $mysqli-&gt;error);
}

var_dump($city);

var_dump($mysqli-&gt;client_encoding());

$mysqli-&gt;close();
</pre>
<p>3.解决方案</p>
<p>mysqli_set_charset函数对PHP和Mysql有版本要求，必须当mysql版本大于5，PHP版本大于5.0.5时，此函数才有效。至于另一个mysql_set_charset函数，则更要求PHP版本大于5.2.3时才能有效。对于mysql4.1以上版本，使用&#8221;SET character_set_client=binary;&#8221;<br />
推荐使用mysql_set_charset设置字符集的方案，只有在环境不允许的情况下，我们才推荐使用第二种binary编码的方案。但是无论在什么情况下，都禁止使用”SET NAMES”来作为设置字符集的操作。</p>
本文永久链接:<a href="http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html">http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/01/18/php-reflection-effect-the-base-class-to-access-sub-categories-of-data.html' rel='bookmark' title='Permanent Link: php反射效果:基类访问子类数据'>php反射效果:基类访问子类数据</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/05/07/php-in-the-ampersand-on-the-abuse-of.html' rel='bookmark' title='Permanent Link: php中&#038;符号的滥用与它引发的bug'>php中&#038;符号的滥用与它引发的bug</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>文件grep-选出两个文件中相同/不同的内容</title>
		<link>http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html</link>
		<comments>http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html#comments</comments>
		<pubDate>Tue, 02 Feb 2010 03:04:35 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[软件]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96057</guid>
		<description><![CDATA[升级于2010-6-10，发现了一个bug，当时用notmatch模式时，如果文件2先eof将导致文件1中的内容没有输出 这个是最近做数据统计用的比较多的一个脚本，目的是根据key值，输出文件中相同或者不同的行。例如文件A的样子： 10000007^H_O 10000036^Hzerui 10000037^Hyanpeng_haha 文件B的样子： 10000037^Hyanpeng_haha 注意文件中的^H是一个字符，在vim中使用输入ctrl+v再输入ctrl+h就可以看到了，这里用它主要是起到文件不同列之间的分隔符作用 使用命令 php mygrep.php A B 可以得到“10000037^Hyanpeng_haha”这一行数据，使用命令 php mygrep.php A B &#8220;notmatch&#8221; 可以得到另外两行数据。 脚本默认使用第零列作为筛选依据，默认使用^H作为分隔符，在脚本中自己配置一下可以更改。脚本工作时，要求筛选依据是已排序的。对于排序，可以使用sort命令操作文件，sort通过-t参数指定分隔符，-f指定按照那一列进行排序。 mygrep.php的代码: $base_file_name = $argv[1]; $check_file_name = $argv[2]; $mode = isset($argv[3])?$argv[3]:false; $field_index = 0; $delimiter = ','; ////////////////////////////////////////////////////////////// $base_file = @fopen($base_file_name, 'r'); $check_file = @fopen($check_file_name, 'r'); $read_base_file = true; $compare_result = 0; $readed_base_file_arr = array(); [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html' rel='bookmark' title='Permanent Link: sigterm sigint sigkill 区别'>sigterm sigint sigkill 区别</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>升级于2010-6-10，发现了一个bug，当时用notmatch模式时，如果文件2先eof将导致文件1中的内容没有输出</p>
<p>这个是最近做数据统计用的比较多的一个脚本，目的是根据key值，输出文件中相同或者不同的行。例如文件A的样子：</p>
<blockquote><p>10000007^H_O<br />
10000036^Hzerui<br />
10000037^Hyanpeng_haha</p></blockquote>
<p>文件B的样子：</p>
<blockquote><p>10000037^Hyanpeng_haha</p></blockquote>
<p>注意文件中的^H是一个字符，在vim中使用输入ctrl+v再输入ctrl+h就可以看到了，这里用它主要是起到文件不同列之间的分隔符作用</p>
<p>使用命令</p>
<blockquote><p>php mygrep.php A B</p></blockquote>
<p>可以得到“10000037^Hyanpeng_haha”这一行数据，使用命令</p>
<blockquote><p>php mygrep.php A B &#8220;notmatch&#8221;</p></blockquote>
<p>可以得到另外两行数据。</p>
<p>脚本默认使用第零列作为筛选依据，默认使用^H作为分隔符，在脚本中自己配置一下可以更改。脚本工作时，要求筛选依据是已排序的。对于排序，可以使用sort命令操作文件，sort通过-t参数指定分隔符，-f指定按照那一列进行排序。</p>
<p>mygrep.php的代码:</p>
<pre class="brush: php">
$base_file_name    = $argv[1];
$check_file_name   = $argv[2];
$mode              = isset($argv[3])?$argv[3]:false;

$field_index = 0;
$delimiter = ',';

//////////////////////////////////////////////////////////////
$base_file = @fopen($base_file_name, 'r');
$check_file = @fopen($check_file_name, 'r');
$read_base_file = true;
$compare_result = 0;
$readed_base_file_arr = array();

//以要检查的文件作为外层循环
while(!feof($check_file)){
    //读取要检查的文件
    $readed_check_arr = explode($delimiter, trim(fgets($check_file)));
    do{
        //读取基准文件
        if($read_base_file === true){
            $readed_base_arr = explode($delimiter, trim(fgets($base_file)));
        }   

        //作比较
        $compare_result = strcmp($readed_check_arr[$field_index], $readed_base_arr[$field_index]);
        $grep_flag = ($compare_result == 0);
        //如果是要取出不相等的数据
        //且检查key小于或等于基准key时，说明需要将检查key下移一行,即此比较key已经比较完成
        //此时如果比较结果相等则不输出,
        //如果比较结果不等，并且检查key大于基准key则输出,如果检查结果小于基准key，说明检查key要下移继续检查
        if($mode !== false &amp;&amp; (strcmp($mode, "notmatch") == 0)
            &amp;&amp; $compare_result &gt;= 0){
            $grep_flag = !$grep_flag;
        }

        //print("comparing check=".$readed_check_arr[$field_index]." base=".$readed_base_arr[$field_index]." result=$compare_result
grep_flag=$grep_flag\n");

        if($grep_flag){
            print implode($delimiter, $readed_base_arr)."\n";
        }

        //总是设置为要读取，如果跳出循环，则由外面设置
        $read_base_file = true;

    //如果检查的key是大于基准的key，并且检查文件未到尾，则重新读取一行基准文件进行检查
    }while($compare_result &gt; 0 &amp;&amp; !feof($base_file));

    if(feof($base_file)){
        break;
    }

    //当检查key小于基准key时，不读取下个基准key,等于则是因为已经比较过，两个都需要读取
    if($compare_result &lt; 0){
        $read_base_file = false;
    }
}

//当check_file结束了但是base_file未结束
do{
    print implode($delimiter, $readed_base_arr)."\n";
    $readed_base_arr = explode($delimiter, trim(fgets($base_file)));
}while(!feof($base_file));

fclose($check_file);
fclose($base_file);
</pre>
本文永久链接:<a href="http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html">http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/05/20/sigterm-sigint-sigkill-difference.html' rel='bookmark' title='Permanent Link: sigterm sigint sigkill 区别'>sigterm sigint sigkill 区别</a></li>
<li><a href='http://www.mirecle.com/2010/05/17/php-and-repair-defects-in-the-getopt.html' rel='bookmark' title='Permanent Link: php中getopt的缺陷及修复'>php中getopt的缺陷及修复</a></li>
<li><a href='http://www.mirecle.com/2010/07/23/sql-to-run-a-simple-package.html' rel='bookmark' title='Permanent Link: sql运行简单封装'>sql运行简单封装</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/02/02/file-grep-select-two-files-same-different-content.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>java中String.split导致的内存泄露</title>
		<link>http://www.mirecle.com/2010/01/29/java-memory-leak-resulting-in-string-split.html</link>
		<comments>http://www.mirecle.com/2010/01/29/java-memory-leak-resulting-in-string-split.html#comments</comments>
		<pubDate>Fri, 29 Jan 2010 15:16:16 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96054</guid>
		<description><![CDATA[有的时候，由于我们队Java api理解上面的错误，可能会导致出现一些意外的问题，比如内存泄露。认为虚拟机会为你创建一个新的对象，引用了不同的内存区域，结果却和想象中的不一样，导致服务宕机。 今天在查网关的内存溢出问题时，发现问题出现在String.split函数上面。大家都认为Java中的String是只读的，new新对象的时候一定是分配了新的内存，但虚拟机内部却不一定如此。sun的hotspot1.5版本在实现java的类时做了优化，为了减少内存拷贝，一个String对象可能会引用另外一个String对象的内存。查看jdk的源代码可知，String内部是用一个名为value的char数组存储内容的，但同时另外也有两个int类型的变量：offset与count。 查看String.split()函数的源代码，随后调用的是Pattern.split()，随后调用String.subSequence()，随后调用String.substring()。String的substring代码如下 public String substring(int beginIndex, int endIndex) { if (beginIndex &#60; 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex &#62; count) { throw new StringIndexOutOfBoundsException(endIndex); } if (beginIndex &#62; endIndex) { throw new StringIndexOutOfBoundsException(endIndex - beginIndex); } return ((beginIndex == 0) &#38;&#38; (endIndex == count)) ? this : new String(offset + beginIndex, [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/06/01/the-number-of-charges-on-the-money.html' rel='bookmark' title='Permanent Link: 关于数钱费'>关于数钱费</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>有的时候，由于我们队Java api理解上面的错误，可能会导致出现一些意外的问题，比如内存泄露。认为虚拟机会为你创建一个新的对象，引用了不同的内存区域，结果却和想象中的不一样，导致服务宕机。</p>
<p>今天在查网关的内存溢出问题时，发现问题出现在String.split函数上面。大家都认为Java中的String是只读的，new新对象的时候一定是分配了新的内存，但虚拟机内部却不一定如此。sun的hotspot1.5版本在实现java的类时做了优化，为了减少内存拷贝，一个String对象可能会引用另外一个String对象的内存。查看jdk的源代码可知，String内部是用一个名为value的char数组存储内容的，但同时另外也有两个int类型的变量：offset与count。</p>
<p>查看String.split()函数的源代码，随后调用的是Pattern.split()，随后调用String.subSequence()，随后调用String.substring()。String的substring代码如下</p>
<pre class="brush:java">
public String substring(int beginIndex, int endIndex) {
if (beginIndex &lt; 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex &gt; count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex &gt; endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) &amp;&amp; (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
</pre>
<p>如果看到最后return的是new String，以为就是一个新的String就真的囧了，这不是一个向外开放的构造函数，它创建了一个新的对象，却是用的原来String对象中的内存</p>
<pre class="brush:java">
// Package private constructor which shares value array for speed.
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
</pre>
<p>本来这样进行优化无可厚非，但在网关的应用情况下就出现问题了：<br />
一次性查询得到一个String，里面记载了1000条数据结果，将这1000条数据结果拆分，封装成1000个对象，存在缓存里面。缓存是用LinkedHashMap，当Entry达到一定数量时就进行淘汰。这样就导致这1000个对象都淘汰了，才会释放存储了1000个数据的String，这个String可是相当的大啊。<br />
又因为查询的时间段是有重叠的，导致每次查询的String都记载了很多重复的内容，虽然缓存里面只对String不同的地方保持了一次引用，但是却无意间存储了大量的无用数据。这就导致了jvm的内存溢出。</p>
<p>好多年没搞java了，结合以前上学时候查java内存泄露的一点经验，说明了：</p>
<p>1.出现内存泄露，通常都是有容器保持了大量的引用，查问题的时候，可以从容器优先开始</p>
<p>2.查看jdk的源代码，是很有必要的。</p>
本文永久链接:<a href="http://www.mirecle.com/2010/01/29/java-memory-leak-resulting-in-string-split.html">http://www.mirecle.com/2010/01/29/java-memory-leak-resulting-in-string-split.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/01/29/java-memory-leak-resulting-in-string-split.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2010/06/01/the-number-of-charges-on-the-money.html' rel='bookmark' title='Permanent Link: 关于数钱费'>关于数钱费</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/01/29/java-memory-leak-resulting-in-string-split.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>linux的shell下文件批量改名</title>
		<link>http://www.mirecle.com/2010/01/27/batch-rename-files-in-shell.html</link>
		<comments>http://www.mirecle.com/2010/01/27/batch-rename-files-in-shell.html#comments</comments>
		<pubDate>Wed, 27 Jan 2010 08:21:29 +0000</pubDate>
		<dc:creator>闫鹏</dc:creator>
				<category><![CDATA[程序员]]></category>
		<category><![CDATA[软件]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.mirecle.com/?p=96052</guid>
		<description><![CDATA[以前写的一个小脚本，用在linux的shell批量修改大量文件名的情况下。昨天不小心删除了大量文件，找回的时候，又一次用到了它，在遇到大批量文件的时候，还是挺有效果的，共享一下。 用法： 1.将你要改名的文件都放在同一个文件夹下，运行&#8221;ls -l &#62; oldnames&#8221;，然后“vi oldnames”，这时候看到的大概是这个样子： total 1224 drwxrwxr-x   3 yanpeng yanpeng    4096 Sep 17 16:13 app drwxrwxr-x   2 yanpeng yanpeng    4096 May 19  2009 bin drwxrwxr-x   2 yanpeng yanpeng    8192 Jan 26 16:40 docpay 2.输入&#8221;ctrl+v&#8221;，移动光标，选中要删除的那一堆内容，其实就是文件名前面的那些列，输入“d”，得到的文件大概为 app bin docpay 3.删除掉第一行的空行，保存退出vi，然后&#8221;cp oldnames newnames&#8221;。 4.修改newnames文件中想要改名的文件为新文件名 5.将change_name.sh脚本放在你的那个放置文件的夹下，运行./change_name.sh就可以了(注意有执行权限，加执行权限的方法chmod a+x change_name.sh) change_name.sh脚本内容，拷贝下，存好就能用了 #!/bin/sh OLDNAMES='oldnames' NEWNAMES='newnames' fileline=`sed -n '$=' $OLDNAMES` [...]


您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2009/07/16/sub-level-management-tag-files.html' rel='bookmark' title='Permanent Link: 分层次管理tag文件'>分层次管理tag文件</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<!--adv-->
<img src="http://emoneycreater.appspot.com/jd.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/sn.jpg" width="0" height="0"/>
<img src="http://emoneycreater.appspot.com/img01.tianya.cn.dehm.jpg" width="0" height="0"/>
<!--adv end-->
<p>以前写的一个小脚本，用在linux的shell批量修改大量文件名的情况下。昨天不小心删除了大量文件，找回的时候，又一次用到了它，在遇到大批量文件的时候，还是挺有效果的，共享一下。</p>
<p><strong>用法：</strong></p>
<p>1.将你要改名的文件都放在同一个文件夹下，运行&#8221;ls -l &gt; oldnames&#8221;，然后“vi oldnames”，这时候看到的大概是这个样子：</p>
<pre name="code" class="text">
total 1224
drwxrwxr-x   3 yanpeng yanpeng    4096 Sep 17 16:13 app
drwxrwxr-x   2 yanpeng yanpeng    4096 May 19  2009 bin
drwxrwxr-x   2 yanpeng yanpeng    8192 Jan 26 16:40 docpay
</pre>
<p>2.输入&#8221;ctrl+v&#8221;，移动光标，选中要删除的那一堆内容，其实就是文件名前面的那些列，输入“d”，得到的文件大概为</p>
<pre name="code" class="text">
app
bin
docpay
</pre>
<p>3.删除掉第一行的空行，保存退出vi，然后&#8221;cp oldnames newnames&#8221;。</p>
<p>4.修改newnames文件中想要改名的文件为新文件名</p>
<p>5.将change_name.sh脚本放在你的那个放置文件的夹下，运行./change_name.sh就可以了(注意有执行权限，加执行权限的方法chmod a+x change_name.sh)</p>
<p>change_name.sh脚本内容，拷贝下，存好就能用了</p>
<pre class="bursh:bash">

#!/bin/sh

OLDNAMES='oldnames'
NEWNAMES='newnames'

fileline=`sed -n '$=' $OLDNAMES`
echo $fileline

index=1
while [ $index -le $fileline ]
do
oldname=`sed -n "${index}p" $OLDNAMES`
newname=`sed -n "${index}p" $NEWNAMES`
mv $oldname $newname
index=`expr $index + 1`
done
</pre>
本文永久链接:<a href="http://www.mirecle.com/2010/01/27/batch-rename-files-in-shell.html">http://www.mirecle.com/2010/01/27/batch-rename-files-in-shell.html</a>
<br/>
[<a href="http://www.mirecle.com/2010/01/27/batch-rename-files-in-shell.html#respond">发表评论</a>]

<p>您可能会喜欢:<ol><li><a href='http://www.mirecle.com/2009/07/16/sub-level-management-tag-files.html' rel='bookmark' title='Permanent Link: 分层次管理tag文件'>分层次管理tag文件</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.mirecle.com/2010/01/27/batch-rename-files-in-shell.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
