<?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</title>
	<atom:link href="http://www.tisswb.com/archives/tag/mysql/feed" rel="self" type="application/rss+xml" />
	<link>http://www.tisswb.com</link>
	<description>结婚开始倒计时了，高兴~</description>
	<lastBuildDate>Tue, 19 Jul 2011 09:30:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>centos中mysql重置密码</title>
		<link>http://www.tisswb.com/archives/552.html</link>
		<comments>http://www.tisswb.com/archives/552.html#comments</comments>
		<pubDate>Wed, 10 Feb 2010 04:26:33 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>
		<category><![CDATA[CentOS]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=552</guid>
		<description><![CDATA[mysql YUM 安装路径rpm -ql mysql (usr/bin)
方法：
# /etc/init.d/mysqld stop
# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &#38;
# mysql -u root mysql
mysql&#62; UPDATE user SET Password=PASSWORD('newpassword') where USER='root';
mysql&#62; FLUSH PRIVILEGES;
mysql&#62; quit
# /etc/init.d/mysqld restart
# mysql -uroot -p
]]></description>
			<content:encoded><![CDATA[<p>mysql YUM 安装路径rpm -ql mysql (usr/bin)</p>
<h3 title="转载">方法：</h3>
<p><code># /etc/init.d/mysqld stop<br />
# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &amp;<br />
# mysql -u root mysql<br />
mysql&gt; UPDATE user SET Password=PASSWORD('newpassword') where USER='root';<br />
mysql&gt; FLUSH PRIVILEGES;<br />
mysql&gt; quit<br />
# /etc/init.d/mysqld restart<br />
# mysql -uroot -p</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/552.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysql中int、bigint、smallint 和 tinyint的区别</title>
		<link>http://www.tisswb.com/archives/550.html</link>
		<comments>http://www.tisswb.com/archives/550.html#comments</comments>
		<pubDate>Mon, 08 Feb 2010 14:11:11 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=550</guid>
		<description><![CDATA[最近使用mysql数据库的时候遇到了多种数字的类型，主要有int,bigint,smallint和tinyint。其中比较迷惑的是int和smallint的差别。今天就在网上仔细找了找，找到如下内容，留档做个总结：
使用整数数据的精确数字数据类型。
bigint
从 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型数据（所有数字）。存储大小为 8 个字节。
int
从 -2^31 (-2,147,483,648) 到 2^31 &#8211; 1 (2,147,483,647) 的整型数据（所有数字）。存储大小为 4 个字节。int 的 SQL-92 同义字为 integer。
smallint
从 -2^15 (-32,768) 到 2^15 &#8211; 1 (32,767) 的整型数据。存储大小为 2 个字节。
<span class="readmore"><a href="http://www.tisswb.com/archives/550.html" title="mysql中int、bigint、smallint 和 tinyint的区别" target="_blank">阅读全文——共609字</a></span>]]></description>
			<content:encoded><![CDATA[<p>最近使用mysql数据库的时候遇到了多种数字的类型，主要有int,bigint,smallint和tinyint。其中比较迷惑的是int和smallint的差别。今天就在网上仔细找了找，找到如下内容，留档做个总结：</p>
<p>使用整数数据的精确数字数据类型。</p>
<p><strong>bigint</strong></p>
<p>从 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型数据（所有数字）。存储大小为 8 个字节。</p>
<p><strong>int</strong></p>
<p>从 -2^31 (-2,147,483,648) 到 2^31 &#8211; 1 (2,147,483,647) 的整型数据（所有数字）。存储大小为 4 个字节。<strong>int </strong>的 SQL-92 同义字为 <strong>integer</strong>。</p>
<p><strong>smallint</strong></p>
<p>从 -2^15 (-32,768) 到 2^15 &#8211; 1 (32,767) 的整型数据。存储大小为 2 个字节。</p>
<p><strong>tinyint</strong></p>
<p>从 0 到 255 的整型数据。存储大小为 1 字节。</p>
<h5>注释</h5>
<p>在支持整数值的地方支持 <strong>bigint</strong> 数据类型。但是，<strong>bigint</strong> 用于某些特殊的情况，当整数值超过 <strong>int</strong> 数据类型支持的范围时，就可以采用 <strong>bigint</strong>。在 SQL Server 中，<strong>int</strong> 数据类型是主要的整数数据类型。</p>
<p>在数据类型优先次序表中，<strong>bigint</strong> 位于 <strong>smallmoney</strong> 和 <strong>int</strong> 之间。</p>
<p>只有当参数表达式是 <strong>bigint</strong> 数据类型时，函数才返回 <strong>bigint</strong>。SQL Server 不会自动将其它整数数据类型（<strong>tinyint</strong>、<strong>smallint</strong> 和 <strong>int</strong>）提升为 <strong>bigint</strong>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/550.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用例子说明inner join,left join,right join,full join的区别</title>
		<link>http://www.tisswb.com/archives/545.html</link>
		<comments>http://www.tisswb.com/archives/545.html#comments</comments>
		<pubDate>Mon, 28 Dec 2009 07:54:36 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>
		<category><![CDATA[SQL优化]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=545</guid>
		<description><![CDATA[最近论坛的数据超过了1600万了，时不时的出现访问速度超慢的情况，虽然不是出现频率很多，但也很影响论坛的正常运行。今天终于抽出一些时间来优化一下，经过分析，发现主要是在一个更新主贴回帖数的语句上出现了问题，因为我们的论坛是从dvbbs转过来的，所以当时这个语句做过调整，原来的语句是
SELECT count(*) FROM cdb_posts AS p LEFT JOIN cdb_members AS m ON p.authorid = m.uid WHERE p.tid = '1213675' AND p.invisible = '0' AND p.fid NOT IN (444,92) AND m.uid IS NOT NULL
发现效率真的很差，经常要执行10秒左右，于是现学现卖，抓紧学知识，首先是加索引，效果不错问题解决了。但是我还是想优化一下这个语句。因为这里面的left join一直以来概念模糊，只知道人家用我也用。今天到网上仔细找了找资料学习了一番，把这个语句改成了
<span class="readmore"><a href="http://www.tisswb.com/archives/545.html" title="用例子说明inner join,left join,right join,full join的区别" target="_blank">阅读全文——共1414字</a></span>]]></description>
			<content:encoded><![CDATA[<p>最近论坛的数据超过了1600万了，时不时的出现访问速度超慢的情况，虽然不是出现频率很多，但也很影响论坛的正常运行。今天终于抽出一些时间来优化一下，经过分析，发现主要是在一个更新主贴回帖数的语句上出现了问题，因为我们的论坛是从dvbbs转过来的，所以当时这个语句做过调整，原来的语句是</p>
<p><code>SELECT count(*) FROM cdb_posts AS p LEFT JOIN cdb_members AS m ON p.authorid = m.uid WHERE p.tid = '1213675' AND p.invisible = '0' AND p.fid NOT IN (444,92) AND m.uid IS NOT NULL</code></p>
<p>发现效率真的很差，经常要执行10秒左右，于是现学现卖，抓紧学知识，首先是加索引，效果不错问题解决了。但是我还是想优化一下这个语句。因为这里面的left join一直以来概念模糊，只知道人家用我也用。今天到网上仔细找了找资料学习了一番，把这个语句改成了</p>
<p><code>SELECT count(*) FROM cdb_posts AS p INNER JOIN cdb_members AS m ON p.authorid = m.uid WHERE p.tid = '1213675' AND p.invisible = '0' AND p.fid NOT IN (444,92)</code></p>
<p>下面总结一下inner join,left join,right join,full join的区别</p>
<p>[TEST@ORA1] SQL&gt;select * from a;</p>
<p>编号 姓名<br />
&#8212;- &#8212;&#8212;&#8212;-<br />
1000 张三<br />
2000 李四<br />
3000 王五</p>
<p>[TEST@ORA1] SQL&gt;select * from b;</p>
<p>编号 商品<br />
&#8212;- &#8212;&#8212;&#8212;-<br />
1000 电视机<br />
2000 录像机<br />
4000 自行车</p>
<p>[TEST@ORA1] SQL&gt;set null 空值&#8211;这里为了显示方面我把NULL定义成了[空值]</p>
<p>[TEST@ORA1] SQL&gt;select a.*,b.* from a inner join b on a.编号=b.编号;</p>
<p>编号 姓名       编号 商品<br />
&#8212;- &#8212;&#8212;&#8212;- &#8212;- &#8212;&#8212;&#8212;-<br />
1000 张三       1000 电视机<br />
2000 李四       2000 录像机</p>
<p>[TEST@ORA1] SQL&gt;select a.*,b.* from a left join b on a.编号=b.编号;</p>
<p>编号 姓名       编号 商品<br />
&#8212;- &#8212;&#8212;&#8212;- &#8212;- &#8212;&#8212;&#8212;-<br />
1000 张三       1000 电视机<br />
2000 李四       2000 录像机<br />
3000 王五       空值 空值</p>
<p>[TEST@ORA1] SQL&gt;select a.*,b.* from a right join b on a.编号=b.编号;</p>
<p>编号 姓名       编号 商品<br />
&#8212;- &#8212;&#8212;&#8212;- &#8212;- &#8212;&#8212;&#8212;-<br />
1000 张三       1000 电视机<br />
2000 李四       2000 录像机<br />
空值 空值       4000 自行车</p>
<p>[TEST@ORA1] SQL&gt;select a.*,b.* from a full join b on a.编号=b.编号;</p>
<p>编号 姓名       编号 商品<br />
&#8212;- &#8212;&#8212;&#8212;- &#8212;- &#8212;&#8212;&#8212;-<br />
1000 张三       1000 电视机<br />
2000 李四       2000 录像机<br />
3000 王五       空值 空值<br />
空值 空值       4000 自行车</p>
<p>================================</p>
<p>看例子就一目了然啦。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/545.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>配置LAMP生产环境：安装Apache、PHP、Mysql</title>
		<link>http://www.tisswb.com/archives/526.html</link>
		<comments>http://www.tisswb.com/archives/526.html#comments</comments>
		<pubDate>Sat, 28 Nov 2009 16:59:52 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>
		<category><![CDATA[Web服务器]]></category>
		<category><![CDATA[服务器]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[CentOS]]></category>
		<category><![CDATA[LAMP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=526</guid>
		<description><![CDATA[上一篇主要说了一下快速最小化安装CentOS5.3的过程，这一篇主要讲一讲APM（Apache、PHP、Mysql的缩写）的安装过程。下一篇将集中讲述一下我是优化LAMP（CentOS5.3+Apache2.2.14+PHP5.2.11+Mysql5.0.36）的具体细节。
在CentOS5.3下面安装APM 主要有两种方法，第一种，yum快速安装；第二种，编译安装。这两种方法可以说各有各的好处，作为生产环境都是可以的，下面我们分别讲讲两种方法。
第一种，yum快速安装APM

安装APM之前，为了保证使用mysql5.1.x和php5.2.x，首先要添加一个源
安装相应的GPG key
# rpm --import http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka
新建一个repo
# /etc/yum.repos.d/utterramblings.repo 
<span class="readmore"><a href="http://www.tisswb.com/archives/526.html" title="配置LAMP生产环境：安装Apache、PHP、Mysql" target="_blank">阅读全文——共1272字</a></span>]]></description>
			<content:encoded><![CDATA[<p>上一篇主要说了一下<a href="http://www.tisswb.cn/archives/519.html" target="_self">快速最小化安装CentOS5.3</a>的过程，这一篇主要讲一讲APM（Apache、PHP、Mysql的缩写）的安装过程。下一篇将集中讲述一下我是优化LAMP（CentOS5.3+Apache2.2.14+PHP5.2.11+Mysql5.0.36）的具体细节。</p>
<p>在CentOS5.3下面安装APM 主要有两种方法，第一种，yum快速安装；第二种，编译安装。这两种方法可以说各有各的好处，作为生产环境都是可以的，下面我们分别讲讲两种方法。</p>
<p>第一种，yum快速安装APM</p>
<ol>
<li>安装APM之前，为了保证使用mysql5.1.x和php5.2.x，首先要添加一个源
<p>安装相应的GPG key</p>
<p><code># rpm --import http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka</code></p>
<p>新建一个repo</p>
<p><code># /etc/yum.repos.d/utterramblings.repo </code></p>
<p>把以下内容添加进去，保存退出就OK了</p>
<p><code>[utterramblings]<br />
name=Jason's Utter Ramblings Repo<br />
baseurl=http://www.jasonlitka.com/media/EL$releasever/$basearch/<br />
enabled=1<br />
gpgcheck=1<br />
gpgkey=http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka </code></p>
</li>
<li>安装APM
<p>安装命令如下：</p>
<p><code>yum install httpd httpd-devel mysql mysql-devel mysql-server php php-devel php-mysql php-common php-gd php-mbstring php-mcrypt php-xml</code></p>
<p>使用/etc/init.d/httpd start 就可以开启web服务器。</p>
<p>使用/etc/init.d/mysqld start 就可以开启Mysql数据库服务器。</li>
<li>初始化Mysql
<p>第一次启动mysql以后执行如下命令：</p>
<p><code>/usr/bin/mysqladmin -u root password 'asdasd'</code></p>
<p>其中&#8221;中的asdasd是密码，你可以设置成想要的密码。</p>
<p>给root用户授权局域网访问</p>
<p><code>GRANT ALL ON *.* TO root@'192.168.%.%' IDENTIFIED BY '密码';<br />
flush privileges;</code></p>
<p>这样的话就可以使用如下命令登陆mysql了：</p>
<p><code>mysql -uroot -p</code></li>
<li>设置httpd和mysqld开机启动
<p>命令如下：</p>
<p><code>chkconfig httpd on</p>
<p>chkconfig mysqld on</p>
<p></code></li>
<li>在/var/www/html下面新建网页phpinfo.php，内容如下：
<p>这样就可以访问基本的web了：http://192.168.0.6/phpinfo.php （其中192.168.0.6是服务器的ip地址）</li>
</ol>
<p>第二种，编译安装APM</p>
<p>具体编译过程正在整理，敬请期待</p>
<p>20100525 今天更新了一下yum的安装方法，添加了几个devel的安装，因为有些时候安装其他的软件的时候需要用到。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/526.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>my.cnf详解及详细翻译</title>
		<link>http://www.tisswb.com/archives/489.html</link>
		<comments>http://www.tisswb.com/archives/489.html#comments</comments>
		<pubDate>Mon, 13 Apr 2009 05:55:29 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=489</guid>
		<description><![CDATA[配置详解：
mysqld程序&#8211;目录和文件
basedir = path  使用给定目录作为根目录(安装目录)。
character-sets-dir = path  给出存放着字符集的目录。
datadir = path  从给定目录读取数据库文件。
pid-file = filename  为mysqld程序指定一个存放进程ID的文件(仅适用于UNIX/Linux系统); Init-V脚本需要使用这个文件里的进程ID结束mysqld进程。
socket = filename  为MySQL客户程序与服务器之间的本地通信指定一个套接字文件(仅适用于UNIX/Linux系统; 默认设置一般是/var/lib/mysql/mysql.sock文件)。
在Windows环境下，如果MySQL客户与服务器是通过命名管道进行通信的，&#8211;sock选项给出的将是该命名管道的名字(默认设置是MySQL)。
<span class="readmore"><a href="http://www.tisswb.com/archives/489.html" title="my.cnf详解及详细翻译" target="_blank">阅读全文——共17353字</a></span>]]></description>
			<content:encoded><![CDATA[<h2><strong>配置详解：</strong></h2>
<p><span style="font-size: 10pt;">mysqld程序&#8211;目录和文件<br />
basedir = path  使用给定目录作为根目录(安装目录)。<br />
character-sets-dir = path  给出存放着字符集的目录。<br />
datadir = path  从给定目录读取数据库文件。<br />
pid-file = filename  为mysqld程序指定一个存放进程ID的文件(仅适用于UNIX/Linux系统); Init-V脚本需要使用这个文件里的进程ID结束mysqld进程。<br />
socket = filename  为MySQL客户程序与服务器之间的本地通信指定一个套接字文件(仅适用于UNIX/Linux系统; 默认设置一般是/var/lib/mysql/mysql.sock文件)。<br />
在Windows环境下，如果MySQL客户与服务器是通过命名管道进行通信的，&#8211;sock选项给出的将是该命名管道的名字(默认设置是MySQL)。<br />
lower_case_table_name = 1/0  新目录和数据表的名字是否只允许使用小写字母; 这个选项在Windows环境下的默认设置是1(只允许使用小写字母)。</p>
<p>mysqld程序&#8211;语言设置<br />
character-sets-server = name  新数据库或数据表的默认字符集。为了与MySQL的早期版本保持兼容，这个字符集也可以用&#8211;default-character-set选项给出; 但这个选项已经显得有点过时了。<br />
collation-server = name  新数据库或数据表的默认排序方式。<br />
lanuage = name  用指定的语言显示出错信息。</p>
<p>mysqld程序&#8211;通信、网络、信息安全<br />
enable-named-pipes  允许Windows 2000/XP环境下的客户和服务器使用命名管道(named pipe)进行通信。这个命名管道的默认名字是MySQL，但可以用&#8211;socket选项来改变。<br />
local-infile [=0]  允许/禁止使用LOAD DATA LOCAL语句来处理本地文件。<br />
myisam-recover [=opt1, opt2, ...]  在启动时自动修复所有受损的MyISAM数据表。这个选项的可取值有4种:DEFAULT、BACKUP、QUICK和FORCE; 它们与myisamchk程序的同名选项作用相同。<br />
old-passwords  使用MySQL 3.23和4.0版本中的老算法来加密mysql数据库里的密码(默认使用MySQL 4.1版本开始引入的新加密算法)。<br />
port = n  为MySQL程序指定一个TCP/IP通信端口(通常是3306端口)。<br />
safe-user-create  只有在mysql.user数据库表上拥有INSERT权限的用户才能使用GRANT命令; 这是一种双保险机制(此用户还必须具备GRANT权限才能执行GRANT命令)。<br />
shared-memory  允许使用内存(shared memory)进行通信(仅适用于Windows)。<br />
shared-memory-base-name = name  给共享内存块起一个名字(默认的名字是MySQL)。<br />
skip-grant-tables  不使用mysql数据库里的信息来进行访问控制(警告:这将允许用户任何用户去修改任何数据库)。<br />
skip-host-cache  不使用高速缓存区来存放主机名和IP地址的对应关系。<br />
skip-name-resovle  不把IP地址解析为主机名; 与访问控制(mysql.user数据表)有关的检查全部通过IP地址行进。<br />
skip-networking  只允许通过一个套接字文件(Unix/Linux系统)或通过命名管道(Windows系统)进行本地连接，不允许ICP/IP连接; 这提高了安全性，但阻断了来自网络的外部连接和所有的Java客户程序(Java客户即使在本地连接里也使用TCP/IP)。<br />
user = name  mysqld程序在启动后将在给定UNIX/Linux账户下执行; mysqld必须从root账户启动才能在启动后切换到另一个账户下执行; mysqld_safe脚本将默认使用&#8211;user=mysql选项来启动mysqld程序。</p>
<p>mysqld程序&#8211;内存管理、优化、查询缓存区<br />
bulk_insert_buffer_size = n  为一次插入多条新记录的INSERT命令分配的缓存区长度(默认设置是8M)。<br />
key_buffer_size = n  用来存放索引区块的RMA值(默认设置是8M)。<br />
join_buffer_size = n  在参加JOIN操作的数据列没有索引时为JOIN操作分配的缓存区长度(默认设置是128K)。<br />
max_heap_table_size = n  HEAP数据表的最大长度(默认设置是16M); 超过这个长度的HEAP数据表将被存入一个临时文件而不是驻留在内存里。<br />
max_connections = n  MySQL服务器同时处理的数据库连接的最大数量(默认设置是100)。<br />
query_cache_limit = n  允许临时存放在查询缓存区里的查询结果的最大长度(默认设置是1M)。<br />
query_cache_size = n  查询缓存区的最大长度(默认设置是0，不开辟查询缓存区)。<br />
query_cache_type = 0/1/2  查询缓存区的工作模式:0, 禁用查询缓存区; 1，启用查询缓存区(默认设置); 2，&#8221;按需分配&#8221;模式，只响应SELECT SQL_CACHE命令。<br />
read_buffer_size = n  为从数据表顺序读取数据的读操作保留的缓存区的长度(默认设置是128KB); 这个选项的设置值在必要时可以用SQL命令SET SESSION read_buffer_size = n命令加以改变。<br />
read_rnd_buffer_size = n  类似于read_buffer_size选项，但针对的是按某种特定顺序(比如使用了ORDER BY子句的查询)输出的查询结果(默认设置是256K)。<br />
sore_buffer = n  为排序操作分配的缓存区的长度(默认设置是2M); 如果这个缓存区太小，则必须创建一个临时文件来进行排序。<br />
table_cache = n  同时打开的数据表的数量(默认设置是64)。<br />
tmp_table_size = n  临时HEAP数据表的最大长度(默认设置是32M); 超过这个长度的临时数据表将被转换为MyISAM数据表并存入一个临时文件。</p>
<p>mysqld程序&#8211;日志<br />
log [= file]  把所有的连接以及所有的SQL命令记入日志(通用查询日志); 如果没有给出file参数，MySQL将在数据库目录里创建一个hostname.log文件作为这种日志文件(hostname是服务器的主机名)。<br />
log-slow-queries [= file]  把执行用时超过long_query_time变量值的查询命令记入日志(慢查询日志); 如果没有给出file参数，MySQL将在数据库目录里创建一个hostname-slow.log文件作为这种日志文件(hostname是服务器主机 名)。<br />
long_query_time = n  慢查询的执行用时上限(默认设置是10s)。<br />
long_queries_not_using_indexs  把慢查询以及执行时没有使用索引的查询命令全都记入日志(其余同&#8211;log-slow-queries选项)。<br />
log-bin [= filename]  把对数据进行修改的所有SQL命令(也就是INSERT、UPDATE和DELETE命令)以二进制格式记入日志(二进制变更日志，binary update log)。这种日志的文件名是filename.n或默认的hostname.n，其中n是一个6位数字的整数(日志文件按顺序编号)。<br />
log-bin-index = filename  二进制日志功能的索引文件名。在默认情况下，这个索引文件与二进制日志文件的名字相同，但后缀名是.index而不是.nnnnnn。<br />
max_binlog_size = n  二进制日志文件的最大长度(默认设置是1GB)。在前一个二进制日志文件里的信息量超过这个最大长度之前，MySQL服务器会自动提供一个新的二进制日志文件接续上。<br />
binlog-do-db = dbname  只把给定数据库里的变化情况记入二进制日志文件，其他数据库里的变化情况不记载。如果需要记载多个数据库里的变化情况，就必须在配置文件使用多个本选项来设置，每个数据库一行。<br />
binlog-ignore-db = dbname  不把给定数据库里的变化情况记入二进制日志文件。<br />
sync_binlog = n  每经过n次日志写操作就把日志文件写入硬盘一次(对日志信息进行一次同步)。n=1是最安全的做法，但效率最低。默认设置是n=0，意思是由操作系统来负责二进制日志文件的同步工作。<br />
log-update [= file]  记载出错情况的日志文件名(出错日志)。这种日志功能无法禁用。如果没有给出file参数，MySQL会使用hostname.err作为种日志文件的名字。</p>
<p>mysqld程序&#8211;镜像(主控镜像服务器)<br />
server-id = n  给服务器分配一个独一无二的ID编号; n的取值范围是1~2的32次方启用二进制日志功能。<br />
log-bin = name  启用二进制日志功能。这种日志的文件名是filename.n或默认的hostname.n，其中的n是一个6位数字的整数(日志文件顺序编号)。<br />
binlog-do/ignore-db = dbname  只把给定数据库里的变化情况记入二进制日志文件/不把给定的数据库里的变化记入二进制日志文件。</p>
<p>mysqld程序&#8211;镜像(从属镜像服务器)<br />
server-id = n  给服务器分配一个唯一的ID编号<br />
log-slave-updates  启用从属服务器上的日志功能，使这台计算机可以用来构成一个镜像链(A-&gt;B-&gt;C)。<br />
master-host = hostname  主控服务器的主机名或IP地址。如果从属服务器上存在mater.info文件(镜像关系定义文件)，它将忽略此选项。<br />
master-user = replicusername  从属服务器用来连接主控服务器的用户名。如果从属服务器上存在mater.info文件，它将忽略此选项。<br />
master-password = passwd  从属服务器用来连接主控服务器的密码。如果从属服务器上存在mater.info文件，它将忽略此选项。<br />
master-port = n  从属服务器用来连接主控服务器的TCP/IP端口(默认设置是3306端口)。<br />
master-connect-retry = n  如果与主控服务器的连接没有成功，则等待n秒(s)后再进行管理方式(默认设置是60s)。如果从属服务器存在mater.info文件，<br />
它将忽略此选项。<br />
master-ssl-xxx = xxx  对主、从服务器之间的SSL通信进行配置。<br />
read-only = 0/1  0: 允许从属服务器独立地执行SQL命令(默认设置); 1: 从属服务器只能执行来自主控服务器的SQL命令。<br />
read-log-purge = 0/1  1: 把处理完的SQL命令立刻从中继日志文件里删除(默认设置); 0: 不把处理完的SQL命令立刻从中继日志文件里删除。<br />
replicate-do-table = dbname.tablename  与&#8211;replicate-do-table选项的含义和用法相同，但数据库和数据库表名字里允许出现通配符&#8221;%&#8221;<br />
(例如: test%.%&#8211;对名字以&#8221;test&#8221;开头的所有数据库里的所以数据库表进行镜像处理)。<br />
replicate-do-db = name  只对这个数据库进行镜像处理。<br />
replicate-ignore-table = dbname.tablename  不对这个数据表进行镜像处理。<br />
replicate-wild-ignore-table = dbn.tablen  不对这些数据表进行镜像处理。<br />
replicate-ignore-db = dbname  不对这个数据库进行镜像处理。<br />
replicate-rewrite-db = db1name &gt; db2name  把主控数据库上的db1name数据库镜像处理为从属服务器上的db2name数据库。<br />
report-host = hostname  从属服务器的主机名; 这项信息只与SHOW SLAVE HOSTS命令有关&#8211;主控服务器可以用这条命令生成一份从属服务器的名单。<br />
slave-compressed-protocol = 1  主、从服务器使用压缩格式进行通信&#8211;如果它们都支持这么做的话。<br />
slave-skip-errors = n1, n2, &#8230;或all  即使发生出错代码为n1、n2等的错误，镜像处理工作也继续进行(即不管发生什么错误，镜像处理工作也继续进行)。<br />
如果配置得当，从属服务器不应该在执行SQL命令时发生错误(在主控服务器上执行出错的SQL命令不会被发送到从属服务器上做镜像处理); 如果不使用<br />
slave-skip-errors选项，从属服务器上的镜像工作就可能国为发生错误而中断，中断后需要有人工参与才能继续进行。</p>
<p>mysqld&#8211;InnoDB&#8211;基本设置、表空间文件<br />
skip-innodb  不加载InnoDB数据表驱动程序&#8211;如果用不着InnoDB数据表，可以用这个选项节省一些内存。<br />
innodb-file-per-table  为每一个新数据表创建一个表空间文件而不是把数据表都集中保存在中央表空间里(后者是默认设置)。该选项始见于MySQL 4.1。<br />
innodb-open-file = n  InnoDB数据表驱动程序最多可以同时打开的文件数(默认设置是300)。如果使用了innodb-file-per-table选项并且需要同时打开很多<br />
数据表的话，这个数字很可能需要加大。<br />
innodb_data_home_dir = p  InnoDB主目录，所有与InnoDB数据表有关的目录或文件路径都相对于这个路径。在默认的情况下，这个主目录就是MySQL的数据目录。<br />
innodb_data_file_path = ts  用来容纳InnoDB为数据表的表空间: 可能涉及一个以上的文件; 每一个表空间文件的最大长度都必须以字节(B)、兆字节(MB)或<br />
千兆字节(GB)为单位给出; 表空间文件的名字必须以分号隔开; 最后一个表空间文件还可以带一个autoextend属性和一个最大长度(max:n)。<br />
例如，ibdata1:1G; ibdata2:1G:autoextend:max:2G的意思是: 表空间文件ibdata1的最大长度是1GB，ibdata2的最大长度也是1G，但允许它扩充到2GB。<br />
除文件名外，还可以用硬盘分区的设置名来定义表空间，此时必须给表空间的最大初始长度值加上newraw关键字做后缀，给表空间的最大扩充长度值加上<br />
raw关键字做后缀(例如/dev/hdb1:20Gnewraw或/dev/hdb1:20Graw); MySQL 4.0及更高版本的默认设置是ibdata1:10M:autoextend。<br />
innodb_autoextend_increment = n  带有autoextend属性的表空间文件每次加大多少兆字节(默认设置是8MB)。这个属性不涉及具体的数据表文件，那些文件的<br />
增大速度相对是比较小的。<br />
innodb_lock_wait_timeout = n  如果某个事务在等待n秒(s)后还没有获得所需要的资源，就使用ROLLBACK命令放弃这个事务。这项设置对于发现和处理未能被<br />
InnoDB数据表驱动程序识别出来的死锁条件有着重要的意义。这个选项的默认设置是50s。<br />
innodb_fast_shutdown 0/1  是否以最快的速度关闭InnoDB，默认设置是1，意思是不把缓存在INSERT缓存区的数据写入数据表，那些数据将在MySQL服务器下次<br />
启动时再写入(这么做没有什么风险，因为INSERT缓存区是表空间的一个组成部分，数据不会丢失)。把这个选项设置为0反面危险，因为在计算机关闭时，<br />
InnoDB驱动程序很可能没有足够的时间完成它的数据同步工作，操作系统也许会在它完成数据同步工作之前强行结束InnoDB，而这会导致数据不完整。</p>
<p>mysqld程序&#8211;InnoDB&#8211;日志<br />
innodb_log_group_home_dir = p  用来存放InnoDB日志文件的目录路径(如ib_logfile0、ib_logfile1等)。在默认的情况下，InnoDB驱动程序将使用MySQL数据目<br />
录作为自己保存日志文件的位置。<br />
innodb_log_files_in_group = n  使用多少个日志文件(默认设置是2)。InnoDB数据表驱动程序将以轮转方式依次填写这些文件; 当所有的日志文件都写满以后，<br />
之后的日志信息将写入第一个日志文件的最大长度(默认设置是5MB)。这个长度必须以MB(兆字节)或GB(千兆字节)为单位进行设置。<br />
innodb_flush_log_at_trx_commit = 0/1/2  这个选项决定着什么时候把日志信息写入日志文件以及什么时候把这些文件物理地写(术语称为&#8221;同步&#8221;)到硬盘上。<br />
设置值0的意思是每隔一秒写一次日志并进行同步，这可以减少硬盘写操作次数，但可能造成数据丢失; 设置值1(设置设置)的意思是在每执行完一条COMMIT<br />
命令就写一次日志并进行同步，这可以防止数据丢失，但硬盘写操作可能会很频繁; 设置值2是一般折衷的办法，即每执行完一条COMMIT命令写一次日志，<br />
每隔一秒进行一次同步。<br />
innodb_flush_method = x  InnoDB日志文件的同步办法(仅适用于UNIX/Linux系统)。这个选项的可取值有两种: fdatasync，用fsync()函数进行同步; O_DSYNC，<br />
用O_SYNC()函数进行同步。<br />
innodb_log_archive = 1  启用InnoDB驱动程序的archive(档案)日志功能，把日志信息写入ib_arch_log_n文件。启用这种日志功能在InnoDB与MySQL一起使用时没有<br />
多大意义(启用MySQL服务器的二进制日志功能就足够用了)。</p>
<p>mysqld程序&#8211;InnoDB&#8211;缓存区的设置和优化<br />
innodb_log_buffer_pool_size = n  为InnoDB数据表及其索引而保留的RAM内存量(默认设置是8MB)。这个参数对速度有着相当大的影响，如果计算机上只运行有<br />
MySQL/InnoDB数据库服务器，就应该把全部内存的80%用于这个用途。<br />
innodb_log_buffer_size = n  事务日志文件写操作缓存区的最大长度(默认设置是1MB)。<br />
innodb_additional_men_pool_size = n  为用于内部管理的各种数据结构分配的缓存区最大长度(默认设置是1MB)。<br />
innodb_file_io_threads = n  I/O操作(硬盘写操作)的最大线程个数(默认设置是4)。<br />
innodb_thread_concurrency = n  InnoDB驱动程序能够同时使用的最大线程个数(默认设置是8)。</p>
<p>mysqld程序&#8211;其它选项<br />
bind-address = ipaddr  MySQL服务器的IP地址。如果MySQL服务器所在的计算机有多个IP地址，这个选项将非常重要。<br />
default-storage-engine = type  新数据表的默认数据表类型(默认设置是MyISAM)。这项设置还可以通过&#8211;default-table-type选项来设置。<br />
default-timezone = name  为MySQL服务器设置一个地理时区(如果它与本地计算机的地理时区不一样)。<br />
ft_min_word_len = n  全文索引的最小单词长度工。这个选项的默认设置是4，意思是在创建全文索引时不考虑那些由3个或更少的字符构建单词。<br />
Max-allowed-packet = n  客户与服务器之间交换的数据包的最大长度，这个数字至少应该大于客户程序将要处理的最大BLOB块的长度。这个选项的默认设置是1MB。<br />
Sql-mode = model1, mode2, &#8230;  MySQL将运行在哪一种SQL模式下。这个选项的作用是让MySQL与其他的数据库系统保持最大程度的兼容。这个选项的可取值包括<br />
ansi、db2、oracle、no_zero_date、pipes_as_concat。</p>
<p>注意：如果在配置文件里给出的某个选项是mysqld无法识别的(如，因为犯了一个愚蠢的打字错误)，MySQL服务器将不启动。</span></p>
<h2><strong>详细翻译：</strong></h2>
<div id="articleBody" class="articleContent">#BEGIN CONFIG INFO<br />
#DESCR: 4GB RAM, 只使用InnoDB, ACID, 少量的连接, 队列负载大<br />
#TYPE: SYSTEM<br />
#END CONFIG INFO</p>
<p>#<br />
# 此mysql配置文件例子针对4G内存，并在<a href="http://www.bt285.cn/"><span style="color: #006600;">www.bt285.cn</span></a> bt下载与 <a href="http://www.5a520.cn/"><span style="color: #006600;">www.5a520.cn</span></a> 小说520，这两个日ip 2w ,pv 20w  测试过的。<br />
# 主要使用INNODB<br />
#处理复杂队列并且连接数量较少的mysql服务器<br />
#<br />
# 将此文件复制到/etc/my.cnf 作为全局设置,<br />
# mysql-data-dir/my.cnf 作为服务器指定设置<br />
# (@localstatedir@ for this installation) 或者放入<br />
# ~/.my.cnf 作为用户设置.<br />
#<br />
# 在此配置文件中, 你可以使用所有程序支持的长选项.<br />
# 如果想获悉程序支持的所有选项<br />
# 请在程序后加上&#8221;&#8211;help&#8221;参数运行程序.<br />
#<br />
# 关于独立选项更多的细节信息可以在手册内找到<br />
#</p>
<p>#<br />
# 以下选项会被MySQL客户端应用读取.<br />
# 注意只有MySQL附带的客户端应用程序保证可以读取这段内容.<br />
# 如果你想你自己的MySQL应用程序获取这些值<br />
# 需要在MySQL客户端库初始化的时候指定这些选项</p>
<p>#<br />
[client]<br />
#password = [your_password]<br />
port = @MYSQL_TCP_PORT@<br />
socket = @MYSQL_UNIX_ADDR@</p>
<p># *** 应用定制选项 ***</p>
<p>#<br />
#  MySQL 服务端<br />
#<br />
[mysqld]</p>
<p># 一般配置选项<br />
port = @MYSQL_TCP_PORT@<br />
socket = @MYSQL_UNIX_ADDR@</p>
<p># back_log 是操作系统在监听队列中所能保持的连接数,<br />
# 队列保存了在MySQL连接管理器线程处理之前的连接.<br />
# 如果你有非常高的连接率并且出现&#8221;connection refused&#8221; 报错,<br />
# 你就应该增加此处的值.<br />
# 检查你的操作系统文档来获取这个变量的最大值.<br />
# 如果将back_log设定到比你操作系统限制更高的值,将会没有效果<br />
back_log = 50</p>
<p># 不在TCP/IP端口上进行监听.<br />
# 如果所有的进程都是在同一台服务器连接到本地的mysqld,<br />
# 这样设置将是增强安全的方法<br />
# 所有mysqld的连接都是通过Unix sockets 或者命名管道进行的.<br />
# 注意在windows下如果没有打开命名管道选项而只是用此项<br />
# (通过 &#8220;enable-named-pipe&#8221; 选项) 将会导致mysql服务没有任何作用!<br />
#skip-networking</p>
<p># MySQL 服务所允许的同时会话数的上限<br />
# 其中一个连接将被SUPER权限保留作为管理员登录.<br />
# 即便已经达到了连接数的上限.<br />
max_connections = 100<br />
一般像在我这个<a href="http://www.bt285.cn/"><span style="color: #006600;">www.bt285.cn</span></a> pv 10w   max_connections=30 就够了。但是如果页面都像<a href="http://www.bt285.cn/content.php?id=1196863"><span style="color: #006600;">http://www.bt285.cn/content.php?id=1196863</span></a> 这个甜性涩爱页面一样，max_connections=30是不够的。<br />
# 每个客户端连接最大的错误允许数量,如果达到了此限制.<br />
# 这个客户端将会被MySQL服务阻止直到执行了&#8221;FLUSH HOSTS&#8221; 或者服务重启<br />
# 非法的密码以及其他在链接时的错误会增加此值.<br />
# 查看 &#8220;Aborted_connects&#8221; 状态来获取全局计数器.<br />
max_connect_errors = 10</p>
<p># 所有线程所打开表的数量.<br />
# 增加此值就增加了mysqld所需要的文件描述符的数量<br />
# 这样你需要确认在[mysqld_safe]中 &#8220;open-files-limit&#8221; 变量设置打开文件数量允许至少4096<br />
table_cache = 2048</p>
<p># 允许外部文件级别的锁. 打开文件锁会对性能造成负面影响<br />
# 所以只有在你在同样的文件上运行多个数据库实例时才使用此选项(注意仍会有其他约束!)<br />
# 或者你在文件层面上使用了其他一些软件依赖来锁定MyISAM表<br />
#external-locking</p>
<p># 服务所能处理的请求包的最大大小以及服务所能处理的最大的请求大小(当与大的BLOB字段一起工作时相当必要)<br />
# 每个连接独立的大小.大小动态增加<br />
max_allowed_packet = 16M</p>
<p># 在一个事务中binlog为了记录SQL状态所持有的cache大小<br />
# 如果你经常使用大的,多声明的事务,你可以增加此值来获取更大的性能.<br />
# 所有从事务来的状态都将被缓冲在binlog缓冲中然后在提交后一次性写入到binlog中<br />
# 如果事务比此值大, 会使用磁盘上的临时文件来替代.<br />
# 此缓冲在每个连接的事务第一次更新状态时被创建<br />
binlog_cache_size = 1M</p>
<p># 独立的内存表所允许的最大容量.<br />
# 此选项为了防止意外创建一个超大的内存表导致永尽所有的内存资源.<br />
max_heap_table_size = 64M</p>
<p># 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序<br />
# 如果排序后的数据无法放入排序缓冲,<br />
# 一个用来替代的基于磁盘的合并分类会被使用<br />
# 查看 &#8220;Sort_merge_passes&#8221; 状态变量.<br />
# 在排序发生时由每个线程分配<br />
sort_buffer_size = 8M</p>
<p># 此缓冲被使用来优化全联合(full JOINs 不带索引的联合).<br />
# 类似的联合在极大多数情况下有非常糟糕的性能表现,<br />
# 但是将此值设大能够减轻性能影响.<br />
# 通过 &#8220;Select_full_join&#8221; 状态变量查看全联合的数量<br />
# 当全联合发生时,在每个线程中分配<br />
join_buffer_size = 8M</p>
<p># 我们在cache中保留多少线程用于重用<br />
# 当一个客户端断开连接后,如果cache中的线程还少于thread_cache_size,<br />
# 则客户端线程被放入cache中.<br />
# 这可以在你需要大量新连接的时候极大的减少线程创建的开销<br />
# (一般来说如果你有好的线程模型的话,这不会有明显的性能提升.)<br />
thread_cache_size = 8</p>
<p># 此允许应用程序给予线程系统一个提示在同一时间给予渴望被运行的线程的数量.<br />
# 此值只对于支持 thread_concurrency() 函数的系统有意义( 例如Sun Solaris).<br />
# 你可可以尝试使用 [CPU数量]*(2..4) 来作为thread_concurrency的值<br />
thread_concurrency = 8</p>
<p># 查询缓冲常被用来缓冲 SELECT 的结果并且在下一次同样查询的时候不再执行直接返回结果.<br />
# 打开查询缓冲可以极大的提高服务器速度, 如果你有大量的相同的查询并且很少修改表.<br />
# 查看 &#8220;Qcache_lowmem_prunes&#8221; 状态变量来检查是否当前值对于你的负载来说是否足够高.<br />
# 注意: 在你表经常变化的情况下或者如果你的查询原文每次都不同,<br />
# 查询缓冲也许引起性能下降而不是性能提升.<br />
query_cache_size = 64M</p>
<p># 只有小于此设定值的结果才会被缓冲<br />
# 此设置用来保护查询缓冲,防止一个极大的结果集将其他所有的查询结果都覆盖.<br />
query_cache_limit = 2M</p>
<p># 被全文检索索引的最小的字长.<br />
# 你也许希望减少它,如果你需要搜索更短字的时候.<br />
# 注意在你修改此值之后,<br />
# 你需要重建你的 FULLTEXT 索引<br />
ft_min_word_len = 4</p>
<p># 如果你的系统支持 memlock() 函数,你也许希望打开此选项用以让运行中的mysql在在内存高度紧张的时候,数据在内存中保持锁定并且防止可能被swapping out<br />
# 此选项对于性能有益<br />
#memlock</p>
<p># 当创建新表时作为默认使用的表类型,<br />
# 如果在创建表示没有特别执行表类型,将会使用此值<br />
default_table_type = MYISAM</p>
<p># 线程使用的堆大小. 此容量的内存在每次连接时被预留.<br />
# MySQL 本身常不会需要超过64K的内存<br />
# 如果你使用你自己的需要大量堆的UDF函数<br />
# 或者你的操作系统对于某些操作需要更多的堆,<br />
# 你也许需要将其设置的更高一点.<br />
thread_stack = 192K</p>
<p># 设定默认的事务隔离级别.可用的级别如下:<br />
# READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE<br />
transaction_isolation = REPEATABLE-READ</p>
<p># 内部(内存中)临时表的最大大小<br />
# 如果一个表增长到比此值更大,将会自动转换为基于磁盘的表.<br />
# 此限制是针对单个表的,而不是总和.<br />
tmp_table_size = 64M</p>
<p># 打开二进制日志功能.<br />
# 在复制(replication)配置中,作为MASTER主服务器必须打开此项<br />
# 如果你需要从你最后的备份中做基于时间点的恢复,你也同样需要二进制日志.<br />
log-bin=mysql-bin</p>
<p># 如果你在使用链式从服务器结构的复制模式 (A-&gt;B-&gt;C),<br />
# 你需要在服务器B上打开此项.<br />
# 此选项打开在从线程上重做过的更新的日志,<br />
# 并将其写入从服务器的二进制日志.<br />
#log_slave_updates</p>
<p># 打开全查询日志. 所有的由服务器接收到的查询 (甚至对于一个错误语法的查询)<br />
# 都会被记录下来. 这对于调试非常有用, 在生产环境中常常关闭此项.<br />
#log</p>
<p># 将警告打印输出到错误log文件.  如果你对于MySQL有任何问题<br />
# 你应该打开警告log并且仔细审查错误日志,查出可能的原因.<br />
#log_warnings</p>
<p># 记录慢速查询. 慢速查询是指消耗了比 &#8220;long_query_time&#8221; 定义的更多时间的查询.<br />
# 如果 log_long_format 被打开,那些没有使用索引的查询也会被记录.<br />
# 如果你经常增加新查询到已有的系统内的话. 一般来说这是一个好主意,<br />
log_slow_queries</p>
<p># 所有的使用了比这个时间(以秒为单位)更多的查询会被认为是慢速查询.<br />
# 不要在这里使用&#8221;1&#8243;, 否则会导致所有的查询,甚至非常快的查询页被记录下来(由于MySQL 目前时间的精确度只能达到秒的级别).<br />
long_query_time = 2</p>
<p># 在慢速日志中记录更多的信息.<br />
# 一般此项最好打开.<br />
# 打开此项会记录使得那些没有使用索引的查询也被作为到慢速查询附加到慢速日志里<br />
log_long_format</p>
<p># 此目录被MySQL用来保存临时文件.例如,<br />
# 它被用来处理基于磁盘的大型排序,和内部排序一样.<br />
# 以及简单的临时表.<br />
# 如果你不创建非常大的临时文件,将其放置到 swapfs/tmpfs 文件系统上也许比较好<br />
# 另一种选择是你也可以将其放置在独立的磁盘上.<br />
# 你可以使用&#8221;;&#8221;来放置多个路径<br />
# 他们会按照roud-robin方法被轮询使用.<br />
#tmpdir = /tmp</p>
<p># ***  复制有关的设置</p>
<p># 唯一的服务辨识号,数值位于 1 到 2^32-1之间.<br />
# 此值在master和slave上都需要设置.<br />
# 如果 &#8220;master-host&#8221; 没有被设置,则默认为1, 但是如果忽略此选项,MySQL不会作为master生效.<br />
server-id = 1</p>
<p># 复制的Slave (去掉master段的注释来使其生效)<br />
#<br />
# 为了配置此主机作为复制的slave服务器,你可以选择两种方法:<br />
#<br />
# 1) 使用 CHANGE MASTER TO 命令 (在我们的手册中有完整描述) -<br />
#    语法如下:<br />
#<br />
#    CHANGE MASTER TO MASTER_HOST=&lt;host&gt;, MASTER_PORT=&lt;port&gt;,<br />
#    MASTER_USER=&lt;user&gt;, MASTER_PASSWORD=&lt;password&gt; ;<br />
#<br />
#    你需要替换掉 &lt;host&gt;, &lt;user&gt;, &lt;password&gt; 等被尖括号包围的字段以及使用master的端口号替换&lt;port&gt; (默认3306).<br />
#<br />
#    例子:<br />
#<br />
#    CHANGE MASTER TO MASTER_HOST=&#8217;125.564.12.1&#8242;, MASTER_PORT=3306,<br />
#    MASTER_USER=&#8217;joe&#8217;, MASTER_PASSWORD=&#8217;secret&#8217;;<br />
#<br />
# 或者<br />
#<br />
# 2) 设置以下的变量. 不论如何, 在你选择这种方法的情况下, 然后第一次启动复制(甚至不成功的情况下,<br />
#     例如如果你输入错密码在master-password字段并且slave无法连接),<br />
#    slave会创建一个 master.info 文件,并且之后任何对于包含在此文件内的参数的变化都会被忽略<br />
#    并且由 master.info 文件内的内容覆盖, 除非你关闭slave服务, 删除 master.info 并且重启slave 服务.<br />
#    由于这个原因,你也许不想碰一下的配置(注释掉的) 并且使用 CHANGE MASTER TO (查看上面) 来代替<br />
#<br />
# 所需要的唯一id号位于 2 和 2^32 &#8211; 1之间<br />
# (并且和master不同)<br />
# 如果master-host被设置了.则默认值是2<br />
# 但是如果省略,则不会生效<br />
#server-id = 2<br />
#<br />
# 复制结构中的master &#8211; 必须<br />
#master-host = &lt;hostname&gt;<br />
#<br />
# 当连接到master上时slave所用来认证的用户名 &#8211; 必须<br />
#master-user = &lt;username&gt;<br />
#<br />
# 当连接到master上时slave所用来认证的密码 &#8211; 必须<br />
#master-password = &lt;password&gt;<br />
#<br />
# master监听的端口.<br />
# 可选 &#8211; 默认是3306<br />
#master-port = &lt;port&gt;</p>
<p># 使得slave只读.只有用户拥有SUPER权限和在上面的slave线程能够修改数据.<br />
# 你可以使用此项去保证没有应用程序会意外的修改slave而不是master上的数据<br />
#read_only</p>
<p>#*** MyISAM 相关选项</p>
<p># 关键词缓冲的大小, 一般用来缓冲MyISAM表的索引块.<br />
# 不要将其设置大于你可用内存的30%,<br />
# 因为一部分内存同样被OS用来缓冲行数据<br />
# 甚至在你并不使用MyISAM 表的情况下, 你也需要仍旧设置起 8-64M 内存由于它同样会被内部临时磁盘表使用.<br />
key_buffer_size = 32M</p>
<p># 用来做MyISAM表全表扫描的缓冲大小.<br />
# 当全表扫描需要时,在对应线程中分配.<br />
read_buffer_size = 2M</p>
<p># 当在排序之后,从一个已经排序好的序列中读取行时,行数据将从这个缓冲中读取来防止磁盘寻道.<br />
# 如果你增高此值,可以提高很多ORDER BY的性能.<br />
# 当需要时由每个线程分配<br />
read_rnd_buffer_size = 16M</p>
<p># MyISAM 使用特殊的类似树的cache来使得突发插入<br />
# (这些插入是,INSERT &#8230; SELECT, INSERT &#8230; VALUES (&#8230;), (&#8230;), &#8230;, 以及 LOAD DATA<br />
# INFILE) 更快. 此变量限制每个进程中缓冲树的字节数.<br />
# 设置为 0 会关闭此优化.<br />
# 为了最优化不要将此值设置大于 &#8220;key_buffer_size&#8221;.<br />
# 当突发插入被检测到时此缓冲将被分配.<br />
bulk_insert_buffer_size = 64M</p>
<p># 此缓冲当MySQL需要在 REPAIR, OPTIMIZE, ALTER 以及 LOAD DATA INFILE 到一个空表中引起重建索引时被分配.<br />
# 这在每个线程中被分配.所以在设置大值时需要小心.<br />
myisam_sort_buffer_size = 128M</p>
<p># MySQL重建索引时所允许的最大临时文件的大小 (当 REPAIR, ALTER TABLE 或者 LOAD DATA INFILE).<br />
# 如果文件大小比此值更大,索引会通过键值缓冲创建(更慢)<br />
myisam_max_sort_file_size = 10G</p>
<p># 如果被用来更快的索引创建索引所使用临时文件大于制定的值,那就使用键值缓冲方法.<br />
# 这主要用来强制在大表中长字串键去使用慢速的键值缓冲方法来创建索引.<br />
myisam_max_extra_sort_file_size = 10G</p>
<p># 如果一个表拥有超过一个索引, MyISAM 可以通过并行排序使用超过一个线程去修复他们.<br />
# 这对于拥有多个CPU以及大量内存情况的用户,是一个很好的选择.<br />
myisam_repair_threads = 1</p>
<p># 自动检查和修复没有适当关闭的 MyISAM 表.<br />
myisam_recover</p>
<p># 默认关闭 Federated<br />
skip-federated</p>
<p># *** BDB 相关选项 ***</p>
<p># 如果你运行的MySQL服务有BDB支持但是你不准备使用的时候使用此选项. 这会节省内存并且可能加速一些事.<br />
skip-bdb</p>
<p># *** INNODB 相关选项 ***</p>
<p># 如果你的MySQL服务包含InnoDB支持但是并不打算使用的话,<br />
# 使用此选项会节省内存以及磁盘空间,并且加速某些部分<br />
#skip-innodb</p>
<p># 附加的内存池被InnoDB用来保存 metadata 信息<br />
# 如果InnoDB为此目的需要更多的内存,它会开始从OS这里申请内存.<br />
# 由于这个操作在大多数现代操作系统上已经足够快, 你一般不需要修改此值.<br />
# SHOW INNODB STATUS 命令会显示当先使用的数量.<br />
innodb_additional_mem_pool_size = 16M</p>
<p># InnoDB使用一个缓冲池来保存索引和原始数据, 不像 MyISAM.<br />
# 这里你设置越大,你在存取表里面数据时所需要的磁盘I/O越少.<br />
# 在一个独立使用的数据库服务器上,你可以设置这个变量到服务器物理内存大小的80%<br />
# 不要设置过大,否则,由于物理内存的竞争可能导致操作系统的换页颠簸.<br />
# 注意在32位系统上你每个进程可能被限制在 2-3.5G 用户层面内存限制,<br />
# 所以不要设置的太高.<br />
innodb_buffer_pool_size = 2G</p>
<p># InnoDB 将数据保存在一个或者多个数据文件中成为表空间.<br />
# 如果你只有单个逻辑驱动保存你的数据,一个单个的自增文件就足够好了.<br />
# 其他情况下.每个设备一个文件一般都是个好的选择.<br />
# 你也可以配置InnoDB来使用裸盘分区 &#8211; 请参考手册来获取更多相关内容<br />
innodb_data_file_path = ibdata1:10M:autoextend</p>
<p># 设置此选项如果你希望InnoDB表空间文件被保存在其他分区.<br />
# 默认保存在MySQL的datadir中.<br />
#innodb_data_home_dir = &lt;directory&gt;</p>
<p># 用来同步IO操作的IO线程的数量. This value is<br />
# 此值在Unix下被硬编码为4,但是在Windows磁盘I/O可能在一个大数值下表现的更好.<br />
innodb_file_io_threads = 4</p>
<p># 如果你发现InnoDB表空间损坏, 设置此值为一个非零值可能帮助你导出你的表.<br />
# 从1开始并且增加此值知道你能够成功的导出表.<br />
#innodb_force_recovery=1</p>
<p># 在InnoDb核心内的允许线程数量.<br />
# 最优值依赖于应用程序,硬件以及操作系统的调度方式.<br />
# 过高的值可能导致线程的互斥颠簸.<br />
innodb_thread_concurrency = 16</p>
<p># 如果设置为1 ,InnoDB会在每次提交后刷新(fsync)事务日志到磁盘上,<br />
# 这提供了完整的ACID行为.<br />
# 如果你愿意对事务安全折衷, 并且你正在运行一个小的食物, 你可以设置此值到0或者2来减少由事务日志引起的磁盘I/O<br />
# 0代表日志只大约每秒写入日志文件并且日志文件刷新到磁盘.<br />
# 2代表日志写入日志文件在每次提交后,但是日志文件只有大约每秒才会刷新到磁盘上.<br />
innodb_flush_log_at_trx_commit = 1</p>
<p># 加速InnoDB的关闭. 这会阻止InnoDB在关闭时做全清除以及插入缓冲合并.<br />
# 这可能极大增加关机时间, 但是取而代之的是InnoDB可能在下次启动时做这些操作.<br />
#innodb_fast_shutdown</p>
<p># 用来缓冲日志数据的缓冲区的大小.<br />
# 当此值快满时, InnoDB将必须刷新数据到磁盘上.<br />
# 由于基本上每秒都会刷新一次,所以没有必要将此值设置的太大(甚至对于长事务而言)</p>
<p>innodb_log_buffer_size = 8M</p>
<p># 在日志组中每个日志文件的大小.<br />
# 你应该设置日志文件总合大小到你缓冲池大小的25%~100%<br />
# 来避免在日志文件覆写上不必要的缓冲池刷新行为.<br />
# 不论如何, 请注意一个大的日志文件大小会增加恢复进程所需要的时间.<br />
innodb_log_file_size = 256M</p>
<p># 在日志组中的文件总数.<br />
# 通常来说2~3是比较好的.<br />
innodb_log_files_in_group = 3</p>
<p># InnoDB的日志文件所在位置. 默认是MySQL的datadir.<br />
# 你可以将其指定到一个独立的硬盘上或者一个RAID1卷上来提高其性能<br />
#innodb_log_group_home_dir</p>
<p># 在InnoDB缓冲池中最大允许的脏页面的比例.<br />
# 如果达到限额, InnoDB会开始刷新他们防止他们妨碍到干净数据页面.<br />
# 这是一个软限制,不被保证绝对执行.<br />
innodb_max_dirty_pages_pct = 90</p>
<p># InnoDB用来刷新日志的方法.<br />
# 表空间总是使用双重写入刷新方法<br />
# 默认值是 &#8220;fdatasync&#8221;, 另一个是 &#8220;O_DSYNC&#8221;.<br />
#innodb_flush_method=O_DSYNC</p>
<p># 在被回滚前,一个InnoDB的事务应该等待一个锁被批准多久.<br />
# InnoDB在其拥有的锁表中自动检测事务死锁并且回滚事务.<br />
# 如果你使用 LOCK TABLES 指令, 或者在同样事务中使用除了InnoDB以外的其他事务安全的存储引擎<br />
# 那么一个死锁可能发生而InnoDB无法注意到.<br />
# 这种情况下这个timeout值对于解决这种问题就非常有帮助.<br />
innodb_lock_wait_timeout = 120</p>
<p>[mysqldump]<br />
# 不要在将内存中的整个结果写入磁盘之前缓存. 在导出非常巨大的表时需要此项<br />
quick</p>
<p>max_allowed_packet = 16M</p>
<p>[mysql]<br />
no-auto-rehash</p>
<p># 仅仅允许使用键值的 UPDATEs 和 DELETEs .<br />
#safe-updates</p>
<p>[isamchk]<br />
key_buffer = 512M<br />
sort_buffer_size = 512M<br />
read_buffer = 8M<br />
write_buffer = 8M</p>
<p>[myisamchk]<br />
key_buffer = 512M<br />
sort_buffer_size = 512M<br />
read_buffer = 8M<br />
write_buffer = 8M</p>
<p>[mysqlhotcopy]<br />
interactive-timeout</p>
<p>[mysqld_safe]<br />
# 增加每个进程的可打开文件数量.<br />
# 警告: 确认你已经将全系统限制设定的足够高!<br />
# 打开大量表需要将此值设高 j<br />
open-files-limit = 8192</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/489.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysql学习——char,varchar,text的比较与选择</title>
		<link>http://www.tisswb.com/archives/251.html</link>
		<comments>http://www.tisswb.com/archives/251.html#comments</comments>
		<pubDate>Wed, 04 Mar 2009 16:27:39 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=251</guid>
		<description><![CDATA[索的存储：
他们的存储方式和数据的检索方式都不一样。
数据的检索效率是：char&#62;varchar&#62;text
空间占用方面，要具体情况具体分析了。




CHAR(M)

<span class="readmore"><a href="http://www.tisswb.com/archives/251.html" title="mysql学习——char,varchar,text的比较与选择" target="_blank">阅读全文——共848字</a></span>]]></description>
			<content:encoded><![CDATA[<p>索的存储：</p>
<p>他们的存储方式和数据的检索方式都不一样。</p>
<p>数据的检索效率是：char&gt;varchar&gt;text</p>
<p>空间占用方面，要具体情况具体分析了。</p>
<table class="MsoNormalTable" style="mso-cellspacing: 1.5pt; mso-padding-alt: 0cm 0cm 0cm 0cm;" border="1" cellpadding="0">
<tbody>
<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes;">
<td style="background-color: transparent; border-color: #d4d0c8; padding: 0cm;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" align="left"><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US"><a onclick="tagshow(event, 'CHAR');" href="javascript:;" target="_self"><span style="text-decoration: underline;"><strong><span style="color: #000000;">CHAR</span></strong></span></a><span style="color: #000000;">(<em>M</em>)</span></span></p>
</td>
<td style="background-color: transparent; border-color: #d4d0c8; padding: 0cm;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" align="left"><span style="color: #000000;"><em><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US">M</span></em><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;">个字节，<span lang="EN-US">0 &lt;=<em>M</em>&lt;= 255</span></span></span></p>
</td>
</tr>
<tr style="mso-yfti-irow: 1;">
<td style="background-color: transparent; border-color: #d4d0c8; padding: 0cm;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" align="left"><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US"><a onclick="tagshow(event, 'VARCHAR');" href="javascript:;" target="_self"><span style="text-decoration: underline;"><strong><span style="color: #000000;">VARCHAR</span></strong></span></a><span style="color: #000000;">(<em>M</em>)</span></span></p>
</td>
<td style="background-color: transparent; border-color: #d4d0c8; padding: 0cm;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" align="left"><span style="color: #000000;"><em><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US">L</span></em><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US">+1</span><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;">个字节，其中<em><span lang="EN-US">L</span></em><span lang="EN-US">&lt;=<em>M</em></span>且<span lang="EN-US">0 &lt;=<em>M</em>&lt;= 65535</span></span></span></p>
</td>
</tr>
<tr style="mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="background-color: transparent; border-color: #d4d0c8; padding: 0cm;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" align="left"><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US"><a onclick="tagshow(event, 'TEXT');" href="javascript:;" target="_self"><span style="text-decoration: underline;"><strong><span style="color: #000000;">TEXT</span></strong></span></a></span></p>
</td>
<td style="background-color: transparent; border-color: #d4d0c8; padding: 0cm;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" align="left"><span style="color: #000000;"><em><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US">L</span></em><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;" lang="EN-US">+2</span><span style="font-size: 12pt; font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体;">个字节，其中<em><span lang="EN-US">L</span></em><span lang="EN-US">&lt; 2<sup>16</sup></span></span></span></p>
</td>
</tr>
</tbody>
</table>
<p>Char为定长，varchar，text为变长</p>
<p>Char在保存的时候，后面（右边）会用空格填充到指定的长度，在检索的时候后面的空格会去掉，所以检索出来的数据需要再用什么trim之类的函数去处理。(与sql server可能有些不同)</p>
<p>Varchar在保存的时候，不进行填充。当值保存和检索时尾部的空格仍保留。</p>
<p>TEXT列不能有默认值，存储或检索过程中，不存在大小写转换.</p>
<p>当存储的字符超过他们定义的长度时候，如果不是在sql服务器的严格模式下，都会自动截取合适的字段存储，而不会出现错误。但是，如果是中文的话同样要报错误：）比如定义char(4),然后insert (‘c哈哈&#8217;).<br />
注意一点的，Char，Varchar不像数值类型，有系统默认长度，所以必须在括号里定义长度，可以有默认值</p>
<p>text不可以写默认值，后面如果指定长度，不会报错误，但是这个长度是不起作用的，意思就是你插入数据的时候，超过你指定的长度还是可以正常插入（严格模式下没有测试 ：））</p>
<p>存储计算：</p>
<p>在使用UTF8字符集的时候，手册上是这样描叙的：</p>
<p>·基本拉丁字母、数字和标点符号使用一个字节。</p>
<p>·大多数的欧洲和中东手写字母适合两个字节序列：扩展的拉丁字母（包括发音符号、长音符号、重音符号、低音符号和其它音符）、西里尔字母、希腊语、亚美尼亚语、希伯来语、阿拉伯语、叙利亚语和其它语言。</p>
<p>·韩语、中文和日本象形文字使用三个字节序列。</p>
<p>但是，经过我的测试，中文汉字使用2个字节序列。</p>
<p> </p>
<p>使用的一般规则：</p>
<p>1.经常变化的字段用char</p>
<p>2.知道固定长度的用char</p>
<p>3.尽量用varchar</p>
<p>4.超过255字节的只能用varchar或者text</p>
<p>5.能用varchar的地方不用text</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/251.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php+mysql数据库编程学习小细节</title>
		<link>http://www.tisswb.com/archives/87.html</link>
		<comments>http://www.tisswb.com/archives/87.html#comments</comments>
		<pubDate>Tue, 22 Jul 2008 16:55:58 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web技术]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=87</guid>
		<description><![CDATA[好多年没写程序了,现在对于php+mysql数据库编程都已经生疏了,最近又重新拾了起来,当然一开始就出现遇见了这样那样的问题.
1.乱码问题
按照以前的习惯写了代码如下；
$link = mysql_connect(&#8216;localhost&#8217;,'hgqy&#8217;,'hgqy&#8217;);　//连接数据服务器
mysql_select_db(&#8216;hgqy&#8217; , $link);　　//选择数据库
$sql = &#8220;select * from `plug＿qiye` where cpname = &#8216;济南&#8217;&#8221;;
$query = mysql_query($sql) or die(&#8220;查询失败&#8221; . mysql_error());　//执行数据查询语句
$row = mysql_fetch_array($query);
<span class="readmore"><a href="http://www.tisswb.com/archives/87.html" title="php+mysql数据库编程学习小细节" target="_blank">阅读全文——共522字</a></span>]]></description>
			<content:encoded><![CDATA[<p>好多年没写程序了,现在对于php+mysql数据库编程都已经生疏了,最近又重新拾了起来,当然一开始就出现遇见了这样那样的问题.<br />
1.<strong>乱码问题</strong><br />
按照以前的习惯写了代码如下；</p>
<blockquote><p>$link = mysql_connect(&#8216;localhost&#8217;,'hgqy&#8217;,'hgqy&#8217;);　//连接数据服务器</p>
<p>mysql_select_db(&#8216;hgqy&#8217; , $link);　　//选择数据库</p>
<p>$sql = &#8220;select * from `plug＿qiye` where cpname = &#8216;济南&#8217;&#8221;;</p>
<p>$query = mysql_query($sql) or die(&#8220;查询失败&#8221; . mysql_error());　//执行数据查询语句</p>
<p>$row = mysql_fetch_array($query);</p>
<p>foreach ($row as $i){<br />
　　　echo $i ;<br />
}</p></blockquote>
<p>输出的时候问题来了，没有任何输出，测试了所有我知道的方法，也没找到原因，于是就开始把 cpname = &#8216;济南&#8217;换成了id = 。终于找到问题了，输出的文字部分变成了乱码，傻了眼。<br />
在查阅资料后发现，原来在选择数据库后，需要再做一步</p>
<blockquote><p>mysql_query(&#8220;set names utf8&#8243;) ;　　//设定编码，utf8和gbk可以自行调整。</p></blockquote>
<p>这回终于可以正确输出了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/87.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL常用命令及基本操作总结</title>
		<link>http://www.tisswb.com/archives/86.html</link>
		<comments>http://www.tisswb.com/archives/86.html#comments</comments>
		<pubDate>Tue, 22 Jul 2008 03:10:41 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=86</guid>
		<description><![CDATA[MySQL常用操作基本操作，以下都是MySQL5.0下测试通过首先说明下，记住在每个命令结束时加上；（分号）
1.导出整个数据库
mysqldump -u 用户名 -p &#8211;default-character-set=latin1 数据库名 &#62; 导出的文件名(数据库默认编码是latin1)
mysqldump -u wcnc -p smgp_apps_wcnc &#62; wcnc.sql
2.导出一个表
mysqldump -u 用户名 -p 数据库名 表名&#62; 导出的文件名
mysqldump -u wcnc -p smgp_apps_wcnc users&#62; wcnc_users.sql
3.导出一个数据库结构
mysqldump -u wcnc -p -d –add-drop-table smgp_apps_wcnc &#62;d:wcnc_db.sql
-d 没有数据 –add-drop-table 在每个create语句之前增加一个drop table
<span class="readmore"><a href="http://www.tisswb.com/archives/86.html" title="MySQL常用命令及基本操作总结" target="_blank">阅读全文——共2455字</a></span>]]></description>
			<content:encoded><![CDATA[<p>MySQL常用操作基本操作，以下都是MySQL5.0下测试通过首先说明下，记住在每个命令结束时加上；（分号）<br />
<strong>1.导出整个数据库<br />
</strong>mysqldump -u 用户名 -p &#8211;default-character-set=latin1 数据库名 &gt; 导出的文件名(数据库默认编码是latin1)<br />
mysqldump -u wcnc -p smgp_apps_wcnc &gt; wcnc.sql<br />
<strong>2.导出一个表</strong><br />
mysqldump -u 用户名 -p 数据库名 表名&gt; 导出的文件名<br />
mysqldump -u wcnc -p smgp_apps_wcnc users&gt; wcnc_users.sql<br />
<strong>3.导出一个数据库结构<br />
</strong>mysqldump -u wcnc -p -d –add-drop-table smgp_apps_wcnc &gt;d:wcnc_db.sql<br />
-d 没有数据 –add-drop-table 在每个create语句之前增加一个drop table<br />
<strong>4.导入数据库<br />
</strong>常用source 命令<br />
进入mysql数据库控制台，<br />
如mysql -u root -p<br />
mysql&gt;use 数据库<br />
然后使用source命令，后面参数为脚本文件(如这里用到的.sql)<br />
mysql&gt;source d:wcnc_db.sql</p>
<p><strong>一、启动与退出<br />
</strong>1、进入MySQL：启动MySQL Command Line Client（MySQL的DOS界面），直接输入安装时的密码即可。此时的提示符是：mysql&gt;<br />
2、退出MySQL：<strong>quit</strong>或<strong>exit</strong><br />
<strong>二、库操作<br />
</strong>1、、创建数据库<br />
命令：<strong>create database</strong> &lt;数据库名&gt;<br />
例如：建立一个名为xhkdb的数据库<br />
mysql&gt; create database xhkdb;<br />
2、显示所有的数据库<br />
命令：<strong>show databases</strong> （注意：最后有个s）<br />
mysql&gt; <strong>show databases</strong>;<br />
3、删除数据库<br />
命令：<strong>drop database</strong> &lt;数据库名&gt;<br />
例如：删除名为 xhkdb的数据库<br />
mysql&gt; <strong>drop database</strong> xhkdb;<br />
4、连接数据库<br />
命令： <strong>use</strong> &lt;数据库名&gt;<br />
例如：如果xhkdb数据库存在，尝试存取它：<br />
mysql&gt; <strong>use</strong> xhkdb;<br />
屏幕提示：Database changed<br />
5、当前选择（连接）的数据库<br />
mysql&gt; <strong>select database()</strong>;<br />
6、当前数据库包含的表信息：<br />
mysql&gt; <strong>show tables</strong>; （注意：最后有个s）</p>
<p><strong>三、表操作，操作之前应连接某个数据库</strong><br />
1、建表<br />
命令：<strong>create table</strong> &lt;表名&gt; ( &lt;字段名1&gt; &lt;类型1&gt; [,..&lt;字段名n&gt; &lt;类型n&gt;]);</p>
<p>mysql&gt; <strong>create table</strong> MyClass(<br />
&gt; id int(4) not null <strong>primary key auto_increment</strong>,<br />
&gt; name char(20) not null,<br />
&gt; sex int(4) not null <strong>default</strong> &#8217;0&#8242;,<br />
&gt; degree double(16,2));<br />
2、获取表结构<br />
命令： <strong>desc</strong> 表名，或者<strong>show columns from</strong> 表名</p>
<p>mysql&gt; <strong>desc</strong> MyClass;<br />
mysql&gt; <strong>show columns from MyClass</strong>;<br />
3、删除表<br />
命令：<strong>drop table</strong> &lt;表名&gt;<br />
例如：删除表名为 MyClass 的表<br />
mysql&gt; <strong>drop table</strong> MyClass;<br />
4、插入数据<br />
命令：<strong>insert into</strong> &lt;表名&gt; [( &lt;字段名1&gt;[,..&lt;字段名n &gt; ])] <strong>values</strong> ( 值1 )[, ( 值n )]<br />
例如，往表 MyClass中插入二条记录, 这二条记录表示：编号为1的名为Tom的成绩为96.45, 编号为2 的名为Joan 的成绩为82.99， 编号为3 的名为Wang 的成绩为96.5.<br />
mysql&gt; <strong>insert into</strong> MyClass <strong>values</strong>(1,&#8217;Tom&#8217;,96.45),(2,&#8217;Joan&#8217;,82.99), (2,&#8217;Wang&#8217;, 96.59);<br />
5、查询表中的数据<br />
1)、查询所有行<br />
命令： <strong>select</strong> &lt;字段1，字段2，&#8230;&gt; <strong>from</strong> &lt; 表名 &gt; <strong>where</strong> &lt; 表达式 &gt;<br />
例如：查看表 MyClass 中所有数据<br />
mysql&gt; select * from MyClass;<br />
2）、查询前几行数据<br />
例如：查看表 MyClass 中前2行数据<br />
mysql&gt; <strong>select * from</strong> MyClass <strong>order by</strong> id <strong>limit</strong> 0,2;<br />
6、删除表中数据<br />
命令：<strong>delete from</strong> 表名 <strong>where</strong> 表达式<br />
例如：删除表 MyClass中编号为1 的记录<br />
mysql&gt; <strong>delete from</strong> MyClass <strong>where</strong> id=1;<br />
7、修改表中数据：<strong>update</strong> 表名 <strong>set</strong> 字段=新值,… <strong>where</strong> 条件<br />
mysql&gt; <strong>update</strong> MyClass <strong>set</strong> name=&#8217;Mary&#8217; <strong>where</strong> id=1;<br />
7、在表中增加字段：<br />
命令：<strong>alter table</strong> 表名 <strong>add</strong>字段 类型 其他;<br />
例如：在表MyClass中添加了一个字段passtest，类型为int(4)，默认值为0<br />
mysql&gt; <strong>alter table</strong> MyClass <strong>add</strong> passtest <strong>int</strong>(4) <strong>default</strong> &#8217;0&#8242;<br />
8、更改表名：<br />
命令：<strong>rename table</strong> 原表名 <strong>to</strong> 新表名;<br />
例如：在表MyClass名字更改为YouClass<br />
mysql&gt; <strong>rename table</strong> MyClass <strong>to</strong> YouClass;<br />
<strong>更新字段内容</strong><br />
update 表名 set 字段名 = 新内容<br />
update 表名 set 字段名 = replace(字段名,&#8217;旧内容&#8217;,'新内容&#8217;);</p>
<p>文章前面加入4个空格<br />
update article set content=concat(&#8216;　　&#8217;,content);</p>
<p><strong>字段类型<br />
</strong>1．INT[(M)] 型： 正常大小整数类型<br />
2．DOUBLE[(M,D)] [ZEROFILL] 型： 正常大小(双精密)浮点数字类型<br />
3．DATE 日期类型：支持的范围是1000-01-01到9999-12-31。MySQL以YYYY-MM-DD格式来显示DATE值，但是允许你使用字符串或数字把值赋给DATE列<br />
4．CHAR(M) 型：定长字符串类型，当存储时，总是是用空格填满右边到指定的长度<br />
5．BLOB TEXT类型，最大长度为65535(2^16-1)个字符。<br />
6．VARCHAR型：变长字符串类型</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/86.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL查询的性能优化</title>
		<link>http://www.tisswb.com/archives/85.html</link>
		<comments>http://www.tisswb.com/archives/85.html#comments</comments>
		<pubDate>Tue, 22 Jul 2008 01:07:28 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=85</guid>
		<description><![CDATA[　　在程序设计中同样存在一个“二八原则”，即20%的代码用去了80%的时间。数据库应用程序的开发亦然。数据库应用程序的优化，重点在于SQL的执行效率。而数据查询优化的重点，则是使得数据库服务器少从磁盘中读数据以及顺序读页而不是非顺序读页。

       查询是数据库技术中最常用的操作。查询操作的过程比较简单，首先从客户端发出查询的SQL语句，数据库服务端在接收到由客户端发来的SQL语句后，执行这条SQL语句，然后将查询到的结果返回给客户端。虽然过程很简单，但不同的查询方式和数据库设置，对查询的性能将会有很在的影响。因此，本文就在 MySQL中常用的查询优化技术进行讨论。讨论的内容如：
1 通过查询缓冲提高查询速度
2 MySQL对查询的自动优化
3 基于索引的排序
4 不可达查询的检测
5 使用各种查询选择来提高性能
一、 通过查询缓冲提高查询速度
    一般我们使用SQL语句进行查询时，数据库服务器每次在收到客户端发来SQL后，都会执行这条SQL语句。但当在一定间隔内（如1分钟内），接到完全一样的 SQL语句，也同样执行它。虽然这样可以保证数据的实时性，但在大多数时候，数据并不要求完全的实时，也就是说可以有一定的延时。如果是这样的话，在短时间内执行完全一样的SQL就有些得不偿失。
<span class="readmore"><a href="http://www.tisswb.com/archives/85.html" title="MySQL查询的性能优化" target="_blank">阅读全文——共4733字</a></span>]]></description>
			<content:encoded><![CDATA[<div class="excerpt">　　在程序设计中同样存在一个“二八原则”，即20%的代码用去了80%的时间。数据库应用程序的开发亦然。数据库应用程序的优化，重点在于SQL的执行效率。而数据查询优化的重点，则是使得数据库服务器少从磁盘中读数据以及顺序读页而不是非顺序读页。</div>
<div class="tbody">
<p>       查询是数据库技术中最常用的操作。查询操作的过程比较简单，首先从客户端发出查询的SQL语句，数据库服务端在接收到由客户端发来的SQL语句后，执行这条SQL语句，然后将查询到的结果返回给客户端。虽然过程很简单，但不同的查询方式和数据库设置，对查询的性能将会有很在的影响。因此，本文就在 MySQL中常用的查询优化技术进行讨论。讨论的内容如：</p>
<p>1 通过查询缓冲提高查询速度<br />
2 MySQL对查询的自动优化<br />
3 基于索引的排序<br />
4 不可达查询的检测<br />
5 使用各种查询选择来提高性能</p>
<p><strong>一、 通过查询缓冲提高查询速度</strong></p>
<p><strong>    </strong>一般我们使用SQL语句进行查询时，数据库服务器每次在收到客户端发来SQL后，都会执行这条SQL语句。但当在一定间隔内（如1分钟内），接到完全一样的 SQL语句，也同样执行它。虽然这样可以保证数据的实时性，但在大多数时候，数据并不要求完全的实时，也就是说可以有一定的延时。如果是这样的话，在短时间内执行完全一样的SQL就有些得不偿失。</p>
<p><strong>    </strong>幸好MySQL为我们提供了查询缓冲的功能（只能在MySQL 4.0.1及以上版本使用查询缓冲）。我们可以通过查询缓冲在一定程度上提高查询性能。</p>
<p><strong>    </strong>我们可以通过在MySQL安装目录中的my.ini文件设置查询缓冲。设置也非常简单，只需要将query_cache_type设为1即可。在设置了这个属性后，MySQL在执行任何SELECT语句之前，都会在它的缓冲区中查询是否在相同的SELECT语句被执行过，如果有，并且执行结果没有过期，那么就直接取查询结果返回给客户端。但在写SQL语句时注意，MySQL的查询缓冲是区分大小写的。如下列的两条SELECT语句：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">from</span><span style="color: #000000;"> TABLE1<br />
</span><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1<br />
</span></div>
<p>    上面的两条SQL语句对于查询缓冲是完全不同的SELECT。而且查询缓冲并不自动处理空格，因此，在写SQL语句时，应尽量减少空格的使用，尤其是在SQL首和尾的空格（因为，查询缓冲并不自动截取首尾空格）。</p>
<p><strong>    </strong>虽然不设置查询缓冲，有时可能带来性能上的损失，但有一些SQL语句需要实时地查询数据，或者并不经常使用（可能一天就执行一两次）。这样就需要把缓冲关了。当然，这可以通过设置query_cache_type的值来关闭查询缓冲，但这就将查询缓冲永久地关闭了。在MySQL 5.0中提供了一种可以临时关闭查询缓冲的方法：SQL_NO_CACHE。 <strong>  </p>
<p></strong></p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> SQL_NO_CACHE field1, field2 </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1<br />
</span></div>
<p>    以上的SQL语句由于使用了SQL_NO_CACHE，因此，不管这条SQL语句是否被执行过，服务器都不会在缓冲区中查找，每次都会执行它。</p>
<p><strong>    </strong>我们还可以将my.ini中的query_cache_type设成2，这样只有在使用了SQL_CACHE后，才使用查询缓冲。</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> SQL_CALHE </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1<br />
</span></div>
<p><strong>二、MySQL对查询的自动优化</strong></p>
<p>    索引对于数据库是非常重要的。在查询时可以通过索引来提高性能。但有时使用索引反而会降低性能。我们可以看如下的SALES表：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">CREATE</span><span style="color: #000000;"> </span><span style="color: #0000ff;">TABLE</span><span style="color: #000000;"> SALES<br />
(<br />
   ID </span><span style="font-weight: bold; color: #000000;">INT</span><span style="color: #000000;">(</span><span style="font-weight: bold; color: #800000;">10</span><span style="color: #000000;">) UNSIGNED </span><span style="color: #808080;">NOT</span><span style="color: #000000;"> </span><span style="color: #0000ff;">NULL</span><span style="color: #000000;"> AUTO_INCREMENT,<br />
   NAME </span><span style="font-weight: bold; color: #000000;">VARCHAR</span><span style="color: #000000;">(</span><span style="font-weight: bold; color: #800000;">100</span><span style="color: #000000;">) </span><span style="color: #808080;">NOT</span><span style="color: #000000;"> </span><span style="color: #0000ff;">NULL</span><span style="color: #000000;">,<br />
   PRICE </span><span style="font-weight: bold; color: #000000;">FLOAT</span><span style="color: #000000;"> </span><span style="color: #808080;">NOT</span><span style="color: #000000;"> </span><span style="color: #0000ff;">NULL</span><span style="color: #000000;">,<br />
   SALE_COUNT </span><span style="font-weight: bold; color: #000000;">INT</span><span style="color: #000000;"> </span><span style="color: #808080;">NOT</span><span style="color: #000000;"> </span><span style="color: #0000ff;">NULL</span><span style="color: #000000;">,<br />
   SALE_DATE DATE </span><span style="color: #808080;">NOT</span><span style="color: #000000;"> </span><span style="color: #0000ff;">NULL</span><span style="color: #000000;">,<br />
</span><span style="color: #0000ff;">PRIMARY</span><span style="color: #000000;"> </span><span style="color: #0000ff;">KEY</span><span style="color: #000000;">(ID)，<br />
</span><span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> (NAME)，<br />
  </span><span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> (SALE_DATE)<br />
)</span></div>
<p>   假设这个表中保存了数百万条数据，而我们要查询商品号为1000的商品在2004年和2005年的平均价格。我们可以写如下的SQL语句：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #ff00ff;">AVG</span><span style="color: #000000;">(PRICE) </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SALES<br />
</span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> ID </span><span style="color: #808080;">=</span><span style="color: #000000;"> </span><span style="font-weight: bold; color: #800000;">1000</span><span style="color: #000000;"> </span><span style="color: #808080;">AND</span><span style="color: #000000;"> SALE_DATE </span><span style="color: #808080;">BETWEEN</span><span style="color: #000000;"> </span><span style="color: #ff0000;">&#8216;</span><span style="color: #ff0000;">2004-01-01</span><span style="color: #ff0000;">&#8216;</span><span style="color: #000000;"> </span><span style="color: #808080;">AND</span><span style="color: #000000;"> </span><span style="color: #ff0000;">&#8216;</span><span style="color: #ff0000;">2005-12-31</span><span style="color: #ff0000;">&#8216;</span><span style="color: #000000;">;</span></div>
<p>    如果这种商品的数量非常多，差不多占了SALES表的记录的50%或更多。那么使用SALE_DATE字段上索引来计算平均数就有些慢。因为如果使用索引，就得对索引进行排序操作。当满足条件的记录非常多时（如占整个表的记录的50%或更多的比例），速度会变慢，这样还不如对整个表进行扫描。因此， MySQL会自动根据满足条件的数据占整个表的数据的比例自动决定是否使用索引进行查询。</p>
<p>    对于MySQL来说，上述的查询结果占整个表的记录的比例是30%左右时就不使用索引了，这个比例是MySQL的开发人员根据他们的经验得出的。然而，实际的比例值会根据所使用的数据库引擎不同而不同。</p>
<p><strong>三、 基于索引的排序</strong></p>
<p>    MySQL的弱点之一是它的排序。虽然MySQL可以在1秒中查询大约15,000条记录，但由于MySQL在查询时最多只能使用一个索引。因此，如果 WHERE条件已经占用了索引，那么在排序中就不使用索引了，这将大大降低查询的速度。我们可以看看如下的SQL语句：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SALES </span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> NAME </span><span style="color: #808080;">=</span><span style="color: #000000;"> “name” </span><span style="color: #0000ff;">ORDER</span><span style="color: #000000;"> </span><span style="color: #0000ff;">BY</span><span style="color: #000000;"> SALE_DATE </span><span style="color: #0000ff;">DESC</span><span style="color: #000000;">;</span></div>
<p>    在以上的SQL的WHERE子句中已经使用了NAME字段上的索引，因此，在对SALE_DATE进行排序时将不再使用索引。为了解决这个问题，我们可以对SALES表建立复合索引：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">ALTER</span><span style="color: #000000;"> </span><span style="color: #0000ff;">TABLE</span><span style="color: #000000;"> SALES </span><span style="color: #0000ff;">DROP</span><span style="color: #000000;"> </span><span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> NAME, </span><span style="color: #0000ff;">ADD</span><span style="color: #000000;"> </span><span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> (NAME, SALE_DATE)<br />
</span></div>
<p>    这样再使用上述的SELECT语句进行查询时速度就会大副提升。但要注意，在使用这个方法时，要确保WHERE子句中没有排序字段，在上例中就是不能用 SALE_DATE进行查询，否则虽然排序快了，但是SALE_DATE字段上没有单独的索引，因此查询又会慢下来。</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SALES </span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> NAME </span><span style="color: #808080;">=</span><span style="color: #000000;"> “name1” </span><span style="color: #808080;">AND</span><span style="color: #000000;"> NAME </span><span style="color: #808080;">=</span><span style="color: #000000;"> “name2”</span></div>
<p>    以上的查询语句要查找NAME既等于name1又等于name2的记录。很明显，这是一个不可达的查询，WHERE条件一定是假。MySQL在执行SQL 语句之前，会先分析WHERE条件是否是不可达的查询，如果是，就不再执行这条SQL语句了。为了验证这一点。我们首先对如下的SQL使用EXPLAIN 进行测试：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #000000;">EXPLAIN </span><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SALES </span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> NAME </span><span style="color: #808080;">=</span><span style="color: #000000;"> “name1”</span></div>
<p>    上面的查询是一个正常的查询，我们可以看到使用EXPLAIN返回的执行信息数据中table项是SALES。这说明MySQL对SALES进行操作了。再看看下面的语句：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #000000;">EXPLAIN </span><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SALES </span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> NAME </span><span style="color: #808080;">=</span><span style="color: #000000;"> “name1” </span><span style="color: #808080;">AND</span><span style="color: #000000;"> NAME </span><span style="color: #808080;">=</span><span style="color: #000000;"> “name2”</span></div>
<p>   我们可以看到，table项是空，这说明MySQL并没有对SALES表进行操作。</p>
<p><strong>五、 使用各种查询选择来提高性能<br />
</strong><br />
<strong>    </strong>SELECT语句除了正常的使用外，MySQL还为我们提供了很多可以增强查询性能的选项。如上面介绍的用于控制查询缓冲的SQL_NO_CACHE和SQL_CACHE就是其中两个选项。在这一部分，我将介绍几个常用的查询选项。</p>
<p><strong>    </strong>1. STRAIGHT_JOIN：强制连接顺序</p>
<p><strong>    </strong>当我们将两个或多个表连接起来进行查询时，我们并不用关心MySQL先连哪个表，后连哪个表。而这一切都是由MySQL内部通过一系列的计算、评估，最后得出的一个连接顺序决定的。如下列的SQL语句中，TABLE1和TABLE2并不一定是谁连接谁：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> TABLE1.FIELD1, TABLE2.FIELD2 </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1 ,TABLE2 </span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> …<br />
</span></div>
<p>    如果开发人员需要人为地干预连接的顺序，就得使用STRAIGHT_JOIN关键字，如下列的SQL语句：</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> TABLE1.FIELD1, TABLE2.FIELD2 </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1 STRAIGHT_JOIN TABLE2 </span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> …</span></div>
<p>由上面的SQL语句可知，通过STRAIGHT_JOIN强迫MySQL按TABLE1、TABLE2的顺序连接表。如果你认为按自己的顺序比MySQL推荐的顺序进行连接的效率高的话，就可以通过STRAIGHT_JOIN来确定连接顺序。</p>
<p>    2. 干预索引使用，提高性能</p>
<p>    在上面已经提到了索引的使用。一般情况下，在查询时MySQL将自己决定是否使用索引，使用哪一个索引。但在一些特殊情况下，我们希望MySQL只使用一个或几个索引，或者不希望使用某个索引。这就需要使用MySQL的控制索引的一些查询选项。</p>
<p>   (1) 限制使用索引的范围</p>
<p>    有时我们在数据表里建立了很多索引，当MySQL对索引进行选择时，这些索引都在考虑的范围内。但有时我们希望MySQL只考虑几个索引，而不是全部的索引，这就需要用到USE INDEX对查询语句进行设置。</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1 </span><span style="color: #0000ff;">USE</span><span style="color: #000000;"> </span><span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> (FIELD1, FIELD2) …</span></div>
<p>从以上SQL语句可以看出，无论在TABLE1中已经建立了多少个索引，MySQL在选择索引时，只考虑在FIELD1和FIELD2上建立的索引。</p>
<p>    (2) 限制不使用索引的范围</p>
<p>   如果我们要考虑的索引很多，而不被使用的索引又很少时，可以使用IGNORE INDEX进行反向选取。在上面的例子中是选择被考虑的索引，而使用IGNORE INDEX是选择不被考虑的索引。</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1 IGNORE </span><span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> (FIELD1, FIELD2) …</span></div>
<p>    在上面的SQL语句中，TABLE1表中只有FIELD1和FIELD2上的索引不被使用。</p>
<p>    (3) 强迫使用某一个索引</p>
<p>    上面的两个例子都是给MySQL提供一个选择，也就是说MySQL并不一定要使用这些索引。而有时我们希望MySQL必须要使用某一个索引（由于 MySQL在查询时只能使用一个索引，因此只能强迫MySQL使用一个索引）。这就需要使用FORCE INDEX来完成这个功能。</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1 FORCE </span><span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> (FIELD1) …</span></div>
<p>以上的SQL语句只使用建立在FIELD1上的索引，而不使用其它字段上的索引。</p>
<p>    3. 使用临时表提供查询性能</p>
<p>    当我们查询的结果集中的数据比较多时，可以通过SQL_BUFFER_RESULT.选项强制将结果集放到临时表中，这样就可以很快地释放MySQL的表锁（这样其它的SQL语句就可以对这些记录进行查询了），并且可以长时间地为客户端提供大记录集。</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #000000;">  </span><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> SQL_BUFFER_RESULT </span><span style="color: #808080;">*</span><span style="color: #000000;"> </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1 </span><span style="color: #0000ff;">WHERE</span><span style="color: #000000;"> …<br />
</span></div>
<p>    和SQL_BUFFER_RESULT.选项类似的还有SQL_BIG_RESULT，这个选项一般用于分组或DISTINCT关键字，这个选项通知MySQL，如果有必要，就将查询结果放到临时表中，甚至在临时表中进行排序。</p>
<div style="padding-right: 5px; padding-left: 4px; font-size: 13px; padding-bottom: 4px; width: 98%; padding-top: 4px; background-color: #eeeeee; border: #cccccc 1px solid;"><span style="color: #0000ff;">SELECT</span><span style="color: #000000;"> SQL_BUFFER_RESULT FIELD1, </span><span style="color: #ff00ff;">COUNT</span><span style="color: #000000;">(</span><span style="color: #808080;">*</span><span style="color: #000000;">) </span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TABLE1 </span><span style="color: #0000ff;">GROUP</span><span style="color: #000000;"> </span><span style="color: #0000ff;">BY</span><span style="color: #000000;"> FIELD1</span></div>
<p><strong>六、 结论</strong></p>
<p>    在程序设计中同样存在一个“二八原则”，即20%的代码用去了80%的时间。数据库应用程序的开发亦然。数据库应用程序的优化，重点在于SQL的执行效率。而数据查询优化的重点，则是使得数据库服务器少从磁盘中读数据以及顺序读页而不是非顺序读页。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/85.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>千万级记录的Discuz论坛导致MySQL CPU 100%的优化笔记</title>
		<link>http://www.tisswb.com/archives/49.html</link>
		<comments>http://www.tisswb.com/archives/49.html#comments</comments>
		<pubDate>Thu, 15 May 2008 01:09:45 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=49</guid>
		<description><![CDATA[　　2007年3月，我写过一篇文章《解决一个 MySQL 服务器进程 CPU 占用 100%的技术笔记》，谈到自己在解决一个拥有 60 万条记录的 MySQL 数据库访问时，导致 MySQL CPU 占用 100% 的经过。在解决问题完成优化(optimize)之后，我发现 Discuz 论坛也存在这个问题，当时稍微提了一下：
发现此主机运行了几个 Discuz 的论坛程序， Discuz论坛的好几个表也存在着这个问题。于是顺手一并解决，cpu占用再次降下来了。
　　前几天，一位朋友通过这篇文章找到了我，说他就是运行最新的 discuz 版本，MySQL 占用 CPU 100%，导致系统假死，每天都要重启好几次，花了一个多月的时间一直没有解决，希望我帮忙一下。经过检查，他的这个论坛最重要的几个表中，目前 cdb_members 表，有记录 6.2 万；cdb_threads 表，有记录 11万；cdb_posts表，有记录 1740 万；所有数据表的记录加起来，超过 2000 万；数据库的大小超过 1GB。经过半天的调试，总算完成了 discuz 论坛优化，于是将其解决经过记录在这篇文章 http://www.xiaohui.com/dev/server/20070701-discuz-mysql-cpu-100-optimize.htm 中。
<span class="readmore"><a href="http://www.tisswb.com/archives/49.html" title="千万级记录的Discuz论坛导致MySQL CPU 100%的优化笔记" target="_blank">阅读全文——共7835字</a></span>]]></description>
			<content:encoded><![CDATA[<p>　　2007年3月，我写过一篇文章《解决一个 MySQL 服务器进程 CPU 占用 100%的技术笔记》，谈到自己在解决一个拥有 60 万条记录的 MySQL 数据库访问时，导致 <strong>MySQL CPU 占用 100% </strong>的经过。在解决问题完成优化(optimize)之后，我发现 <strong>Discuz 论坛</strong>也存在这个问题，当时稍微提了一下：</p>
<blockquote><p>发现此主机运行了几个 Discuz 的论坛程序， Discuz论坛的好几个表也存在着这个问题。于是顺手一并解决，cpu占用再次降下来了。</p></blockquote>
<p>　　前几天，一位朋友通过这篇文章找到了我，说他就是运行最新的 discuz 版本，MySQL 占用 CPU 100%，导致系统假死，每天都要重启好几次，花了一个多月的时间一直没有解决，希望我帮忙一下。经过检查，他的这个论坛最重要的几个表中，目前 cdb_members 表，有记录 6.2 万；cdb_threads 表，<span style="color: #ff0000;">有记录 11万</span>；cdb_posts表，<span style="color: #ff0000;">有记录 1740 万</span>；所有数据表的记录加起来，<span style="color: #ff0000;">超过 2000 万</span>；数据库的大小超过 1GB。经过半天的调试，总算完成了 <strong>discuz 论坛优化</strong>，于是将其解决经过记录在这篇文章 <a href="http://www.xiaohui.com/dev/server/20070701-discuz-mysql-cpu-100-optimize.htm">http://www.xiaohui.com/dev/server/20070701-discuz-mysql-cpu-100-optimize.htm</a> 中。</p>
<p> </p>
<p>　　2007年3月我发现 discuz 论坛的数据库结构设计有一些疏忽，有许多查询子句的条件比较，都没有建立 <strong>Index 索引</strong>。当时我所检查的那个数据表，记录只有几千条，因此对 <strong>CPU 负荷</strong>不大。现在这个数据库表，上千万的记录检索，可以想象，如果数据表结构设计不规范，没有提供索引，所耗费的时间是一个恐怖的数字。有关 MySQL 建立索引的重要性，可以参见我的这篇文章底部的说明：<a href="http://www.xiaohui.com/weekly/20070307.htm" target="_blank">http://www.xiaohui.com/weekly/20070307.htm</a></p>
<p>　　为了调试方便，我从 dizcus 的官网下载了其最新的 Dizcus! 5.5.0 论坛程序．</p>
<p>　　我首先检查了 my.ini 的参数配置，一切正常。进入 MySQL 的命令行，调用 show processlist 语句，查找<strong>负荷最重的 SQL 语句</strong>，结合 Discuz 论坛的源码，发现有以下语句导致 CPU 上升：</p>
<pre><tt>mysql&gt; show processlist;
+-----+------+----------------+---------+---------+------+------------+---------
-----------------------------------------------------------------+
| Id  | User | Host           | db      | Command | Time | State      | Info
                                                                 |
+-----+------+----------------+---------+---------+------+------------+---------
-----------------------------------------------------------------+
| 363 | root | localhost:1393 | history | Query   |    0 | statistics | SELECT C
OUNT(*) FROM cdb_pms WHERE msgfromid=11212 AND folder='outbox' |
+-----+------+----------------+---------+---------+------+------------+---------
</tt></pre>
<p>　　检查 cdb_pms 表的结构：</p>
<pre><tt>mysql&gt; show columns from cdb_pms;
+-----------+------------------------+------+-----+---------+----------------+
| Field     | Type                   | Null | Key | Default | Extra          |
+-----------+------------------------+------+-----+---------+----------------+
| pmid      | int(10) unsigned       | NO   | PRI | NULL    | auto_increment |
| msgfrom   | varchar(15)            | NO   |     |         |                |
| msgfromid | mediumint(8) unsigned  | NO   | MUL | 0       |                |
| msgtoid   | mediumint(8) unsigned  | NO   | MUL | 0       |                |
<span style="color: #0000ff;">| folder    | enum('inbox','outbox') | NO   |     | inbox   |                |</span>
| new       | tinyint(1)             | NO   |     | 0       |                |
| subject   | varchar(75)            | NO   |     |         |                |
| dateline  | int(10) unsigned       | NO   |     | 0       |                |
| message   | text                   | NO   |     |         |                |
| delstatus | tinyint(1) unsigned    | NO   |     | 0       |                |
+-----------+------------------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
</tt></pre>
<p>　　这条语句: <span style="color: #ff0000;">WHERE msgfromid=11212 AND folder=&#8217;outbox&#8217;</span>，我们看到，在 cdb_pms 表中，msgfromid 字段已经建立了索引，但是，folder 字段并没有。目前这个表已经有记录 7823 条。显然，这会对查询造成一定影响。于是为其建立索引：</p>
<pre><tt>mysql&gt; ALTER TABLE `cdb_pms` ADD INDEX ( `folder` );
Query OK, 7823 rows affected (1.05 sec)
Records: 7823  Duplicates: 0  Warnings: 0
</tt></pre>
<p>　　继续检查：</p>
<pre><tt>mysql&gt; show processlist;
+------+------+----------------+---------+---------+------+------------+--------
--------------------------------------------------------------------------------
--------------+
| Id   | User | Host           | db      | Command | Time | State      | Info

              |
+------+------+----------------+---------+---------+------+------------+--------
--------------------------------------------------------------------------------
--------------+
              |
| 1583 | root | localhost:2616 | history | Query   |    0 | statistics | SELECT
t.tid, t.closed, f.*, ff.*  , f.fid AS fid
                        FROM cdb_threads t
                        INNER JOIN cdb_forums f |
+------+------+----------------+---------+---------+------+------------+--------
--------------------------------------------------------------------------------
--------------+
1 rows in set (0.00 sec)
</tt></pre>
<p>　　这条 SQL 语句是针对最重要的数据表 cdb_threads 进行操作的，由于 show processlist 没有将这条 SQL 语句全部显示完全，经对比 Discuz 论坛的源码，此SQL语句的原型位于 common.inc.php 的 Line 283，内容如下：</p>
<pre><tt>$query = $db-&gt;query("SELECT t.tid, t.closed,".(defined('SQL_ADD_THREAD') ?
    SQL_ADD_THREAD : '')." f.*, ff.* $accessadd1 $modadd1, f.fid AS fid
    FROM {$tablepre}threads t
    INNER JOIN {$tablepre}forums f ON f.fid=t.fid
    LEFT JOIN {$tablepre}forumfields ff ON ff.fid=f.fid $accessadd2 $modadd2
    WHERE t.tid='$tid'".($auditstatuson ? '' : " AND t.displayorder&gt;=0")." LIMIT 1");
</tt></pre>
<p>　　经检查，数据表 cdb_threads, 并没有针对 displayorder 字段建立索引。在 discuz 论坛中，displayorder字段多次参与了 Where 子句的比较。于是为其建立索引：</p>
<pre><tt>mysql&gt; ALTER TABLE `cdb_threads` ADD INDEX ( `displayorder` );
Query OK, 110330 rows affected (2.36 sec)
Records: 110330  Duplicates: 0  Warnings: 0
</tt></pre>
<p>　　此时 cpu 已经轻微下降了一部分。</p>
<p> </p>
<p>　　继续检查，发现 下面这条 discuz 的 SQL 语句，也导致负荷增加，这条语句位于 rss.php 程序中的第 142 行。</p>
<pre><tt>    $query = $db-&gt;query("SELECT t.tid, t.readperm, t.price, t.author, t.dateline, t.subject, p.message
    FROM {$tablepre}threads t
    LEFT JOIN {$tablepre}posts p ON p.tid=t.tid AND p.first=1
    WHERE t.fid='$fid' AND t.displayorder&gt;=0
    ORDER BY t.dateline DESC LIMIT $num");
</tt></pre>
<p>　　在这个 Order by 子句中，用到了 cdb_threads 表中的 dataline 字段。这个字段是用来存储 unixtime 的时间戳，在整个论坛程序中，大部分时候数据的排序也是基于这个字段，竟然没有建立索引。于是加上：</p>
<pre><tt>mysql&gt; ALTER TABLE `cdb_threads` ADD INDEX ( `dateline` );
Query OK, 110330 rows affected (12.27 sec)
Records: 110330  Duplicates: 0  Warnings: 0
</tt></pre>
<p>　　查找占用 CPU 高负茶的 SQL 语句，是一件麻烦而又枯燥的事，需要一条一条排除、分析。后面的工作，都是依此类推，经过检查，共查出有八处地方，需要增加索引，如果你也碰到了 discuz 论坛导致 cpu 占用 100% 的情况，可以直接将下列语句复制过去，在 mysql 的命令行下执行即可：</p>
<pre><tt>ALTER TABLE `cdb_pms` ADD INDEX ( `folder` );
ALTER TABLE `cdb_threads` ADD INDEX ( `displayorder` );
ALTER TABLE `cdb_threads` ADD INDEX ( `dateline` );
ALTER TABLE `cdb_threads` ADD INDEX ( `closed` );
ALTER TABLE `cdb_threadsmod` ADD INDEX ( `dateline` );
ALTER TABLE `cdb_sessions` ADD INDEX ( `invisible` );
ALTER TABLE `cdb_forums` ADD INDEX ( `type` );
ALTER TABLE `cdb_forums` ADD INDEX ( `displayorder` );
</tt></pre>
<p>　　注意：“cdb_” 是 discuz 论坛的默认数据表前缀。如果你的表名前缀不是 “cdb_”，则应该改成你对应的表名。例如：my_threads, my_pms 等等。</p>
<p> </p>
<p> </p>
<p>　　完成这些结构的优化之后，整个系统的 CPU 负荷在 10%~20%左右震荡，问题解决。</p>
<p> </p>
<p>　　我很奇怪，设计数据库结构，是一个数据库开发人员的基本功，discuz 论坛好歹也是一个发展了有六七年的论坛了，为何数据库结构设计得如此糟糕？我想也许有如下三个原因：</p>
<p> </p>
<ul>
<li>数据库开发人员设计时本身的疏忽</li>
<li>故意留下的缺陷，当普通论坛没有上数量级的记录时，不会感觉到这个问题，当数据量增大（例如千万级），此问题突现，以便针对用户提供个性服务收取服务费．呵呵，估且以最大的恶意来猜测此事，玩笑而已，不必当真。:)　</li>
<li>另一个可能就是用户的论坛是从低版本升级而来，程序升了级，但数据结构也许没有做相应的更新</li>
</ul>
<p> </p>
<p> </p>
<h2>附1: 补充笔记 2007-07-09</h2>
<p> </p>
<p>　　今天查看网站日志的 reffer, 发现在 discuz 的官方论坛上，有人就此文引起了一些争论。discuz 的管理员和管理员有如下言论：</p>
<blockquote><p><strong>引用自 cnteacher</strong>:</p>
<p>恰恰相反，discuz 的优化措施和数据库的索引是按照大规模论坛设计的。</p>
<p>TO 一楼：数据库结构的设计都是按照程序应用来进行的，使用任何非Discuz! 标准版本以外的代码和程序，或者变更标准数据结构，均可能遇到不可预知的各种问题。</p>
<p><strong>引用自 童虎</strong>:</p>
<p>你们可以看看xxxxx, xxxx之类的比较大型的网站，这种网站使用dz论坛都没有问题，说明dz标准程序是没有问题，出现楼主说的情况，多半属于服务器或者安装一些插件造成的</p></blockquote>
<p>　　显然将问题推给插件的原因是不正确的．举个简单的例子：在最新的 discuz 5.5.0 forumdisplay.php 第183 行，有如下语句：</p>
<pre><tt>$query = $db-&gt;query("SELECT uid, groupid, username, invisible,
  lastactivity, action FROM {$tablepre}sessions
  WHERE $guestwhere fid='$fid' AND <span style="color: #ff0000;">invisible</span>=0");
</tt></pre>
<p>　　这里的 invisible 并没有建立索引。本文中有评论认为 session 表是内存表, 速度会很快。理论是如此。不过我在 show processlist 中，观察到上面这条语句占用了大量 CPU， 所以也将其一并加上了 index。cdb_threads 中的 closed 等字段, 也多次参与 where 运算, 也没有建立索引。这些运算的语句, 是 discuz 自己的程序中的。</p>
<p> </p>
<p> </p>
<h2>附2: 补充笔记 2007-11-11</h2>
<p>　　自从这篇笔记发表以来，在我的这篇文章的评论、以及我的联系消息中，就经常收到许多下面两种类型的评论和邮件：一、许多技术人员批评我胡说八道、Dizcus 论坛不需要做优化或者不能乱建索引的；二、许多使用Dizcus 的站长找我“冰天雪地裸体跪求”解决他们的 CPU 占用 100% 的问题。</p>
<p> </p>
<p>　　关于 <strong>MySQL 数据库优化技术</strong>上的争论，我的观点再次声明如下：</p>
<p> </p>
<ol>
<li>技术上的争论是可以放开了讨论的。而我的水平也确实只是半瓶子水，对数据库的理论知识也只懂这么点，牛牛们的批评，我虚心接心，非常感谢。但是，评论里的批评不要上升到人身攻击，否则，我的地盘我作主，直接删除。我喜欢听好话，请大家理解一个三○男人的这点可怜的虚荣心。:) 
<p> </li>
<li>数据库的优化，要涉及到的方方面面很多。关说理论是没有用的，得靠事实说话。一个千万级数据库的实例优化说明不了问题，两个千万级的数据库优化也许还说明不了问题，但我相信，三个、四个、五个总是可以说明问题的，－－截止到 2007.11.09，我已经帮助朋友优化过五个记录数超过 1000 万的 discuz 论坛了。优化之前，cpu 都是 100%；优化之后，cpu 降到 30%~40% 左右。我想<span style="color: #ff0000;">事实胜于雄辩</span>。</li>
</ol>
<p> </p>
<p>　　关于找我帮忙<strong>解决数据库优化</strong>的评论和邮件，答复如下:</p>
<p> </p>
<ol>
<li>数据库的优化，不同的版本有不同的实际情况，优化一个 database，短则三两小时，慢则半天一天。请大家理解一个三○老男人养家的压力，我的精力有限，不可能一一帮到。 
<p> </li>
<li><span style="color: #aa0000;">对于个人网站，我可以在周六周日的空余时间内帮忙。请事先与我联系好。</span> 
<p> </li>
<li><span style="color: #aa0000;">对于商业网站，嗯嗯，自觉点，请带价格与我联系，或者直接安排美女请我吃饭，否则免谈。:)</span></li>
</ol>
<p> </p>
<p> </p>
<h2>附3: 补充笔记 2007-11-17: 关于装有首页四格插件的 dz 论坛导致 MySQL 占用 大量CPU 的分析</h2>
<p>　　今天手机巴士的站长( http://bbs.sj84.com )找到我，他的基于 Discuz 的论坛，也存在 CPU 占用 100% 的问题，服务器从 Win 2003 换到　CentOS，内存 2G, CPU 1.86G,　数据：cdb_threads 4 万，cdb_posts 96 万，cdb_members 35 万，已经按我上面文章所说的优化过索引。按说这个配置足够运行论坛了，但问题一直得不到解决。</p>
<p> </p>
<p>　　经过调试，将慢查询的结果 dump 到 /usr/local/mysql/var/localhost-slow.log，运行 /usr/local/mysql/bin/mysqldumpslow /usr/local/mysql/var/localhost-slow.log 查看，结合 show processlist 命令，发现慢查询集中在下列语句:</p>
<pre><tt>SELECT t.*, f.name FROM cdb_threads t, cdb_forums f WHERE
t.fid&lt;&gt;'S'
AND f.fid=t.fid
AND f.fid NOT IN (N,N,N,N)
AND t.closed NOT LIKE 'S'
AND t.replies !=N
AND t.displayorder&gt;=N
ORDER BY t.views DESC LIMIT N, N</tt></pre>
<p>　　然而搜索 Dizcus 论坛的源码，并没有找到这行代码。怀疑是插件的原因。经查，论坛装了首页四格的插件，这行语句位于 include/toplist.php 中: 仔细检查这行代码，发现存在许多性能或语法规范上的问题：</p>
<p> </p>
<p> </p>
<ol>
<li><strong>AND t.closed NOT LIKE &#8216;S&#8217;</strong>:t.closed 是数值字段，不应该用 LIKE &#8216;S&#8217; 的形式参与比较。　</li>
<li><strong>ORDER BY t.views:</strong> t.views 在 dizcus 的原始数据表中，是没有做索引的。</li>
<li><strong>SELECT t.*</strong>: 这种写法，是不被推荐的。如果要选择某个表内的所有字段，最好是按实全部写出来，例如：select t.aa, t.bb, t.cc, t.dd, &#8230;</li>
<li><strong>WHERE　t.fid &lt;&gt; &#8216;S&#8217;</strong>: t.fid 是数值型字段，不应该写成 字符比较的形式。这个对性能影响不大，是个编程规范的问题。</li>
<li>&#8230;.</li>
</ol>
<p> </p>
<p>　　toplist.php 的其他三条 sql 语句，都存在这些问题。如果要针对他的 sql 语句去优化 MySQL 结构，会带来不良的后果；如果直接改他的 toplist.php 程序，如果站长以后升级　toplist.php 又怕带来不兼容问题。于是我建议他干脆关闭首页四格插件。</p>
<p>　　关闭首页四格插件之后，CPU 降到 18% 左右震荡，表现非常良好。</p>
<p>　　如果是我来写首页四格的程序，我不会采用这种方案，我会用定时15分钟或30分钟查询一次数据库，将结果写入 TXT 文件或临时表，然后程序再从中读取，效率会高许多。</p>
<p>　　结论：</p>
<p> </p>
<ol>
<li>如果装了插件的论坛碰到　CPU 高负荷时，建议关掉插件再评估性能。</li>
<li>慎装第三方插件。没事不要乱插。:)</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/49.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>解决一个 MySQL 服务器进程 CPU 占用 100%的技术笔记</title>
		<link>http://www.tisswb.com/archives/48.html</link>
		<comments>http://www.tisswb.com/archives/48.html#comments</comments>
		<pubDate>Thu, 15 May 2008 01:00:00 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=48</guid>
		<description><![CDATA[　MYSQL CPU 占用 100% 的现象描述
 
　　早上帮朋友一台服务器解决了 Mysql cpu 占用 100% 的问题。稍整理了一下，将经验记录在这篇文章里：《解决一个 MySQL 服务器进程 CPU 占用 100%的技术笔记》
 
　　朋友主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下。此主机有10个左右的 database, 分别给十个网站调用。据朋友测试，导致 mysqld-nt.exe cpu 占用奇高的是网站A，一旦在 IIS 中将此网站停止服务，CPU 占用就降下来了。一启用，则马上上升。
 
 
　MYSQL CPU 占用 100% 的解决过程
　　今天早上仔细检查了一下。目前此网站的七日平均日 IP 为2000，PageView 为 3万左右。网站A 用的 database 目前有39个表，记录数 60.1万条，占空间 45MB。按这个数据，MySQL 不可能占用这么高的资源。
<span class="readmore"><a href="http://www.tisswb.com/archives/48.html" title="解决一个 MySQL 服务器进程 CPU 占用 100%的技术笔记" target="_blank">阅读全文——共3646字</a></span>]]></description>
			<content:encoded><![CDATA[<h2>　MYSQL CPU 占用 100% 的现象描述</h2>
<p> </p>
<p>　　早上帮朋友一台服务器解决了 <strong>Mysql cpu 占用 100%</strong> 的问题。稍整理了一下，将经验记录在这篇文章里：《<strong>解决一个 MySQL 服务器进程 CPU 占用 100%的技术笔记</strong>》</p>
<p> </p>
<p>　　朋友主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (<strong>mysqld-nt.exe</strong>) CPU 占用率总为 100% 高居不下。此主机有10个左右的 database, 分别给十个网站调用。据朋友测试，导致 mysqld-nt.exe cpu 占用奇高的是网站A，一旦在 IIS 中将此网站停止服务，CPU 占用就降下来了。一启用，则马上上升。</p>
<p> </p>
<p> </p>
<h2>　MYSQL CPU 占用 100% 的解决过程</h2>
<p>　　今天早上仔细检查了一下。目前此网站的七日平均日 IP 为2000，PageView 为 3万左右。网站A 用的 database 目前有39个表，记录数 60.1万条，占空间 45MB。按这个数据，MySQL 不可能占用这么高的资源。</p>
<p> </p>
<p>　　于是在服务器上运行命令，将 mysql 当前的<strong>环境变量</strong>输出到文件 output.txt：</p>
<pre><tt>d:webmysql&gt; mysqld.exe --help &gt;output.txt</tt></pre>
<p>　　发现 tmp_table_size 的值是默认的 32M，于是修改 My.ini, 将 tmp_table_size 赋值到 200M:</p>
<pre><tt>d:webmysql&gt; notepad c:windowsmy.ini
[mysqld]
tmp_table_size=200M
</tt></pre>
<p>　　然后重启 MySQL 服务。CPU 占用有轻微下降，以前的CPU 占用波形图是 100% 一根直线，现在则在 97%~100%之间起伏。这表明<strong>调整 tmp_table_size 参数</strong>对 <strong>MYSQL 性能提升有改善作用</strong>。但问题还没有完全解决。</p>
<p> </p>
<p> </p>
<p>　　于是进入 mysql 的 shell 命令行，调用 <strong>show processlist</strong>, 查看当前 mysql 使用频繁的 sql 语句：</p>
<pre><tt>mysql&gt; show processlist;
</tt></pre>
<p>　　反复调用此命令(每秒刷两次），发现网站 A 的两个 SQL 语句经常在 process list 中出现，其语法如下：</p>
<pre><tt>SELECT t1.pid, t2.userid, t3.count, t1.date
FROM _mydata AS t1
LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid
LEFT JOIN _mydata_body AS t2 ON t1.pid=t3.pid
ORDER BY t1.pid
LIMIT 0,15
</tt></pre>
<p>　　调用 <strong>show columns</strong> 检查这三个表的结构 :</p>
<pre><tt>mysql&gt; show columns from _myuser;
mysql&gt; show columns from _mydata;
mysql&gt; show columns from _mydata_body;
</tt></pre>
<p>　　终于发现了问题所在：_mydata 表，只根据 pid 建立了一个 primary key，但并没有为 userid 建立索引。而在这个 SQL 语句的第一个 <strong>LEFT JOIN ON</strong> 子句中：</p>
<pre><tt>LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid</tt></pre>
<p>　　_mydata 的 userid 被参与了条件比较运算。于是我为给 _mydata 表根据字段 userid 建立了一个索引：</p>
<pre><tt>mysql&gt; ALTER TABLE `_mydata` ADD INDEX ( `userid` )</tt></pre>
<p>　　建立此索引之后，CPU 马上降到了 80% 左右。看到找到了问题所在，于是检查另一个反复出现在 show processlist 中的 sql 语句：</p>
<pre><tt>SELECT COUNT(*)
FROM _mydata AS t1, _mydata_key AS t2
WHERE t1.pid=t2.pid and t2.keywords = '孔雀'
</tt></pre>
<p>　　经检查 _mydata_key 表的结构，发现它只为 pid 建了了 primary key, 没有为 keywords 建立 index。_mydata_key 目前有 33 万条记录，在没有索引的情况下对33万条记录进行文本检索匹配，不耗费大量的 cpu 时间才怪。看来就是针对这个表的检索出问题了。于是同样为 _mydata_key 表根据字段 keywords 加上索引:</p>
<pre><tt>mysql&gt; ALTER TABLE `_mydata_key` ADD INDEX ( `keywords` )</tt></pre>
<p>　　建立此索引之后，CPU立刻降了下来，在 50%~70%之间震荡。</p>
<p> </p>
<p> </p>
<p>　　再次调用 show prosslist，网站A 的sql 调用就很少出现在结果列表中了。但发现此主机运行了几个 Discuz 的论坛程序， Discuz 论坛的好几个表也存在着这个问题。于是顺手一并解决，cpu占用再次降下来了。(<strong>2007.07.09 附注</strong>：关于 discuz 论坛的具体优化过程，我后来另写了一篇文章，详见：<a href="http://www.xiaohui.com/dev/server/20070701-discuz-mysql-cpu-100-optimize.htm" target="_blank">千万级记录的 Discuz! 论坛导致 MySQL CPU 100% 的 优化笔记 http://www.xiaohui.com/dev/server/20070701-discuz-mysql-cpu-100-optimize.htm</a>)</p>
<p> </p>
<p> </p>
<h2>　解决 MYSQL CPU 占用 100% 的经验总结</h2>
<p>　 http://www.xiaohui.com/weekly/20070307.htm</p>
<p> </p>
<p> </p>
<p> </p>
<ol>
<li><strong>增加 tmp_table_size 值</strong>。mysql 的配置文件中，<strong>tmp_table_size</strong> 的默认大小是 32M。如果一张临时表超出该大小，MySQL产生一个 <strong>The table tbl_name is full</strong> 形式的错误，如果你做很多高级 GROUP BY 查询，<strong>增加 tmp_table_size 值</strong>。 这是 mysql 官方关于此选项的解释：  <br />
<blockquote><p><strong>tmp_table_size</strong></p>
<p>This variable determines the maximum size for a temporary table in memory. If the table becomes too large, a MYISAM table is created on disk. Try to avoid temporary tables by optimizing the queries where possible, but where this is not possible, try to ensure temporary tables are always stored in memory. Watching the processlist for queries with temporary tables that take too long to resolve can give you an early warning that tmp_table_size needs to be upped. Be aware that memory is also allocated per-thread. An example where upping this worked for more was a server where I upped this from 32MB (the default) to 64MB with immediate effect. The quicker resolution of queries resulted in less threads being active at any one time, with all-round benefits for the server, and available memory.</p></blockquote>
<p> </li>
<li><strong>对 WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX</strong>。索引被用来快速找出在一个列上用一特定值的行。没有索引，MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大，花费时间越多。如果表对于查询的列有一个索引，MySQL能快速到达一个位置去搜寻到数据文件的中间，没有必要考虑所有数据。如果一个表有1000行，这比顺序读取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。 根据 mysql 的开发文档:<br />
<blockquote><p><strong>索引 index 用于</strong>：</p>
<ul>
<li>快速找出匹配一个WHERE子句的行</li>
<li>当执行联结(JOIN)时，从其他表检索行。</li>
<li>对特定的索引列找出MAX()或MIN()值</li>
<li>如果排序或分组在一个可用键的最左面前缀上进行(例如，ORDER BY key_part_1,key_part_2)，排序或分组一个表。如果所有键值部分跟随DESC，键以倒序被读取。</li>
<li>在一些情况中，一个查询能被优化来检索值，不用咨询数据文件。如果对某些表的所有使用的列是数字型的并且构成某些键的最左面前缀，为了更快，值可以从索引树被检索出来。假定你发出下列SELECT语句：
<pre><tt>mysql&gt; SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;</tt></pre>
<p>如果一个多列索引存在于col1和col2上，适当的行可以直接被取出。如果分开的单行列索引存在于col1和col2上，优化器试图通过决定哪个索引将找到更少的行并来找出更具限制性的索引并且使用该索引取行。 </li>
</ul>
</blockquote>
<p> </li>
</ol>
<p>　　开发人员做 SQL 数据表设计的时候，一定要通盘考虑清楚。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/48.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LAMP系统性能调优(3): MySQL 服务器调优</title>
		<link>http://www.tisswb.com/archives/26.html</link>
		<comments>http://www.tisswb.com/archives/26.html#comments</comments>
		<pubDate>Tue, 01 Apr 2008 16:04:20 +0000</pubDate>
		<dc:creator>笨二十一</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web技术]]></category>
		<category><![CDATA[Web服务器]]></category>
		<category><![CDATA[服务器]]></category>
		<category><![CDATA[LAMP]]></category>

		<guid isPermaLink="false">http://www.tisswb.cn/?p=26</guid>
		<description><![CDATA[有 3 种方法可以加快 MySQL 服务器的运行速度，效率从低到高依次为：

替换有问题的硬件。
对 MySQL 进程的设置进行调优。
对查询进行优化。

替换有问题的硬件通常是我们的第一考虑，主要原因是数据库会占用大量资源。不过这种解决方案也就仅限于此了。实际上，您通常可以让中央处理器（CPU）或磁盘速度加倍，也可以让内存增大 4 到 8 倍。
第二种方法是对 MySQL 服务器（也称为 mysqld）进行调优。对这个进程进行调优意味着适当地分配内存，并让 mysqld 了解将会承受何种类型的负载。加快磁盘运行速度不如减少所需的磁盘访问次数。类似地，确保 MySQL 进程正确操作就意味着它花费在服务查询上的时间要多于花费在处理后台任务（如处理临时磁盘表或打开和关闭文件）上的时间。对 mysqld 进行调优是本文的重点。
最好的方法是确保查询已经进行了优化。这意味着对表应用了适当的索引，查询是按照可以充分利用 MySQL 功能的方式来编写的。尽管本文并没有包含查询调优方面的内容（很多著作中已经针对这个主题进行了探讨），不过它会配置 mysqld 来报告可能需要进行调优的查询。
<span class="readmore"><a href="http://www.tisswb.com/archives/26.html" title="LAMP系统性能调优(3): MySQL 服务器调优" target="_blank">阅读全文——共7891字</a></span>]]></description>
			<content:encoded><![CDATA[<p>有 3 种方法可以加快 MySQL 服务器的运行速度，效率从低到高依次为：</p>
<ol>
<li>替换有问题的硬件。</li>
<li>对 MySQL 进程的设置进行调优。</li>
<li>对查询进行优化。</li>
</ol>
<p>替换有问题的硬件通常是我们的第一考虑，主要原因是数据库会占用大量资源。不过这种解决方案也就仅限于此了。实际上，您通常可以让中央处理器（CPU）或磁盘速度加倍，也可以让内存增大 4 到 8 倍。</p>
<p>第二种方法是对 MySQL 服务器（也称为 <code>mysqld</code>）进行调优。对这个进程进行调优意味着适当地分配内存，并让 <code>mysqld</code> 了解将会承受何种类型的负载。加快磁盘运行速度不如减少所需的磁盘访问次数。类似地，确保 MySQL 进程正确操作就意味着它花费在服务查询上的时间要多于花费在处理后台任务（如处理临时磁盘表或打开和关闭文件）上的时间。对 <code>mysqld</code> 进行调优是本文的重点。</p>
<p>最好的方法是确保查询已经进行了优化。这意味着对表应用了适当的索引，查询是按照可以充分利用 MySQL 功能的方式来编写的。尽管本文并没有包含查询调优方面的内容（很多著作中已经针对这个主题进行了探讨），不过它会配置 <code>mysqld</code> 来报告可能需要进行调优的查询。</p>
<p>虽然已经为这些任务指派了次序，但是仍然要注意硬件和 <code>mysqld</code> 的设置以利于适当地调优查询。机器速度慢也就罢了，我曾经见过速度很快的机器在运行设计良好的查询时由于负载过重而失败，因为 <code>mysqld</code> 被大量繁忙的工作所占用而不能服务查询。<a name="N100C3"><span class="atitle">记录慢速查询</span></a></p>
<p>在一个 SQL 服务器中，数据表都是保存在磁盘上的。索引为服务器提供了一种在表中查找特定数据行的方法，而不用搜索整个表。当必须要搜索整个表时，就称为<em>表扫描</em>。通常来说，您可能只希望获得表中数据的一个子集，因此全表扫描会浪费大量的磁盘 I/O，因此也就会浪费大量时间。当必须对数据进行连接时，这个问题就更加复杂了，因为必须要对连接两端的多行数据进行比较。</p>
<p>当然，表扫描并不总是会带来问题；有时读取整个表反而会比从中挑选出一部分数据更加有效（服务器进程中查询规划器用来作出这些决定）。如果索引的使用效率很低，或者根本就不能使用索引，则会减慢查询速度，而且随着服务器上的负载和表大小的增加，这个问题会变得更加显著。执行时间超过给定时间范围的查询就称为<em>慢速查询</em>。</p>
<p>您可以配置 <code>mysqld</code> 将这些慢速查询记录到适当命名的慢速查询日志中。管理员然后会查看这个日志来帮助他们确定应用程序中有哪些部分需要进一步调查。清单 1 给出了要启用慢速查询日志需要在 my.cnf 中所做的配置。<br />
<a name="listing1"><strong>清单 1. 启用 MySQL 慢速查询日志</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">[mysqld] ; enable the slow query log, default 10 seconds log-slow-queries ; log queries taking longer than 5 seconds long_query_time = 5 ; log queries that don&#8217;t use indexes even if they take less than long_query_time ; MySQL 4.1 and newer only log-queries-not-using-indexes</td>
</tr>
</tbody>
</table>
<p> </p>
<p>这三个设置一起使用，可以记录执行时间超过 5 秒和没有使用索引的查询。请注意有关 <code>log-queries-not-using-indexes</code> 的警告：您必须使用 MySQL 4.1 或更高版本。慢速查询日志都保存在 MySQL 数据目录中，名为 <em>hostname</em>-slow.log。如果希望使用一个不同的名字或路径，可以在 my.cnf 中使用 <code>log-slow-queries = /new/path/to/file</code> 实现此目的。</p>
<p>阅读慢速查询日志最好是通过 <code>mysqldumpslow</code> 命令进行。指定日志文件的路径，就可以看到一个慢速查询的排序后的列表，并且还显示了它们在日志文件中出现的次数。一个非常有用的特性是 <code>mysqldumpslow</code> 在比较结果之前，会删除任何用户指定的数据，因此对同一个查询的不同调用被计为一次；这可以帮助找出需要工作量最多的查询。<a name="N100FF"><span class="atitle">对查询进行缓存</span></a></p>
<p>很多 LAMP 应用程序都严重依赖于数据库，但却会反复执行相同的查询。每次执行查询时，数据库都必须要执行相同的工作 —— 对查询进行分析，确定如何执行查询，从磁盘中加载信息，然后将结果返回给客户机。MySQL 有一个特性称为<em>查询缓存</em>，它将（后面会用到的）查询结果保存在内存中。在很多情况下，这会极大地提高性能。不过，问题是查询缓存在默认情况下是禁用的。</p>
<p>将 <code>query_cache_size = 32M</code> 添加到 /etc/my.conf 中可以启用 32MB 的查询缓存。</p>
<p><a name="N10112"><span class="smalltitle"><strong><span style="font-size: small; font-family: Arial;">监视查询缓存</span></strong></span></a></p>
<p>在启用查询缓存之后，重要的是要理解它是否得到了有效的使用。MySQL 有几个可以查看的变量，可以用来了解缓存中的情况。清单 2 给出了缓存的状态。</p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">mysql&gt; SHOW STATUS LIKE &#8216;qcache%&#8217;; +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+ | Variable_name | Value | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+ | Qcache_free_blocks | 5216 | | Qcache_free_memory | 14640664 | | Qcache_hits | 2581646882 | | Qcache_inserts | 360210964 | | Qcache_lowmem_prunes | 281680433 | | Qcache_not_cached | 79740667 | | Qcache_queries_in_cache | 16927 | | Qcache_total_blocks | 47042 | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+ 8 rows in set (0.00 sec)</td>
</tr>
</tbody>
</table>
<p> </p>
<p>这些项的解释如表 1 所示。<br />
<a name="table1"><strong>表 1. MySQL 查询缓存变量</strong></a></p>
<table class="data-table-1" border="0" cellspacing="0" cellpadding="0" width="80%" summary="Timers">
<tbody>
<tr>
<th>变量名</th>
<th>说明</th>
</tr>
<tr>
<td><code>Qcache_free_blocks</code></td>
<td>缓存中相邻内存块的个数。数目大说明可能有碎片。<code>FLUSH QUERY CACHE</code> 会对缓存中的碎片进行整理，从而得到一个空闲块。</td>
</tr>
<tr>
<td><code>Qcache_free_memory</code></td>
<td>缓存中的空闲内存。</td>
</tr>
<tr>
<td><code>Qcache_hits</code></td>
<td>每次查询在缓存中命中时就增大。</td>
</tr>
<tr>
<td><code>Qcache_inserts</code></td>
<td>每次插入一个查询时就增大。命中次数除以插入次数就是不中比率；用 1 减去这个值就是命中率。在上面这个例子中，大约有 87% 的查询都在缓存中命中。</td>
</tr>
<tr>
<td><code>Qcache_lowmem_prunes</code></td>
<td>缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看；如果这个数字在不断增长，就表示可能碎片非常严重，或者内存很少。（上面的 <code>free_blocks</code> 和 <code>free_memory</code> 可以告诉您属于哪种情况）。</td>
</tr>
<tr>
<td><code>Qcache_not_cached</code></td>
<td>不适合进行缓存的查询的数量，通常是由于这些查询不是 <code>SELECT</code> 语句。</td>
</tr>
<tr>
<td><code>Qcache_queries_in_cache</code></td>
<td>当前缓存的查询（和响应）的数量。</td>
</tr>
<tr>
<td><code>Qcache_total_blocks</code></td>
<td>缓存中块的数量。</td>
</tr>
</tbody>
</table>
<p>通常，间隔几秒显示这些变量就可以看出区别，这可以帮助确定缓存是否正在有效地使用。运行 <code>FLUSH STATUS</code> 可以重置一些计数器，如果服务器已经运行了一段时间，这会非常有帮助。</p>
<p>使用非常大的查询缓存，期望可以缓存所有东西，这种想法非常诱人。由于 <code>mysqld</code> 必须要对缓存进行维护，例如当内存变得很低时执行剪除，因此服务器可能会在试图管理缓存时而陷入困境。作为一条规则，如果 <code>FLUSH QUERY CACHE</code> 占用了很长时间，那就说明缓存太大了。</p>
<p><a name="N101CB"><span class="atitle">强制限制</span></a></p>
<p>您可以在 <code>mysqld</code> 中强制一些限制来确保系统负载不会导致资源耗尽的情况出现。清单 3 给出了 my.cnf 中与资源有关的一些重要设置。<br />
<a name="listing3"><strong>清单 3. MySQL 资源设置</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">set-variable=max_connections=500 set-variable=wait_timeout=10 max_connect_errors = 100</td>
</tr>
</tbody>
</table>
<p> </p>
<p>连接最大个数是在第一行中进行管理的。与 Apache 中的 <code>MaxClients</code> 类似，其想法是确保只建立服务允许数目的连接。要确定服务器上目前建立过的最大连接数，请执行 <code>SHOW STATUS LIKE 'max_used_connections'</code>。</p>
<p>第 2 行告诉 <code>mysqld</code> 终止所有空闲时间超过 10 秒的连接。在 LAMP 应用程序中，连接数据库的时间通常就是 Web 服务器处理请求所花费的时间。有时候，如果负载过重，连接会挂起，并且会占用连接表空间。如果有多个交互用户或使用了到数据库的持久连接，那么将这个值设低一点并不可取！</p>
<p>最后一行是一个安全的方法。如果一个主机在连接到服务器时有问题，并重试很多次后放弃，那么这个主机就会被锁定，直到 <code>FLUSH HOSTS</code> 之后才能运行。默认情况下，10 次失败就足以导致锁定了。将这个值修改为 100 会给服务器足够的时间来从问题中恢复。如果重试 100 次都无法建立连接，那么使用再高的值也不会有太多帮助，可能它根本就无法连接。<a name="N101FB"><span class="atitle">缓冲区和缓存</span></a></p>
<p>MySQL 支持超过 100 个的可调节设置；但是幸运的是，掌握少数几个就可以满足大部分需要。查找这些设置的正确值可以通过 <code>SHOW STATUS</code> 命令查看状态变量，从中可以确定 <code>mysqld</code> 的运作情况是否符合我们的预期。给缓冲区和缓存分配的内存不能超过系统中的现有内存，因此调优通常都需要进行一些妥协。</p>
<p>MySQL 可调节设置可以应用于整个 <code>mysqld</code> 进程，也可以应用于单个客户机会话。</p>
<p><a name="N10213"><span class="smalltitle"><strong><span style="font-size: small; font-family: Arial;">服务器端的设置</span></strong></span></a></p>
<p>每个表都可以表示为磁盘上的一个文件，必须先打开，后读取。为了加快从文件中读取数据的过程，<code>mysqld</code> 对这些打开文件进行了缓存，其最大数目由 /etc/mysqld.conf 中的 <code>table_cache</code> 指定。清单 4 给出了显示与打开表有关的活动的方式。<br />
<a name="listing4"><strong>清单 4. 显示打开表的活动</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">mysql&gt; SHOW STATUS LIKE &#8216;open%tables&#8217;;</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;-+<br />
|Variable_name | Value |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;-+ |<br />
Open_tables | 5000 |<br />
| Opened_tables | 195 |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;-+<br />
2 rows in set (0.00 sec)</td>
</tr>
</tbody>
</table>
<p> </p>
<p>清单 4 说明目前有 5,000 个表是打开的，有 195 个表需要打开，因为现在缓存中已经没有可用文件描述符了（由于统计信息在前面已经清除了，因此可能会存在 5,000 个打开表中只有 195 个打开记录的情况）。如果 <code>Opened_tables</code> 随着重新运行 <code>SHOW STATUS</code> 命令快速增加，就说明缓存命中率不够。如果 <code>Open_tables</code> 比 <code>table_cache</code> 设置小很多，就说明该值太大了（不过有空间可以增长总不是什么坏事）。例如，使用 <code>table_cache = 5000</code> 可以调整表的缓存。</p>
<p>与表的缓存类似，对于线程来说也有一个缓存。 <code>mysqld</code> 在接收连接时会根据需要生成线程。在一个连接变化很快的繁忙服务器上，对线程进行缓存便于以后使用可以加快最初的连接。</p>
<p>清单 5 显示如何确定是否缓存了足够的线程。<br />
<a name="listing5"><strong>清单 5. 显示线程使用统计信息</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">mysql&gt; SHOW STATUS LIKE &#8216;threads%&#8217;; +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+ | Variable_name | Value | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+ | Threads_cached | 27 | | Threads_connected | 15 | | Threads_created | 838610 | | Threads_running | 3 | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+ 4 rows in set (0.00 sec)</td>
</tr>
</tbody>
</table>
<p> </p>
<p>此处重要的值是 <code>Threads_created</code>，每次 <code>mysqld</code> 需要创建一个新线程时，这个值都会增加。如果这个数字在连续执行 <code>SHOW STATUS</code> 命令时快速增加，就应该尝试增大线程缓存。例如，可以在 my.cnf 中使用 <code>thread_cache = 40</code> 来实现此目的。</p>
<p>关键字缓冲区保存了 MyISAM 表的索引块。理想情况下，对于这些块的请求应该来自于内存，而不是来自于磁盘。清单 6 显示了如何确定有多少块是从磁盘中读取的，以及有多少块是从内存中读取的。<br />
<a name="listing6"><strong>清单 6. 确定关键字效率</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">mysql&gt; show status like &#8216;%key_read%&#8217;; +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+ | Variable_name | Value | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+ | Key_read_requests | 163554268 | | Key_reads | 98247 | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+ 2 rows in set (0.00 sec)</td>
</tr>
</tbody>
</table>
<p> </p>
<p><code>Key_reads</code> 代表命中磁盘的请求个数， <code>Key_read_requests</code> 是总数。命中磁盘的读请求数除以读请求总数就是不中比率 —— 在本例中每 1,000 个请求，大约有 0.6 个没有命中内存。如果每 1,000 个请求中命中磁盘的数目超过 1 个，就应该考虑增大关键字缓冲区了。例如，<code>key_buffer = 384M</code> 会将缓冲区设置为 384MB。</p>
<p>临时表可以在更高级的查询中使用，其中数据在进一步进行处理（例如 <code>GROUP BY</code> 字句）之前，都必须先保存到临时表中；理想情况下，在内存中创建临时表。但是如果临时表变得太大，就需要写入磁盘中。清单 7 给出了与临时表创建有关的统计信息。<br />
<a name="listing7"><strong>清单 7. 确定临时表的使用</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">mysql&gt; SHOW STATUS LIKE &#8216;created_tmp%&#8217;; +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;-+ | Variable_name | Value | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;-+ | Created_tmp_disk_tables | 30660 | | Created_tmp_files | 2 | | Created_tmp_tables | 32912 | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;-+ 3 rows in set (0.00 sec)</td>
</tr>
</tbody>
</table>
<p> </p>
<p>每次使用临时表都会增大 <code>Created_tmp_tables</code>；基于磁盘的表也会增大 <code>Created_tmp_disk_tables</code>。对于这个比率，并没有什么严格的规则，因为这依赖于所涉及的查询。长时间观察 <code>Created_tmp_disk_tables</code> 会显示所创建的磁盘表的比率，您可以确定设置的效率。 <code>tmp_table_size</code> 和 <code>max_heap_table_size</code> 都可以控制临时表的最大大小，因此请确保在 my.cnf 中对这两个值都进行了设置。</p>
<p><a name="N102B0"><span class="smalltitle"><strong><span style="font-size: small; font-family: Arial;">每个会话的设置</span></strong></span></a></p>
<p>下面这些设置针对于每个会话。在设置这些数字时要十分谨慎，因为它们在乘以可能存在的连接数时候，这些选项表示大量的内存！您可以通过代码修改会话中的这些数字，或者在 my.cnf 中为所有会话修改这些设置。</p>
<p>当 MySQL 必须要进行排序时，就会在从磁盘上读取数据时分配一个排序缓冲区来存放这些数据行。如果要排序的数据太大，那么数据就必须保存到磁盘上的临时文件中，并再次进行排序。如果 <code>sort_merge_passes</code> 状态变量很大，这就指示了磁盘的活动情况。清单 8 给出了一些与排序相关的状态计数器信息。<br />
<a name="listing8"><strong>清单 8. 显示排序统计信息</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">mysql&gt; SHOW STATUS LIKE &#8220;sort%&#8221;; +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;+ | Variable_name | Value | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;+ | Sort_merge_passes | 1 | | Sort_range | 79192 | | Sort_rows | 2066532 | | Sort_scan | 44006 | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;+ 4 rows in set (0.00 sec)</td>
</tr>
</tbody>
</table>
<p> </p>
<p>如果 <code>sort_merge_passes</code> 很大，就表示需要注意 <code>sort_buffer_size</code>。例如， <code>sort_buffer_size = 4M</code> 将排序缓冲区设置为 4MB。</p>
<p>MySQL 也会分配一些内存来读取表。理想情况下，索引提供了足够多的信息，可以只读入所需要的行，但是有时候查询（设计不佳或数据本性使然）需要读取表中大量数据。要理解这种行为，需要知道运行了多少个 <code>SELECT</code> 语句，以及需要读取表中的下一行数据的次数（而不是通过索引直接访问）。实现这种功能的命令如清单 9 所示。<br />
<a name="listing9"><strong>清单 9. 确定表扫描比率</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="80%">
<tbody>
<tr>
<td class="code-outline">mysql&gt; SHOW STATUS LIKE &#8220;com_select&#8221;; +&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+ | Variable_name | Value | +&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+ | Com_select | 318243 | +&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+ 1 row in set (0.00 sec) mysql&gt; SHOW STATUS LIKE &#8220;handler_read_rnd_next&#8221;; +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+ | Variable_name | Value | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+ | Handler_read_rnd_next | 165959471 | +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+ 1 row in set (0.00 sec)</td>
</tr>
</tbody>
</table>
<p> </p>
<p><code>Handler_read_rnd_next</code> / <code>Com_select</code> 得出了表扫描比率 —— 在本例中是 521:1。如果该值超过 4000，就应该查看 <code>read_buffer_size</code>，例如 <code>read_buffer_size = 4M</code>。如果这个数字超过了 8M，就应该与开发人员讨论一下对这些查询进行调优了！</p>
<p> </p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td><img src="http://www.ibm.com/i/c.gif" border="0" alt="" width="8" height="6" /></td>
</tr>
</tbody>
</table>
<table class="no-print" border="0" cellspacing="0" cellpadding="0" align="right">
<tbody>
<tr align="right">
<td><img src="http://www.ibm.com/i/c.gif" alt="" width="100%" height="4" /></p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle"> </td>
<td align="right" valign="top"><strong></strong></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p><a name="N102FD"><span class="atitle">3 个必不可少的工具</span></a></p>
<p>尽管在了解具体设置时，<code>SHOW STATUS</code> 命令会非常有用，但是您还需要一些工具来解释 <code>mysqld</code> 所提供的大量数据。我发现有 3 个工具是必不可少的；在 <a href="http://www.tisswb.cn/wp-admin/#resources"><span style="color: #5c81a7;">参考资料</span></a> 一节中您可以找到相应的链接。</p>
<p>大部分系统管理员都非常熟悉 <code>top</code> 命令，它为任务所消耗的 CPU 和内存提供了一个不断更新的视图。 <code>mytop</code> 对 <code>top</code> 进行了仿真；它为所有连接上的客户机以及它们正在运行的查询提供了一个视图。<code>mytop</code> 还提供了一个有关关键字缓冲区和查询缓存效率的实时数据和历史数据，以及有关正在运行的查询的统计信息。这是一个很有用的工具，可以查看系统中（比如 10 秒钟之内）的状况，您可以获得有关服务器健康信息的视图，并显示导致问题的任何连接。</p>
<p><code>mysqlard</code> 是一个连接到 MySQL 服务器上的守护程序，负责每 5 分钟搜集一次数据，并将它们存储到后台的一个 Round Robin Database 中。有一个 Web 页面会显示这些数据，例如表缓存的使用情况、关键字效率、连接上的客户机以及临时表的使用情况。尽管 <code>mytop</code> 提供了服务器健康信息的快照，但是 <code>mysqlard</code> 则提供了长期的健康信息。作为奖励，<code>mysqlard</code> 使用自己搜集到的一些信息针对如何对服务器进行调优给出一些建议。</p>
<p>搜集 <code>SHOW STATUS</code> 信息的另外一个工具是 <code>mysqlreport</code>。其报告要远比 <code>mysqlard</code> 更加复杂，因为需要对服务器的每个方面都进行分析。这是对服务器进行调优的一个非常好的工具，因为它对状态变量进行适当计算来帮助确定需要修正哪些问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tisswb.com/archives/26.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

