<?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>风雪之隅 &#187; MySQL/PostgreSQL</title>
	<atom:link href="http://www.laruence.com/category/mysqlpostgresql/feed" rel="self" type="application/rss+xml" />
	<link>http://www.laruence.com</link>
	<description>PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 - 左手代码 右手诗</description>
	<lastBuildDate>Wed, 08 Feb 2012 05:12:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>mysqlnd插件mysqlnd_ms的介绍</title>
		<link>http://www.laruence.com/2011/10/05/2192.html</link>
		<comments>http://www.laruence.com/2011/10/05/2192.html#comments</comments>
		<pubDate>Wed, 05 Oct 2011 12:06:37 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[fail over]]></category>
		<category><![CDATA[load balancing]]></category>
		<category><![CDATA[mysqlnd]]></category>
		<category><![CDATA[mysqlnd_ms]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[read-write splitting]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=2192</guid>
		<description><![CDATA[ 从PHP5.3开始, MySQL team专为PHP开发的MySQL连接库mysqlnd(MySQL native driver for PHP)终于和PHP一起发布了. mysqlnd的主要目的是为了解决长久以来mysql和php的license的问题.  它将作为PHP的源代码的一部分和PHP一起发布.

    今天, 我要为大家介绍一个mysqlnd的插件:mysqlnd_ms,  这个插件是由mysqlnd的开发者Andrey Hristov,<a href="http://blog.ulf-wendel.de/">Ulf Wendel</a>和<a href="http://schlueters.de/blog/">johannes</a>一起开发的, 目前发布在PECL: <a href="http://pecl.php.net/package/mysqlnd_ms">mysqlnd_ms</a>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/10/05/2192.html"  title="Permanet Link to mysqlnd插件mysqlnd_ms的介绍" >http://www.laruence.com/2011/10/05/2192.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    从PHP5.3开始, MySQL team专为PHP开发的MySQL连接库mysqlnd(MySQL native driver for PHP)终于和PHP一起发布了. mysqlnd的主要目的是为了解决长久以来mysql和php的license的问题.  它将作为PHP的源代码的一部分和PHP一起发布.</p>
<p>    今天, 我要为大家介绍一个mysqlnd的插件:mysqlnd_ms,  这个插件是由mysqlnd的开发者Andrey Hristov,<a href="http://blog.ulf-wendel.de/" >Ulf Wendel</a>和<a href="http://schlueters.de/blog/" >johannes</a>一起开发的, 目前发布在PECL: <a href="http://pecl.php.net/package/mysqlnd_ms" >mysqlnd_ms</a></p>
<p>    在这个扩展的介绍页面我们可以看到它的功能描述:</p>
<blockquote><p>
The replication and load balancing plugin is a plugin for the mysqlnd library. It can be used with PHP MySQL extensions (ext/mysql, ext/mysqli, PDO_MySQL). if they are compiled to use mysqlnd. The plugin inspects queries to do read-write splitting. Read-only queries are send to configured MySQL replication slave servers all other queries are redirected to the MySQL replication master server. Very little, if any, application changes required, dependent on the usage scenario required.
</p></blockquote>
<p>    这个扩展, 主要实现了, 连接保持和切换, 负载均衡和读写分离等, 也就是说, 这个扩展会去分别PHP发给MySQL的query,  如果是&#8221;读&#8221;的query, 就会把query发送给从库(配置中指明), 并且支持负载均衡;  而如果是&#8221;写&#8221;的query,  就会把query发送给主库.</p>
<p>    不过这个扩展需要搭配mysqlnd一起使用(从PHP5.4 beta1开始, 我们已经把mysqlnd作为mysql, mysqli, pdo的默认链接目标, 当然, 你也可以通过&#8211;with-mysql=***来制定你想要链接到libmysql).</p>
<p>    这个扩展使用的方法也很简单, 首先在<b>php.ini</b>中定义配置:</p>
<pre name="code"  class="sh_ini"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
mysqlnd_ms.enable=1
mysqlnd_ms.ini_file=/path/to/mysqlnd_ms_plugin.ini
</pre>
<p>    之后, 在你指明的mysqlnd_ms_plugin.ini中配置好MySQL的主从库就好了:</p>
<pre name="code"  class="sh_ini"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
[myapp]
master[]=localhost:/tmp/mysql.sock
slave[]=192.168.2.27:3306
</pre>
<p>   <b>博文发出以后, Ulf提醒我, 从1.1.0开始, 配置文件改为JSON格式:</b></p>
<blockquote><p>
Ulf_Wendel: @laruence >Thx for the blog. Please note, mysqlnd_ms config format was changed in 1.1.0. Now JSON based
</p></blockquote>
<p>   所以新的配置应该类似于如下格式:</p>
<pre name="code"  class="sh_json"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
{
    &quot;myapp&quot;: {
        &quot;master&quot;: {
            &quot;master_0&quot;: {
                &quot;host&quot;: &quot;localhost&quot;,
                &quot;socket&quot;: &quot;\/tmp\/mysql.sock&quot;
            }
        },
        &quot;slave&quot;: {
            &quot;slave_0&quot;: {
                &quot;host&quot;: &quot;192.168.2.27&quot;,
                &quot;port&quot;: &quot;3306&quot;
            }
        }
    }
}
</pre>
<p>   链接方式修改如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
/* Load balanced following &quot;myapp&quot; section rules from the plugins config file */
$mysqli = new mysqli(&quot;myapp&quot;, &quot;username&quot;, &quot;password&quot;, &quot;database&quot;);
$pdo = new PDO('mysql:host=myapp;dbname=database', 'username', 'password');
$mysql = mysql_connect(&quot;myapp&quot;, &quot;username&quot;, &quot;password&quot;);
?&gt;
</pre>
<p>   然后就和你之前一样的来开发了. </p>
<p>   如果希望获得更多信息, 可以参看: <a href="http://php.net/mysqlnd_ms" >http://php.net/mysqlnd_ms</a><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_ini.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_ini.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_json.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/06</a>, 风起 writes: 不错, 读写分离这点很需要</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/07</a>, <a href="http://baloyou.gotoip55.com/archives/433"  rel="external nofollow"  class="url" >mysqlnd插件mysqlnd_ms的介绍 | 风雪之隅 - 候鸟的博客</a> writes: [...] 通过mysqlnd插件mysqlnd_ms的介绍 | 风雪之隅.      wordpress 源码解读 (1) [...]</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/09</a>, <a href="http://xiaobin.net"  rel="external nofollow"  class="url" >Robin</a> writes: 请问鸟哥有在生产环境使用么？

一直在关注mysqlnd_ms，不过发现从统计数据来看（iva http://url.cn/0DdMJr）下载的人并不多，不太敢贸然使用。

另外也关注mysql proxy，但是问题好像也不少(via http://url.cn/1r9DR5)</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/10/10</a>, <a href="http://www.6pima.cn"  rel="external nofollow"  class="url" >中山网站建设</a> writes: 不错哟，学习一下</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/11/19</a>, 深空 writes: 不知道能否很好识别事务</li><li><a href="http://www.laruence.com/2011/10/05/2192.html" >2011/11/25</a>, <a href="http://www.cnxct.com/some-errors-on-compile-php-5-3-8-with-pdo_mysql-and-mysqlnd/"  rel="external nofollow"  class="url" >php5.3.8中编译pdo_mysql的艰难历程 | CNXCT小组的博客</a> writes: [...] 这里是将pdo_mysql作为一个拓展引入使用的。在php5.3中，PHP开发组把mysqlnd作为默认的连接MYSQL的数据库驱动来使用，据官方描述，节省内存40%，速度更快，当然或许是为了解决许可协议的问题。详情见：mysqlnd插件mysqlnd_ms的介绍。 两种方法都可以，运维同事都尝试了，由于时间关系，他们没做过多的尝试研究，就转向更紧急的项目了。 [...]</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/09/20/523.html"  rel="bookmark"  title="Permanent Link: PHP5.3 α2初体验" >PHP5.3 α2初体验</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/08/2528.html"  title="PHP-5.3.9远程执行任意代码漏洞(CVE-2012-0830)" >PHP-5.3.9远程执行任意代码漏洞(CVE-2012-0830)</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/10/05/2192.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>为MySQL设置查询超时</title>
		<link>http://www.laruence.com/2011/04/27/1995.html</link>
		<comments>http://www.laruence.com/2011/04/27/1995.html#comments</comments>
		<pubDate>Wed, 27 Apr 2011 09:12:20 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[MYSQL_OPT_READ_TIMEOUT]]></category>
		<category><![CDATA[query timeout]]></category>
		<category><![CDATA[query超时]]></category>
		<category><![CDATA[read timeout]]></category>
		<category><![CDATA[查询超时]]></category>
		<category><![CDATA[读超时]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1995</guid>
		<description><![CDATA[<p>
     昨天有人在群里问,  MySQL是否可以设置读写超时(非连接超时),  如果可以就可以避免一条SQL执行过慢, 导致PHP超时错误. 这个, 其实可以有.  只不过稍微要麻烦点.
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2011/04/27/1995.html"  title="Permanet Link to 为MySQL设置查询超时" >http://www.laruence.com/2011/04/27/1995.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
     昨天有人在群里问,  MySQL是否可以设置读写超时(非连接超时),  如果可以就可以避免一条SQL执行过慢, 导致PHP超时错误. 这个, 其实可以有.  只不过稍微要麻烦点.
</p>
<p>
     首先, 在libmysql中, 是提供了MYSQL_OPT_READ_TIMEOUT设置项的, 并且libmysql中提供了设置相关设置项的API, mysql_options:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
int STDCALL
mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
{
  DBUG_ENTER(&quot;mysql_option&quot;);
  DBUG_PRINT(&quot;enter&quot;,(&quot;option: %d&quot;,(int) option));
  switch (option) {
  case MYSQL_OPT_CONNECT_TIMEOUT:
    mysql-&gt;options.connect_timeout= *(uint*) arg;
    break;
  /** 读超时时间 */
  case MYSQL_OPT_READ_TIMEOUT:
    mysql-&gt;options.read_timeout= *(uint*) arg;
    break;
  case MYSQL_OPT_WRITE_TIMEOUT:
    mysql-&gt;options.write_timeout= *(uint*) arg;
    break;
  case MYSQL_OPT_COMPRESS:
    mysql-&gt;options.compress= 1; 

   /* 以下省略 */
</pre>
<p>     但是, 可惜的是,  目前只有mysqli扩展, 把mysql_options完全暴露给了PHP:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
PHP_FUNCTION(mysqli_options)
{
 /** 有省略 */
     switch (Z_TYPE_PP(mysql_value)) {
        /** 没有任何限制, 直接传递给mysql_options */
        case IS_STRING:
            ret = mysql_options(mysql-&gt;mysql, mysql_option, Z_STRVAL_PP(mysql_value));
            break;
        default:
            convert_to_long_ex(mysql_value);
            l_value = Z_LVAL_PP(mysql_value);
            ret = mysql_options(mysql-&gt;mysql, mysql_option, (char *)&amp;l_value);
            break;
    }

    RETURN_BOOL(!ret);
}
</pre>
<p>     但是因为Mysqli并没有导出这个常量, 所以我们需要通过查看MySQL的代码, 得到MYSQL_OPT_READ_TIMEOUT的实际值, 然后直接调用mysql_options:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
enum mysql_option
{
  MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE,
  MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP,
  MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, MYSQL_OPT_LOCAL_INFILE,
  MYSQL_OPT_PROTOCOL, MYSQL_SHARED_MEMORY_BASE_NAME, MYSQL_OPT_READ_TIMEOUT,
  MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
  MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
  MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
  MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
  MYSQL_OPT_SSL_VERIFY_SERVER_CERT
};
</pre>
<p>   可以看到,  MYSQL_OPT_READ_TIMEOUT为11.</p>
<p>   现在, 我们就可以设置查询超时了:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$mysqli = mysqli_init();
$mysqli-&gt;options(11 /*MYSQL_OPT_READ_TIMEOUT*/, 1);
$mysql-&gt;real_connect(***);
</pre>
<p>   不过, 因为在libmysql中有重试机制(尝试一次, 重试俩次),  所以, 最终我们设置的超时阈值都会三倍于我们设置的值.</p>
<p>   也就是说, 如果我们设置了MYSQL_OPT_READ_TIMEOUT为1,  最终会在3s以后超时结束.   也就是说, 我们目前能设置的最短超时时, 就是3秒&#8230;</p>
<p>   虽说大了点,, 不过总比没有好, 呵呵</p>
<p>   PS: 写了一半的时候, 就发现小黑已经写过一篇了,  所以大家也可以参看这篇<a href="http://blog.csdn.net/heiyeshuwu/archive/2010/09/08/5869813.aspx" >PHP访问MySQL查询超时处理</a><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/04/27/1995.html" >2011/04/27</a>, <a href="http://www.hencuo.com"  rel="external nofollow"  class="url" >半醒</a> writes: 求QQ群号啊</li><li><a href="http://www.laruence.com/2011/04/27/1995.html" >2011/04/28</a>, rwl writes: 好东西.</li><li><a href="http://www.laruence.com/2011/04/27/1995.html" >2011/08/24</a>, tsgx writes: 设置下mysql数据库的session变量就可以了。</li><li><a href="http://www.laruence.com/2011/04/27/1995.html" >2011/10/11</a>, Rocky writes: hi,请假一个问题：
zend dubugger的调试问题，从浏览器启动调试后大约50秒如果这次调试没有完成，apache就会报错，0x007cxxx 不能为read，请问大致是什么原因？</li><li><a href="http://www.laruence.com/2011/04/27/1995.html" >2011/10/13</a>, <a href="http://blog.chedushi.com/archives/454"  rel="external nofollow"  class="url" >为MySQL设置查询超时 | 岭南六少 - 一朵在LAMP架构下挣扎的云</a> writes: [...] 本文地址: http://www.laruence.com/2011/04/27/1995.html [...]</li><li><a href="http://www.laruence.com/2011/04/27/1995.html" >2011/11/01</a>, gan writes: 哎，一直期待PHP有这个功能，这个功能应该引用到PDO里面去，我现在的办法是通过后台进程定时5秒去杀超时的进程，希望鸟儿能给PHP核心组反映，3KS</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/04/12/1396.html"  title="深入理解SET NAMES和mysql(i)_set_charset的区别" >深入理解SET NAMES和mysql(i)_set_charset的区别</a></li><li><a href="http://www.laruence.com/2008/11/11/610.html"  title="统一信息存储平台(ISP)" >统一信息存储平台(ISP)</a></li><li><a href="http://www.laruence.com/2008/01/05/12.html"  title="深入Mysql字符集设置" >深入Mysql字符集设置</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2011/04/27/1995.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>深入理解SET NAMES和mysql(i)_set_charset的区别</title>
		<link>http://www.laruence.com/2010/04/12/1396.html</link>
		<comments>http://www.laruence.com/2010/04/12/1396.html#comments</comments>
		<pubDate>Mon, 12 Apr 2010 14:10:27 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[mysqli:set_charset]]></category>
		<category><![CDATA[mysqli_set_charset]]></category>
		<category><![CDATA[mysql_set_charset]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[set names]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1396</guid>
		<description><![CDATA[最近公司组织了个PHP安全编程的培训, 其中涉及到一部分关于Mysql的"SET NAMES"和mysql_set_charset (mysqli_set_charset)的内容:
  
  说到, 尽量使用mysqli_set_charset而不是"SET NAMES", 当然, 这个内容在PHP手册中也有叙及, 但是却没有解释为什么.

  最近有好几个朋友问我这个问题, 到底为什么?

  问的人多了, 我也就觉得可以写篇blog, 专门介绍下这部分的内容了.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/04/12/1396.html"  title="Permanet Link to 深入理解SET NAMES和mysql(i)_set_charset的区别" >http://www.laruence.com/2010/04/12/1396.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
  最近公司组织了个PHP安全编程的培训, 其中涉及到一部分关于Mysql的&#8221;SET NAMES&#8221;和mysql_set_charset (mysqli_set_charset)的内容:</p>
<p>  说到, 尽量使用mysqli_set_charset(mysqli:set_charset)而不是&#8221;SET NAMES&#8221;, 当然, 这个内容在PHP手册中也有叙及, 但是却没有解释为什么.</p>
<p>  最近有好几个朋友问我这个问题, 到底为什么?</p>
<p>  问的人多了, 我也就觉得可以写篇blog, 专门介绍下这部分的内容了.</p>
<p>  首先, 很多人都不知道&#8221;SET NAMES&#8221;到底是做了什么,</p>
<p>  我之前的文章<a href="http://www.laruence.com/2008/01/05/12.html" >深入MySQL字符集设置</a>中, 曾经介绍过character_set_client/character_set_connection/character_set_results这三个MySQL的&#8221;环境变量&#8221;,  这里再简单介绍下,</p>
<p>  这三个变量, 分别告诉MySQL服务器, 客户端的编码集, 在传输给MySQL服务器的时候的编码集, 以及期望MySQL返回的结果的编码集.</p>
<p>  比如, 通过使用&#8221;SET NAMES utf8&#8243;, 就告诉服务器, 我用的是utf-8编码, 我希望你也给我返回utf-8编码的查询结果.</p>
<p>  一般情况下, 使用&#8221;SET NAMES&#8221;就足够了, 也是可以保证正确的. 那么为什么手册又要说推荐使用mysqli_set_charset(PHP>=5.0.5)呢?</p>
<p>  首先, 我们看看mysqli_set_charset到底做了什么(注意星号注释处, mysql_set_charset类似):</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//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()
		, &quot;Os&quot;, &amp;mysql_link, mysqli_link_class_entry, &amp;cs_name, &amp;len) == FAILURE) {
        return;
    }
    MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &amp;mysql_link, &quot;mysqli_link&quot;
        , MYSQLI_STATUS_VALID);

    if (mysql_set_character_set(mysql-&gt;mysql, cs_name)) {
		//** 调用libmysql的对应函数
        RETURN_FALSE;
    }
    RETURN_TRUE;
}
</pre>
<p>  那mysql_set_character_set又做了什么呢?</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//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 &quot;SET NAMES&quot; for pre-4.1 servers */
    if (mysql_get_server_version(mysql) &lt; 40100)
      return 0;
    sprintf(buff, &quot;SET NAMES %s&quot;, cs_name);
    if (!mysql_real_query(mysql, buff, strlen(buff)))
    {
      mysql-&gt;charset= cs;
    }
  }
  //以下省略
</pre>
<p>  我们可以看到, mysqli_set_charset除了做了&#8221;SET NAMES&#8221;以外, 还多做了一步:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
sprintf(buff, &quot;SET NAMES %s&quot;, cs_name);
if (!mysql_real_query(mysql, buff, strlen(buff)))
{
  mysql-&gt;charset= cs;
}
</pre>
<p>  而对于mysql这个核心结构的成员charset又有什么作用呢?</p>
<p>  这就要说说mysql_real_escape_string()了, 这个函数和mysql_escape_string的区别就是, 它会考虑&#8221;当前&#8221;字符集. 那么这个当前字符集从哪里来呢?</p>
<p>  对了, 你猜的没错, 就是mysql->charset.</p>
<p>  mysql_real_string在判断宽字符集的字符的时候, 就根据这个成员变量来分别采用不同的策略, 比如如果是utf-8, 那么就会采用libmysql/ctype-utf8.c.</p>
<p>  看个实例, 默认mysql连接字符集是latin-1, (经典的5c问题):</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
    $db = mysql_connect('localhost:3737', 'root' ,'123456');
    mysql_select_db(&quot;test&quot;);
    $a = &quot;\x91\x5c&quot;;//&quot;慭&quot;的gbk编码, 低字节为5c, 也就是ascii中的&quot;\&quot;

    var_dump(addslashes($a));
    var_dump(mysql_real_escape_string($a, $db));

    mysql_query(&quot;set names gbk&quot;);
    var_dump(mysql_real_escape_string($a, $db));

    mysql_set_charset(&quot;gbk&quot;);
    var_dump(mysql_real_escape_string($a, $db));
?&gt;
</pre>
<p>因为, &#8220;慭&#8221;的gbk编码低字节为5c, 也就是ascii中的&#8221;\&#8221;, 而因为除了mysql(i)_set_charset影响mysql->charset以外, 其他时刻mysql->charset都为默认值, 所以, 结果就是:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ php -f 5c.php
string(3) &quot;慭\&quot;
string(3) &quot;慭\&quot;
string(3) &quot;慭\&quot;
string(2) &quot;慭&quot;
</pre>
<p>  大家现在很清楚了吧?
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/12</a>, qywyh writes: 看贴不回木jj，学习了,顶！</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/12</a>, <a href="http://www.felix021.com"  rel="external nofollow"  class="url" >felix021</a> writes: 1L真狠。。。</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, <a href="http://topsy.com/trackback?utm_source=pingback&#038;utm_campaign=L2&#038;url=http://www.laruence.com/2010/04/12/1396.html"  rel="external nofollow"  class="url" >Tweets that mention 深入理解SET NAMES和mysql(i)_set_charset的区别 | 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by 高春辉, Angus Li. Angus Li said: 深入理解SET NAMES和mysql(i)_set_charset的区别 http://ff.im/-iUWcK [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, <a href="http://blog.panzhibiao.com"  rel="external nofollow"  class="url" >kevin</a> writes: addslashes(), str_replace()等等基于ascii编码的函数都会遇到这种问题。mysql_*系列有解决方案，别的有什么好的解决方案么？</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, <a href="http://www.itphper.com/blog/?p=84"  rel="external nofollow"  class="url" >[转]深入理解SET NAMES和mysql(i)_set_charset的区别 - coder辉的it生涯</a> writes: [...] 本文地址: http://www.laruence.com/2010/04/12/1396.html [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, <a href="http://sanmuding.com"  rel="external nofollow"  class="url" >Anders</a> writes: 之前</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, <a href="http://sanmuding.com"  rel="external nofollow"  class="url" >Anders</a> writes: 之前遇到这个问题，但是 使用的是PDO, 不知道如何解决。</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @Anders pdo找不到类似的方法,,,,,</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, cz writes: 所以这两年我一看到SET NAMES的代码就要破口大骂，虽然utf-8编码里不存在5c问题

另外对于PDO，可以用prepared statement来解决。这也是一个比字符串过滤更好的防止注入的方法</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, 好黑啊 writes: 非常good的文章，我very like</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/13</a>, <a href="http://hi.baidu.com/aleafs"  rel="external nofollow"  class="url" >aleafs</a> writes: 太清楚了</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/17</a>, <a href="http://www.jaceju.net/blog/?p=1108"  rel="external nofollow"  class="url" >網站製作學習誌 &raquo; [Web] 連結分享</a> writes: [...] 深入理解SET NAMES和mysql(i)_set_charset的区别 [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/04/18</a>, Yufeng writes: 学习了，呵呵。</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/05/14</a>, <a href="http://www.bringsir.com"  rel="external nofollow"  class="url" >kazaff</a> writes: thx</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/07/03</a>, <a href="http://www.lowest-rate-loans.com"  rel="external nofollow"  class="url" >OllieNoel</a> writes: Have no enough cash to buy a car? Worry no more, just because that is achievable to get the <a href="http://lowest-rate-loans.com/topics/credit-loans"  rel="nofollow" >credit loans</a> to solve such problems. Thus get a small business loan to buy everything you need.</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/09/03</a>, <a href="http://54blues.com"  rel="external nofollow"  class="url" >blues</a> writes: 新手参上
竟然深入到C中了,C语言没怎么学会,看了个不大懂,自学的时候也没注意到这些问题,见识了,你的博客都很有深度啊,会经常来看的.目前还只能做做应用,无法深入到C,你这篇文章改变了我对php的理解,本以为可以不学C了,现在发现要深入学习还是需要知其根源,希望2年后毕业的时候也能有这样的深度.</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2010/12/29</a>, <a href="http://www.bpzc.net/article-107.html"  rel="external nofollow"  class="url" >[PHP]SET NAMES和mysql(i)_set_charset的区别 &raquo; 半瓶子醋</a> writes: [...] 转自[风雪之隅] [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2011/03/07</a>, 寻仙人 writes: 高手啊，膜拜</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2011/03/15</a>, <a href="http://blog.zahuibbs.com/?p=418"  rel="external nofollow"  class="url" >关于宽字节（宽字符）注入。 - whoami&#039;s blog</a> writes: [...] 参考 ： http://www.laruence.com/2010/04/12/1396.html http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2011/03/20</a>, <a href="http://www.w3hacker.com/?p=191"  rel="external nofollow"  class="url" >深入理解SET NAMES和mysql(i)_set_charset的区别 | 万维网黑客联盟</a> writes: [...] 本文地址: http://www.laruence.com/2010/04/12/1396.html [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2011/04/17</a>, asdf1234 writes: 大牛，你是在什么公司啊，百度？</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2011/06/01</a>, <a href="http://blog.missyi.com/page_722.html"  rel="external nofollow"  class="url" >深入理解SET NAMES和mysql(i)_set_charset的区别 | 麦克 Magic Coder</a> writes: [...] 本文地址: http://www.laruence.com/2010/04/12/1396.html [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2011/07/30</a>, <a href="http://blog.nhack.com/blog/?p=415"  rel="external nofollow"  class="url" >iEasyi &raquo; Blog Archive &raquo; 宽字节（宽字符）注入</a> writes: [...] 参考 ： http://www.laruence.com/2010/04/12/1396.html http://www.mirecle.com/2010/04/13/php-in-the-set-names-and-mysql_set_charset.html [...]</li><li><a href="http://www.laruence.com/2010/04/12/1396.html" >2011/11/06</a>, <a href="http://ihacklog.com"  rel="external nofollow"  class="url" >荒野无灯</a> writes: 嗯，关于gbk编码与\的一个漏洞以前在某老外的blog上看到过。</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/08/28/483.html"  rel="bookmark"  title="Permanent Link: HTTP1.0下HTTP_HOST为空" >HTTP1.0下HTTP_HOST为空</a></li><li><a href="http://www.laruence.com/2009/12/26/1198.html"  rel="bookmark"  title="Permanent Link: 深入理解PHP原理之变量生命期(一)" >深入理解PHP原理之变量生命期(一)</a></li><li><a href="http://www.laruence.com/2008/11/20/640.html"  rel="bookmark"  title="Permanent Link: Opcodes list" >Opcodes list</a></li><li><a href="http://www.laruence.com/2009/06/14/945.html"  rel="bookmark"  title="Permanent Link: 深入理解PHP原理之扩展载入过程" >深入理解PHP原理之扩展载入过程</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/02/08/2528.html"  title="PHP-5.3.9远程执行任意代码漏洞(CVE-2012-0830)" >PHP-5.3.9远程执行任意代码漏洞(CVE-2012-0830)</a></li><li><a href="http://www.laruence.com/2012/02/02/2515.html"  title="我们什么时候应该使用异常?" >我们什么时候应该使用异常?</a></li><li><a href="http://www.laruence.com/2012/02/01/2503.html"  title="使用exit(-1)为什么得到255退出码?" >使用exit(-1)为什么得到255退出码?</a></li><li><a href="http://www.laruence.com/2012/01/11/2482.html"  title="PHP的历史" >PHP的历史</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2012/01/07/2453.html"  title="2012年1月全球www网站技术报告" >2012年1月全球www网站技术报告</a></li><li><a href="http://www.laruence.com/2011/12/30/2440.html"  title="PHP5.2.*防止Hash冲突拒绝服务攻击的Patch" >PHP5.2.*防止Hash冲突拒绝服务攻击的Patch</a></li><li><a href="http://www.laruence.com/2011/12/30/2435.html"  title="PHP数组的Hash冲突实例" >PHP数组的Hash冲突实例</a></li><li><a href="http://www.laruence.com/2011/12/29/2412.html"  title="通过构造Hash冲突实现各种语言的拒绝服务攻击" >通过构造Hash冲突实现各种语言的拒绝服务攻击</a></li><li><a href="http://www.laruence.com/2011/12/06/2381.html"  title="更简单的重现PHP Core的调用栈" >更简单的重现PHP Core的调用栈</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/04/12/1396.html/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>也谈PostgreSQL的同步配置(Slony)</title>
		<link>http://www.laruence.com/2009/06/09/912.html</link>
		<comments>http://www.laruence.com/2009/06/09/912.html#comments</comments>
		<pubDate>Tue, 09 Jun 2009 12:47:39 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[pgsql]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[slony]]></category>
		<category><![CDATA[同步]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=912</guid>
		<description><![CDATA[    不知道"拉"一天开始, 好像大家都开始谈论PgSQL了, 呵呵, 最近尝试在项目中使用Pgsql, 现在就将使用Slony-I配置PostgreSQL同步的过程拿来与大家分享.

    话说Pgsql虽然很流行,但是国内的文档真的是很少,尤其配置同步这块,基本上都是互相转贴, 写的也很笼统,在我自己配置过程中, 遇到了很多问题. 本文将努力将各种概念解释清楚, 尽量避免大家再遇到我遇到的疑难问题.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/06/09/912.html"  title="Permanet Link to 也谈PostgreSQL的同步配置(Slony)" >http://www.laruence.com/2009/06/09/912.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    不知道&#8221;拉&#8221;一天开始, 好像大家都开始谈论PgSQL了, 呵呵, 最近尝试在项目中使用Pgsql, 现在就将使用Slony-I配置PostgreSQL同步的过程拿来与大家分享.</p>
<p>   话说Pgsql虽然很流行,但是国内的文档真的是很少,尤其配置同步这块,基本上都是互相转贴, 写的也很笼统,在我自己配置过程中, 遇到了很多问题. 本文将努力将各种概念解释清楚, 尽量避免大家再遇到我遇到的疑难问题.
</p>
<p>
	Slony-I是一个BSD授权的开源项目, 致力于解决Pgsql的同步. </p>
<p>    它通过在配置中指明的数据库中的特定表上增加trigger(触发器), 从而在主库有变更的时候, 通过trigger函数连接到各个要同步的从库上同步从库.</p>
<p>    正因为如此, 所以我们需要首先创建在每个数据库上的用户, 并且为超级用户, 并且需要配置pg_hab.conf使得主库和从库之间可以互联.</p>
<p>	创建用户可以简单的使用pgsql的createuser, 以下我们假设创建的超级用户为repl,密码也为repl</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
		$ pgsql_dir/bin/createuser -p repl
	</pre>
<p>	另外, 由于Slony的触发器函数是PLPGSQL语言写的, 所以我们也要给相应的数据库安装相应的语言包.</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
		$ pgsql_dir/bin/createlang -d dbname plpgsql
	</pre>
<p>    接下来, 必须在<strong>主服务器和从服务器上</strong>都下载编译安装<a href="http://pgfoundry.org/projects/slony1" > slony-i</a>(我的配置中, slony安装在/home/work/local/slony下, 请根据情况调整相关参数).</p>
<p>    首先我们配置<strong>主服务器上</strong>:<br/>
    1. 在主服务器上, 我们编辑一个shell脚本:configMaster.</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#!/bin/sh
SLONIK=/home/work/local/slony/bin/slonik #slonik可执行文件位置

CLUSTER=Laruence                                                     #自定定义你的集群(Cluster)的名称

MASTER_ID=1                                                             #主库ID
MASTER_HOST=db1.laruence.com   #主库IP或主机名
MASTER_DBNAME=ams                                               #需要复制的数据库名字
MASTER_USER=repl                                                #主库数据库超级用户名
MASTER_PASSWORD=repl                                    #主库数据库超级用户密码

SLAVER_ID=2                                                             #从库ID
SLAVER_HOST=db2.laruence.com   #从库IP或主机名
SLAVER_DBNAME=ams                                               #需要同步的数据库名字(可以和主库数据库的名字不同)
SLAVER_USER=repl                                                #从库数据库超级用户名
SLAVER_PASSWORD=repl                                    #从库数据库超级用户密码

$SLONIK&lt;&lt;_EOF_
cluster name = $CLUSTER; #指明要定义的Cluster名

node $MASTER_ID admin conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MASTER_USER password=$MASTER_PASSWORD';

node $SLAVER_ID admin conninfo = 'dbname=$SLAVER_DBNAME host=$SLAVER_HOST user=$SLAVER_USER password=$SLAVER_PASSWORD';

init cluster(id = 1, comment = 'Primary Cluster'); #初始化Cluster,ID从1开始

create set ( id = 1, origin = $MASTER_ID, comment = 'Data Provider' ); #定义复制集, origin指明主库

set add table ( set id = 1, origin = $MASTER_ID, id = 1, fully qualified name = 'public.repl', comment='Repl Table' );
#为复制集合中增加表, fully qualified name 指明了要复制的表名.

store node ( id = $SLAVER_ID, comment = 'Slave Node', event node=$MASTER_ID); #定义从库节点

#定义路由路径
store path ( server=1, client=2, conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MASTER_USER password=$MASTER_PASSWORD');

#添加事件监听
store listen ( origin = $MASTER_ID, provider = $MASTER_ID, receiver = $SLAVER_ID );
_EOF_
 	</pre>
<p>	然后赋予这个脚本可执行权限, 并在<strong>主库服务器</strong>上执行这个脚本.</p>
<p>	如果执行成功, 我们在$MASTER_DBNAME的数据库中, 查看响应的表的话, 会发现, 这个表被增加了俩个触发器函数:</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
ams=# \d repl
                                  Table &quot;public.repl&quot;
  Column  |          Type          |                     Modifiers
----------+------------------------+---------------------------------------------------
 id       | integer                | not null default nextval('repl_id_seq'::regclass)
 username | character varying(100) |
Indexes:
    &quot;repl_pkey&quot; PRIMARY KEY, btree (id)
Triggers:
    &quot;_Laruence_logtrigger&quot; AFTER INSERT OR DELETE OR UPDATE ON repl FOR EACH ROW EXECUTE PROCEDURE &quot;_Laruence&quot;.logtrigger('_Laruence', '1', 'k')
Disabled triggers:
    &quot;_Laruence_denyaccess&quot; BEFORE INSERT OR DELETE OR UPDATE ON repl FOR EACH ROW EXECUTE PROCEDURE &quot;_Laruence&quot;.denyaccess('_Laruence')
	</pre>
<p>	详细信息, 大家也可以在pg_proc, pg_namespace寻找到更多信息.</p>
<p>	2. 然后分别在<strong>主库服务器和从库服务器</strong>上启动slon进程, 开始监听.</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
	主库服务器上:
	 ./slon Laruence &quot;dbname=ams host=slaver_host user=repl password=repl port=5432&quot; &amp; //其中Laruence为你定义的Cluster名
	</pre>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
	从库服务器上:
	 ./slon Laruence &quot;dbname=ams host=slaver_host user=repl password=repl port=5432&quot;&amp; //其中Laruence为你定义的Cluster名
	</pre>
<p>	3. 接下来,在<strong>主库服务器</strong>上提交同步集, 同样的建立一个shell脚本</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#!/bin/bash
SLONIK=/home/work/local/slony/bin/slonik #slonik可执行文件位置

CLUSTER=Laruence                                                     #自定定义你的集群(Cluster)的名称

MASTER_ID=1                                                             #主库ID
MASTER_HOST=db1.laruence.com   #主库IP或主机名
MASTER_DBNAME=ams                                               #需要复制的数据库名字
MASTER_USER=repl                                                #主库数据库超级用户名
MASTER_PASSWORD=repl                                    #主库数据库超级用户密码

SLAVER_ID=2                                                             #从库ID
SLAVER_HOST=db2.laruence.com   #从库IP或主机名
SLAVER_DBNAME=ams                                               #需要同步的数据库名字(可以和主库数据库的名字不同)
SLAVER_USER=repl                                                #从库数据库超级用户名
SLAVER_PASSWORD=repl                                    #从库数据库超级用户密码

$SLONIK&lt;&lt;_EOF_
cluster name = $CLUSTER; #指明要定义的Cluster名
node $MASTER_ID admin conninfo = 'dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MASTER_USER password=$MASTER_PASSWORD';
node $SLAVER_ID admin conninfo = 'dbname=$SLAVER_DBNAME host=$SLAVER_HOST user=$SLAVER_USER password=$SLAVER_PASSWORD';
# 提交订阅复制集
subscribe set ( id=1, provider=$MASTER_ID, receiver=$SLAVER_ID, forward=no);
_EOF_
</pre>
<p>	同样,赋予这个脚本执行权限, 执行既可.<br/>
	现在看看是否已经开始同步了呢?
</p>
<p>
<b>Q&#038;A:</b></p>
<p>	1. 提示db_getLocalNodeId()  wrong database?<br/>
		检查store path是否设置正确, 主从是否指向正确.</p>
<p>	2. 提示duplicate key sl_nodelock-pkey and duplicate &#8230;?<br/>
		检查主机和从机上的slon进程都是连接向对方, 不要重复.</p>
<p>	3. 运行configmain的时候, 提示REQUIRE EVENT NODE?<br/>
		在定义store node 的时候, 需要指明事件源节点, 在本例中是主机节点($MASTER_ID)</p>
<p>	4. 提示cannot connect to local database &#8211; fe_sendauth: no password supplied:<br/>
		这是因为slony使用的c pgsql lib需要你在用户根目录下建立一个.pgpass文件, 文件的属性必须为0600, 文件的内容格式为: hostname:port:database:username:passwor, 前4个字段,都可以使用&#8221;*&#8221;通配.</p>
<p>	5. 能否实现主从互相同步呢?<br/>
		可以, 只要指明反向的store path, 在订阅集中指明对映的复制条目, 既可. </p>
<p>	6. 能否实现多个从机呢?<br/>
		可以, 添加多个node, store path, set条目既可.</p>
<p>        7. 还有其他问题,怎么办?<br/>
                访问我的blog<a href="http://www.laruence.com/2009/06/09/912.html" >留言交流</a>.</p>
<p>
	参考文档: <a href="http://www.slony.info/documentation/cmds.html"  target="_blank" >SLONY-I</a>
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/06/09/912.html" >2009/06/11</a>, <a href="http://www.mikesmoneysite.com"  rel="external nofollow"  class="url" >How to Make Thousands of Dollars Posting Links on Google</a> writes: Thanks for posting, I'll definitely be subscribing to your blog.</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2009/07/14</a>, sky writes: 同步周期或某一DB网络中断怎么处理的？</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2009/07/14</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: 如果这样,需要重新做一遍整个工作. 貌似也没什么更好的办法.</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2009/07/22</a>, <a href="http://54chen.com"  rel="external nofollow"  class="url" >cc0cc</a> writes: 哈哈 兄弟也开始搞pgsql啦，来看看我的小原创两篇 使用postgreSQL+bamboo搭建比lucene方便N倍的全文搜索 分两部分 http://www.54chen.com/c/601
http://www.54chen.com/c/634
欢迎指点哈</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2009/07/23</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @cc0cc 把你当成SPAM了...^_^</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2010/06/15</a>, <a href="http://www.lowest-rate-loans.com"  rel="external nofollow"  class="url" >DonaldsonMuriel26</a> writes: I propose not to wait until you get enough cash to buy all you need! You can just get the <a href="http://lowest-rate-loans.com/topics/credit-loans"  rel="nofollow" >credit loans</a> or short term loan and feel comfortable</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2011/02/12</a>, smallfish writes: 首先感谢博主写的这篇文章，请教一下，您这篇文章是完整的吗？我怎么在执行第一个脚本configMaster的时候就出错：

./master.sh: line 15: cluster: command not found
./master.sh: line 16: node: command not found
./master.sh: line 17: node: command not found
./master.sh: line 19: syntax error near unexpected token `('
./master.sh: line 19: `init cluster (id = 1, comment = 'Primary Cluster');'

是不是别的地方还要设置？</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2011/02/12</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >laruence</a> writes: @smallfish /home/work/local/slony/bin/slonik 路径对么?</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2011/02/12</a>, smallfish writes: 路径是对的：
# whereis slonik
slonik: /usr/bin/slonik
我的脚本是：
#!/bin/sh
SLONIK=/usr/bin/slonik
CLUSTER=slony_test
MASTER_ID=1
MASTER_HOST=10.155.50.51
MASTER_DBNAME=hhm
MASTER_USER=repl
MASTER_PASSWORD=repl
SLAVER_ID=2
SLAVER_HOST=10.155.50.52
SLAVER_DBNAME=hhm
SLAVER_USER=repl
SLAVER_PASSWORD=repl
#SLONIK&lt;&lt;_EOF_
cluster name = $CLUSTER
node $MASTER_ID admin conninfo = &#039;dbname=$MASTER_DBNAME host=$MASTER_HOST user=$MA
STER_USER password=$MASTER_PASSWORD&#039;;
node $SLAVER_ID admin conninfo = &#039;dbname=$SLAVER_DBNAME host=$SLAVER_HOST user=$
SLAVER_USER password=$SLAVER_PASSWORD&#039;;
init cluster (id = 1, comment = &#039;Primary Cluster&#039;);
create set (id = 1, origin = $MASTER_ID, comment = &#039;Data Provider&#039;);
set add table ( set id = 1,origin = $MASTER_ID, id = 1, fully qualified name = &#039;pu
blic.repl&#039;, comment=&#039;Repl Table&#039;);
store node ( id = $SLAVER_ID, comment = &#039;Slave Node&#039;, event node=$MASTER_ID);
store path ( server=1, client=2, conninfo = &#039;dbname=$MASTER_DBNAME host=$MASTER_HO
ST USER=$MASTER_USER password=$MASTER_PASSWORD&#039;);
store listen ( origin = $MASTER_ID, provider = $MASTER_ID, receiver = $SLAVER_ID);
_EOF_</li><li><a href="http://www.laruence.com/2009/06/09/912.html" >2011/02/13</a>, smallfish writes: 原来是将$SLONIK写成#SLONIK了，现在脚本可以执行，但是提示：
:7: PGRES_FATAL_ERROR select "_Laruence".determineIdxnameUnique('public.repl', NULL);  - ERROR:  Slony-I: table "public"."repl" not found</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Random Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2012/01/24/2494.html"  title="大家新年好~" >大家新年好~</a></li><li><a href="http://www.laruence.com/2011/06/23/2057.html"  title="如何调试PHP的Core之获取基本信息" >如何调试PHP的Core之获取基本信息</a></li><li><a href="http://www.laruence.com/2008/08/26/463.html"  title="深入理解PHP原理之变量作用域(Scope in PHP)" >深入理解PHP原理之变量作用域(Scope in PHP)</a></li><li><a href="http://www.laruence.com/2010/07/16/1648.html"  title="定制自己的PHP语法-在PHP中实现unless" >定制自己的PHP语法-在PHP中实现unless</a></li><li><a href="http://www.laruence.com/2012/01/10/2469.html"  title="如何设置一个严格30分钟过期的Session" >如何设置一个严格30分钟过期的Session</a></li><li><a href="http://www.laruence.com/2008/08/15/274.html"  title="PHP 源代码分析 V0.0.2" >PHP 源代码分析 V0.0.2</a></li><li><a href="http://www.laruence.com/2008/11/19/625.html"  title="让人无语的139邮箱" >让人无语的139邮箱</a></li><li><a href="http://www.laruence.com/2010/06/21/1608.html"  title="PHP调试技术手册发布(1.0.0 pdf)" >PHP调试技术手册发布(1.0.0 pdf)</a></li><li><a href="http://www.laruence.com/2008/08/10/1.html"  title="个人主页开张" >个人主页开张</a></li><li><a href="http://www.laruence.com/2008/07/16/225.html"  title="Zend Engine幻想" >Zend Engine幻想</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/06/09/912.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>统一信息存储平台(ISP)</title>
		<link>http://www.laruence.com/2008/11/11/610.html</link>
		<comments>http://www.laruence.com/2008/11/11/610.html#comments</comments>
		<pubDate>Tue, 11 Nov 2008 08:26:01 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[isp]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[统一信息存储平台]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=610</guid>
		<description><![CDATA[<p>&#160;&#160;是否因为需求经常变动，而导致你需要频繁修改数据库结构呢？ 是否经常的数据库结构的调整，导致你的数据库性能极度下降呢？ 基于这样的考虑， 我设计了ISP， 我的出发点就是， 将数据库的数据逻辑剥离出来，数据库单纯就是存储数据，而数据之间的逻辑关系，提出来交由脚本逻辑完成。 并且在设计数据库的时候， 本着适应多种数据存储要求，而设计出可定制的表结构，和适应定制化的接口。</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2008/11/11/610.html"  title="Permanet Link to 统一信息存储平台(ISP)" >http://www.laruence.com/2008/11/11/610.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>是否因为需求经常变动，而导致你需要频繁修改数据库结构呢？ 是否经常的数据库结构的调整，导致你的数据库性能极度下降呢？ 基于这样的考虑， 我设计了ISP， 我的出发点就是， 将数据库的数据逻辑剥离出来，数据库单纯就是存储数据，而数据之间的逻辑关系，提出来交由脚本逻辑完成。 并且在设计数据库的时候， 本着适应多种数据存储要求，而设计出可定制的表结构，和适应定制化的接口。</p>
<p>
     现在来说，还只是一个最简单的版本加一个应用，之后有时间了，我会将这个外部逻辑包装，包装成一个c library,并加入连接池管理， 最后再通过PHP扩展，提供接口给PHP方便使用。
</p>
<p>
 数据库设计图：<br/>
<div id="attachment_611"  class="wp-caption aligncenter"  style="width: 310px" ><a href="http://laruence-wordpress.stor.sinaapp.com/uploads/aos-e695b0e68daee5ba93.png" ><img src="http://laruence-wordpress.stor.sinaapp.com/uploads/aos-e695b0e68daee5ba93-300x249.png"  alt="ISP数据库设计"  title="ISP_ARCH"  width="300"  height="249"  class="size-medium wp-image-611" /></a><p class="wp-caption-text" >ISP数据库设计</p></div>
</p>
<p>
Project Home:<a href="http://code.google.com/p/infosstoreplatform/" >http://code.google.com/p/infosstoreplatform/</a><br/>
Codes : <a href="http://code.google.com/p/infosstoreplatform/source/browse/#svn/trunk" >http://code.google.com/p/infosstoreplatform/source/browse/#svn/trunk</a></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/11</a>, <a href="http://www.blankyao.cn"  rel="external nofollow"  class="url" >blankyao</a> writes: 先down下来再说</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/11</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: ^_^,恐怕让你失望了</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/12</a>, <a href="http://icyriver.net/"  rel="external nofollow"  class="url" >IcyRiver</a> writes: .....</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/12</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: I no why you so ....</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/12</a>, ryan writes: 又看到新东西，支持...</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/12</a>, zvaly writes: 不错不错，需要合伙人不？</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/12</a>, Commen writes: Commen</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/13</a>, timothy_huo writes: 有点熟悉的影子，拍一下。期待下文...</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/14</a>, <a href="http://www.blankyao.cn"  rel="external nofollow"  class="url" >blankyao</a> writes: 期待你加入c library ，哈哈</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/11/21</a>, <a href="http://rodin.rizili.cn"  rel="external nofollow"  class="url" >Rodin</a> writes: 莫非……莫非……

为什么不用bdb呢？

用bdb的bt模式，连索引都有了~不够的话，还有oracle的扩展项目： Bdb XML，支持XQuery</li><li><a href="http://www.laruence.com/2008/11/11/610.html" >2008/12/31</a>, 守护 writes: 期待</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/04/27/1995.html"  title="为MySQL设置查询超时" >为MySQL设置查询超时</a></li><li><a href="http://www.laruence.com/2010/04/12/1396.html"  title="深入理解SET NAMES和mysql(i)_set_charset的区别" >深入理解SET NAMES和mysql(i)_set_charset的区别</a></li><li><a href="http://www.laruence.com/2008/01/05/12.html"  title="深入Mysql字符集设置" >深入Mysql字符集设置</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2008/11/11/610.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>MySQL也真是让人郁闷(关于子查询中使用limit)</title>
		<link>http://www.laruence.com/2008/07/16/227.html</link>
		<comments>http://www.laruence.com/2008/07/16/227.html#comments</comments>
		<pubDate>Wed, 16 Jul 2008 07:08:14 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[随笔]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=227</guid>
		<description><![CDATA[    在MySQL4.1中子查询是不能使用LIMIT的，手册中也明确指明 "This version of MySQL doesn't yet support 'LIMIT &#038; IN/ALL/ANY/SOME subquery' "

  也就是说，这样的语句是不能正确执行的。
      select * from table where id in (select id from table limit 10);

  但是，，但是，，，只要你再来一层就行。。如：
      select * from table where id in (select t.id from (select * from table limit 10)as t)

  你说说，MySQL是不是很让人无语？？]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2008/07/16/227.html"  title="Permanet Link to MySQL也真是让人郁闷(关于子查询中使用limit)" >http://www.laruence.com/2008/07/16/227.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<p>    在MySQL4.1中子查询是不能使用LIMIT的，手册中也明确指明 &#8220;This version of MySQL doesn&#8217;t yet support &#8216;LIMIT &#038; IN/ALL/ANY/SOME subquery&#8217; &#8221;</p>
<p>  也就是说，这样的语句是不能正确执行的。<br/>
      select * from table where id in (select id from table limit 10);</p>
<p>  但是，，但是，，，只要你再来一层就行。。如：<br/>
      select * from table where id in (select t.id from (select * from table limit 10)as t)</p>
<p>  你说说，MySQL是不是很让人无语？？</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/07/16/227.html" >2008/09/13</a>, <a href="http://zhengwei.name"  rel="external nofollow"  class="url" >zwws</a> writes: ...无语</li><li><a href="http://www.laruence.com/2008/07/16/227.html" >2008/12/27</a>, RainChen writes: 更感兴趣的，你怎么发现的，一般都很少用到2层子查询了</li><li><a href="http://www.laruence.com/2008/07/16/227.html" >2009/01/14</a>, ilsanbao[小宝] writes: 无语的有点BT</li><li><a href="http://www.laruence.com/2008/07/16/227.html" >2009/05/11</a>, LungZeno writes: 測試了一下，又是自然人類語言的歧義性使人誤解……
"This version of MySQL doesn't yet support 'LIMIT &amp; IN/ALL/ANY/SOME subquery'" 的意思是，這版本的 MySQL 不支持使用 LIMIT 子句的 IN/ALL/ANY/SOME 子查詢，即是支持非 IN/ALL/ANY/SOME 子查詢的 LIMIT 子查詢。
歧義點在於各生字的 apply 和組合順序，這句子的正確結合順序是 "This version of MySQL doesn't yet support ((LIMIT-(IN/ALL/ANY/SOME)) subquery)" （"-"符號為 hyphen ），有可能的錯誤理解是 "This version of MySQL doesn't yet support ((LIMIT subquery) &amp; ((IN/ALL/ANY/SOME) subquery))" 。</li><li><a href="http://www.laruence.com/2008/07/16/227.html" >2011/02/22</a>, <a href="http://www.5idev.com"  rel="external nofollow"  class="url" >5idev</a> writes: 谢谢楼主，因为这次在子查询用到了limit，mysql不支持，用楼主的方法解决了！</li><li><a href="http://www.laruence.com/2008/07/16/227.html" >2011/07/13</a>, pan writes: 额，这都被你发现了，神人</li></ul><hr/><h2>Related posts:</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/04/27/1995.html"  rel="bookmark"  title="Permanent Link: 为MySQL设置查询超时" >为MySQL设置查询超时</a></li><li><a href="http://www.laruence.com/2011/10/05/2192.html"  rel="bookmark"  title="Permanent Link: mysqlnd插件mysqlnd_ms的介绍" >mysqlnd插件mysqlnd_ms的介绍</a></li><li><a href="http://www.laruence.com/2010/04/12/1396.html"  rel="bookmark"  title="Permanent Link: 深入理解SET NAMES和mysql(i)_set_charset的区别" >深入理解SET NAMES和mysql(i)_set_charset的区别</a></li><li><a href="http://www.laruence.com/2009/06/17/951.html"  rel="bookmark"  title="Permanent Link: 思考能力何其重要.." >思考能力何其重要..</a></li><li><a href="http://www.laruence.com/2009/08/18/1042.html"  rel="bookmark"  title="Permanent Link: 保证PHP扩展的依赖关系" >保证PHP扩展的依赖关系</a></li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Random Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/09/30/2179.html"  title="PHP正则之递归匹配" >PHP正则之递归匹配</a></li><li><a href="http://www.laruence.com/2011/06/26/2083.html"  title="Yaf已提交到PECL" >Yaf已提交到PECL</a></li><li><a href="http://www.laruence.com/2008/08/28/483.html"  title="HTTP1.0下HTTP_HOST为空" >HTTP1.0下HTTP_HOST为空</a></li><li><a href="http://www.laruence.com/2009/04/24/695.html"  title="数组非数字键名引号的必要性" >数组非数字键名引号的必要性</a></li><li><a href="http://www.laruence.com/2008/08/17/313.html"  title="PHP的老式语法" >PHP的老式语法</a></li><li><a href="http://www.laruence.com/2008/09/23/539.html"  title="使用PHP Embed SAPI实现Opcodes查看器" >使用PHP Embed SAPI实现Opcodes查看器</a></li><li><a href="http://www.laruence.com/2008/09/01/492.html"  title="Js处理Json的&#8221;invalid label&#8221;错" >Js处理Json的&#8221;invalid label&#8221;错</a></li><li><a href="http://www.laruence.com/2009/02/21/662.html"  title="PHP字符串比较" >PHP字符串比较</a></li><li><a href="http://www.laruence.com/2008/11/11/606.html"  title="图解aclocal、autoconf、automake、autoheader、configure" >图解aclocal、autoconf、automake、autoheader、configure</a></li><li><a href="http://www.laruence.com/2008/07/28/210.html"  title="关于JavaScript的执行域,标识符解析,闭包的研究" >关于JavaScript的执行域,标识符解析,闭包的研究</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2008/07/16/227.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>深入Mysql字符集设置</title>
		<link>http://www.laruence.com/2008/01/05/12.html</link>
		<comments>http://www.laruence.com/2008/01/05/12.html#comments</comments>
		<pubDate>Sat, 05 Jan 2008 06:42:09 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[MySQL/PostgreSQL]]></category>
		<category><![CDATA[charset]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[字符集]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=12</guid>
		<description><![CDATA[根据<a href="http://weibo.com/u/1919389283">Chaos  Wang</a>的PPT整理而成， 在此再次感谢Chaos  Wang的此次TechTalk]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: <a href="http://www.laruence.com" >Laruence</a>(<a href="http://www.twitter.com/laruence"  target="meme"  title="Twitter" ><img src="/images/ico-twitter.png" /></a> <a href="http://t.sina.com/laruence"  target="meme"  title="新浪微博" ><img src="/images/ico-sina.png" /></a> <a href="http://fusion.google.com/add?feedurl=http://www.laruence.com/feed"  target="meme"  title="Google阅读器" ><img src="/images/ico-google.png" /></a> <a href="mailto:laruence@yahoo.com.cn"  target="meme"  title="邮件" ><img src="/images/ico-mail.png" /></a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2008/01/05/12.html"  title="Permanet Link to 深入Mysql字符集设置" >http://www.laruence.com/2008/01/05/12.html</a></li>
</li>
<li>转载请注明出处 </li>
</ul></div>
<div id="msgcns!BDC1482E8FA76F7D!290"  class="bvMsg" >
<p><span style="color: #21c0a9;" >根据<a href="http://weibo.com/u/1919389283" >Chaos  Wang</a>的PPT整理而成， 在此再次感谢Chaos Wang的此次TechTalk</span></p>
<h4><strong>基本概念</strong></h4>
<p>• 字符(Character)是指人类语言中最小的表义符号。例如&#8217;A'、&#8217;B'等；</p>
<p>• 给定一系列字符，对每个字符赋予一个数值，用数值来代表对应的字符，这一数值就是字符的编码(Encoding)。例如，我们给字符&#8217;A'赋予数值0，给字符&#8217;B'赋予数值1，则0就是字符&#8217;A'的编码；</p>
<p>• 给定一系列字符并赋予对应的编码后，所有这些字符和编码对组成的集合就是字符集(Character Set)。例如，给定字符列表为{&#8216;A&#8217;,'B&#8217;}时，{&#8216;A&#8217;=&gt;0, &#8216;B&#8217;=&gt;1}就是一个字符集；</p>
<p>• 字符序(Collation)是指在同一字符集内字符之间的比较规则；</p>
<p>• 确定字符序后，才能在一个字符集上定义什么是等价的字符，以及字符之间的大小关系；</p>
<p>• 每个字符序唯一对应一种字符集，但一个字符集可以对应多种字符序，其中有一个是默认字符序(Default Collation)；</p>
<p>• MySQL中的字符序名称遵从命名惯例：以字符序对应的字符集名称开头；以_ci(表示大小写不敏感)、_cs(表示大小写敏感)或_bin(表示按编码值比较)结尾。例如：在字符序&#8220;utf8_general_ci&#8221;下，字符&#8220;a&#8221;和&#8220;A&#8221;是等价的；</p>
<h4><strong>MySQL字符集设置</strong></h4>
<p>• 系统变量：</p>
<p>– <strong>character_set_server</strong>：默认的内部操作字符集</p>
<p>– <strong>character_set_client</strong>：客户端来源数据使用的字符集</p>
<p>– <strong>character_set_connection</strong>：连接层字符集</p>
<p>– <strong>character_set_results</strong>：查询结果字符集</p>
<p>– <strong>character_set_database</strong>：当前选中数据库的默认字符集</p>
<p>– <strong>character_set_system</strong>：系统元数据(字段名等)字符集</p>
<p>– 还有以<strong>collation_</strong>开头的同上面对应的变量，用来描述字符序。</p>
<p>• 用introducer指定文本字符串的字符集：</p>
<p>– 格式为：[_charset] &#8216;string&#8217; [COLLATE collation]</p>
<p>– 例如：</p>
<p>• SELECT _latin1 &#8216;string&#8217;;</p>
<p>• SELECT _utf8 &#8216;你好&#8217; COLLATE utf8_general_ci;</p>
<p>– 由introducer修饰的文本字符串在请求过程中不经过多余的转码，直接转换为内部字符集处理。</p>
<h4><strong>MySQL中的字符集转换过程</strong></h4>
<p>1. MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection；</p>
<p>2. 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集，其确定方法如下：</p>
<p>• 使用每个数据字段的CHARACTER SET设定值；</p>
<p>• 若上述值不存在，则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展，非SQL标准)；</p>
<p>• 若上述值不存在，则使用对应数据库的DEFAULT CHARACTER SET设定值；</p>
<p>• 若上述值不存在，则使用character_set_server设定值。</p>
<p>3. 将操作结果从内部操作字符集转换为character_set_results。</p>
<p><a href="http://by1.storage.msn.com/y1pe_jYelFdqS5ZJBldNnN9gSgYvu_yPc2SPiYr0F0bF7hv5mC9eAa4eB1O_GcmQX4LuVf7yiUB9a4WppnLOMJURShP4yYRLXXr?PARTNER=WRITER" ><img border="0"  style="border: 0px none;"  src="http://by1.storage.msn.com/y1pe_jYelFdqS4M9uVHASUOPMiWGlORakiVALpmSBiPqEK3tIk0pus8_MDYpf2ILdCT9o1jW0SU9cv5aDsszqDz1rmEP6crey3P?PARTNER=WRITER"  alt="图片1"  width="426"  height="373" /></a></p>
<h4><strong>常见问题解析</strong></h4>
<p>• 向默认字符集为utf8的数据表插入utf8编码的数据前没有设置连接字符集，查询时设置连接字符集为utf8</p>
<p>– 插入时根据MySQL服务器的默认设置，character_set_client、character_set_connection和character_set_results均为latin1；</p>
<p>– 插入操作的数据将经过latin1=&gt;latin1=&gt;utf8的字符集转换过程，这一过程中每个插入的汉字都会从原始的3个字节变成6个字节保存；</p>
<p>– 查询时的结果将经过utf8=&gt;utf8的字符集转换过程，将保存的6个字节原封不动返回，产生乱码……</p>
<p><a href="http://ixxpjg.bay.livefilestore.com/y1pU6_cSvL4HBsiKr55ChShxx15zfX64SQiUj_czboWqPod1v6K0Wb-LebCyQC1tSi7E9AH1qnY8ACb8E9STxpB268dg3ZYaHFy?PARTNER=WRITER" ><img border="0"  style="border: 0px none; width: 664px; height: 210px;"  src="http://by1.storage.msn.com/y1pe_jYelFdqS65OW_dplyOcCLGOp_5HSQ2yXdkDqtt3VNeuqllpNEkzOzQsKv2mpa71xcdFHmJjZ4Nte_6LGpf7zhgoeoIUoO8?PARTNER=WRITER"  alt="图片2"  width="553"  height="236" /></a></p>
<p>• 向默认字符集为latin1的数据表插入utf8编码的数据前设置了连接字符集为utf8</p>
<p>– 插入时根据连接字符集设置，character_set_client、character_set_connection和character_set_results均为utf8；</p>
<p>– 插入数据将经过utf8=&gt;utf8=&gt;latin1的字符集转换，若原始数据中含有\u0000~\u00ff范围以外的Unicode字 符，会因为无法在latin1字符集中表示而被转换为“?”(0x3F)符号，以后查询时不管连接字符集设置如何都无法恢复其内容了。</p>
<p><a href="http://ixxpjg.bay.livefilestore.com/y1pU6_cSvL4HBsnogZw0HevAR0xadYeRuYNzavtKLG29pZqXskdoxoXjOVZ3rZcYUyu74ISQqNaW2kPQ5ZKj6cc2cIudvq5Y2hF?PARTNER=WRITER" ><img border="0"  style="border: 0px none; width: 659px; height: 246px;"  src="http://by1.storage.msn.com/y1pe_jYelFdqS4EkLLX7fHY9BjVxN1dxUWGpFTyfv_Lk8CdCifQ1ZXIPOGfhFV2emYq46cOYM004D1ft_-dDLfvgEicuIhhGFRB?PARTNER=WRITER"  alt="图片3"  width="559"  height="246" /></a></p>
<h4><strong>检测字符集问题的一些手段</strong></h4>
<p>• SHOW CHARACTER SET;</p>
<p>• SHOW COLLATION;</p>
<p>• SHOW VARIABLES LIKE &#8216;character%&#8217;;</p>
<p>• SHOW VARIABLES LIKE &#8216;collation%&#8217;;</p>
<p>• SQL函数HEX、LENGTH、CHAR_LENGTH</p>
<p>• SQL函数CHARSET、COLLATION</p>
<h4>使用MySQL字符集时的建议</h4>
<p>• 建立数据库/表和进行数据库操作时尽量显式指出使用的字符集，而不是依赖于MySQL的默认设置，否则MySQL升级时可能带来很大困扰；</p>
<p>• 数据库和连接字符集都使用latin1时虽然大部分情况下都可以解决乱码问题，但缺点是无法以字符为单位来进行SQL操作，一般情况下将数据库和连接字符集都置为utf8是较好的选择；</p>
<p>• 使用mysql C API时，初始化数据库句柄后马上用mysql_options设定MYSQL_SET_CHARSET_NAME属性为utf8，这样就不用显式地用 SET NAMES语句指定连接字符集，且用mysql_ping重连断开的长连接时也会把连接字符集重置为utf8；</p>
<p>• 对于mysql PHP API，一般页面级的PHP程序总运行时间较短，在连接到数据库以后显式用SET NAMES语句设置一次连接字符集即可；但当使用长连接时，请注意保持连接通畅并在断开重连后用SET NAMES语句显式重置连接字符集。</p>
<h4>其他注意事项</h4>
<p>• my.cnf中的default_character_set设置只影响mysql命令连接服务器时的连接字符集，不会对使用libmysqlclient库的应用程序产生任何作用！</p>
<p>• 对字段进行的SQL函数操作通常都是以内部操作字符集进行的，不受连接字符集设置的影响。</p>
<p>• SQL语句中的裸字符串会受到连接字符集或introducer设置的影响，对于比较之类的操作可能产生完全不同的结果，需要小心！</p></div>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2008/01/05/12.html" >2008/11/04</a>, jimmy writes: 这篇文字我来回看了好几回,讲解的确实很精细.使我对编码的理解多了份帮助,其实做为一个小鸟,我由衷的期望laruence能在闲暇之际,写些对于初学者如何学习php相关的一些有帮助资料,教程.我知道你会很忙，所以总结出东西就显得尤为宝贵.</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2008/12/03</a>, <a href="http://www.blankyao.cn"  rel="external nofollow"  class="url" >blankyao</a> writes: 如果可以的话，把ppt放出来看下吧，嘿嘿</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2008/12/03</a>, <a href="http://planet.blankyao.cn/mysql-charset.html"  rel="external nofollow"  class="url" >深入Mysql字符集设置 | Planet of CODE</a> writes: [...] 作者:laruence(http://www.laruence.com/) · 本文地址: http://www.laruence.com/2008/01/05/12.html · [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2008/12/04</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @blankyao, 早没了，，，，，</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2008/12/04</a>, <a href="http://www.blankyao.cn"  rel="external nofollow"  class="url" >blankyao</a> writes: @雪候鸟,这么好的资料竟然不保存 :(</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2008/12/04</a>, <a href="http://www.deepseabug.cn/blog/?p=184"  rel="external nofollow"  class="url" >[转]深入Mysql字符集设置 at Deep Sea Bug</a> writes: [...] &middot; 本文地址: http://www.laruence.com/2008/01/05/12.html &middot; [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2009/05/11</a>, LungZeno writes: 題外話，語文中的最小表義單位為語素（morpheme），而非字元（character）。</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/04/12</a>, <a href="http://www.laruence.com/2010/04/12/1396.html"  rel="external nofollow"  class="url" >深入理解SET NAMES和mysql(i)_set_charset的区别 | 风雪之隅</a> writes: [...] 我之前的文章深入MySQL字符集设置中, 曾经介绍过character_set_client/character_set_connection/character_set_results这三个MySQL的&#8221;环境变量&#8221;, 这里再简单介绍下, [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/04/12</a>, qywyh writes: re！</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/06/21</a>, Anonymous writes: 写得很详细,真是浅显易懂嗯</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/06/22</a>, volew writes: • 向默认字符集为utf8的数据表插入utf8编码的数据前没有设置连接字符集，查询时设置连接字符集为utf8

这个情况下关于“结果将经过utf8=&gt;utf8的字符集转换.”我有个疑惑想请教一下.

查询结果MYSQL不会按照 COLUMN CHARSET=》CONNECT CHARSET=》 RESULTS CHARSET
的方式进行转化 即 utf8=&gt; latin1 =&gt; latin1的转换么？</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/08/06</a>, <a href="http://www.bpzc.net/article-107.html"  rel="external nofollow"  class="url" >[PHP]SET NAMES和mysql(i)_set_charset的区别</a> writes: [...] 首先, 很多人都不知道”SET NAMES”到底是做了什么, 我之前的文章深入MySQL字符集设置中, [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/08/12</a>, <a href="http://www.4pang.com/2010/08/12/%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3set-names%e5%92%8cmysqli_set_charset%e7%9a%84%e5%8c%ba%e5%88%ab.html"  rel="external nofollow"  class="url" >4 ～ 胖 &raquo; 深入理解SET NAMES和mysql(i)_set_charset的区别</a> writes: [...] 我之前的文章深入MySQL字符集设置中, 曾经介绍过character_set_client/character_set_connection/character_set_results这三个MySQL的”环境变量”, 这里再简单介绍下, [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/09/29</a>, <a href="http://mesoblog.org/"  rel="external nofollow"  class="url" >Mesothelioma Cancer</a> writes: 我想太多复杂的编码我想你应该上传视频教程。</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/11/25</a>, <a href="http://www.vkebb.com/2010/11/24/%e6%b7%b1%e5%85%a5mysql%e5%ad%97%e7%ac%a6%e9%9b%86%e8%ae%be%e7%bd%ae-%e8%bd%ac/"  rel="external nofollow"  class="url" >深入Mysql字符集设置 [转] &raquo; vkebb 随笔</a> writes: [...] 本文地址: http://www.laruence.com/2008/01/05/12.html [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2010/12/10</a>, <a href="http://blog.cnlaoKe.com/2010/12/10/384/"  rel="external nofollow"  class="url" >深入理解SET NAMES和mysql(i)_set_charset的区别 | CNlaoKe&#39;s Blog</a> writes: [...] 我之前的文章深入MySQL字符集设置中, 曾经介绍过character_set_client/character_set_connection/character_set_results这三个MySQL的”环境变量”, 这里再简单介绍下, [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2011/02/19</a>, <a href="http://foolbird.net"  rel="external nofollow"  class="url" >maker</a> writes: 今天从早上到现在一直都在看您的博文,获益匪浅,期待您更多的分享.</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2011/03/20</a>, <a href="http://www.w3hacker.com/?p=193"  rel="external nofollow"  class="url" >深入Mysql字符集设置 | 万维网黑客联盟</a> writes: [...] 本文地址: http://www.laruence.com/2008/01/05/12.html [...]</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2011/04/23</a>, Kyli writes: 偶像级别呵呵，
向你学习</li><li><a href="http://www.laruence.com/2008/01/05/12.html" >2011/07/06</a>, <a href="http://blog.missyi.com/page_722.html"  rel="external nofollow"  class="url" >深入理解SET NAMES和mysql(i)_set_charset的区别 | 麦克 Magic Coder</a> writes: [...] 很多人都不知道”SET NAMES”到底是做了什么,  我之前的文章深入MySQL字符集设置中, [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small><h2 class="related_post_title" >Related Posts:</h2><ul class="related_post"   style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2011/04/27/1995.html"  title="为MySQL设置查询超时" >为MySQL设置查询超时</a></li><li><a href="http://www.laruence.com/2010/04/12/1396.html"  title="深入理解SET NAMES和mysql(i)_set_charset的区别" >深入理解SET NAMES和mysql(i)_set_charset的区别</a></li><li><a href="http://www.laruence.com/2008/11/11/610.html"  title="统一信息存储平台(ISP)" >统一信息存储平台(ISP)</a></li><li><a href="http://www.laruence.com/2008/10/16/559.html"  title="引用外部JS文件的编码问题" >引用外部JS文件的编码问题</a></li><li><a href="http://www.laruence.com/2008/04/17/110.html"  title="页面乱码问题根源浅析" >页面乱码问题根源浅析</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2008/01/05/12.html/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>

