﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-study-随笔分类-mysql</title><link>http://www.blogjava.net/lzj520/category/29730.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 28 Feb 2008 09:39:56 GMT</lastBuildDate><pubDate>Thu, 28 Feb 2008 09:39:56 GMT</pubDate><ttl>60</ttl><item><title>MYSQL数据同步,双向热备（转）</title><link>http://www.blogjava.net/lzj520/archive/2008/02/27/182485.html</link><dc:creator>lzj520</dc:creator><author>lzj520</author><pubDate>Wed, 27 Feb 2008 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/lzj520/archive/2008/02/27/182485.html</guid><wfw:comment>http://www.blogjava.net/lzj520/comments/182485.html</wfw:comment><comments>http://www.blogjava.net/lzj520/archive/2008/02/27/182485.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lzj520/comments/commentRss/182485.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lzj520/services/trackbacks/182485.html</trackback:ping><description><![CDATA[<p>1、简要介绍：mysql从3.23.15版本以后提供数据库复制功能。利用该功能可以实现两个数据库同步，主从模式(A-&gt;B)，互相备份模式(A&lt;=&gt;B)的功能。<br />
mysql数据库同步复制功能的设置都在mysql的配置文件中体现。在linux环境下的配置文件一般在/etc/mysql/my.cnf或者在mysql用户的home目录下的my.cnf，笔者的my.cnf则在/etc/my.cnf；windows环境下则可到mysql安装路径下找到my.ini。</p>
<p>&nbsp;2、下面我们来看看如何配置数据同步(A-&gt;B)：<br />
(笔者mysql版本 5.0.26)<br />
假设数据库A为主机（将向B提供同步服务，即B中的数据来自A）：<br />
A机器：<br />
IP = 192.168.1.101<br />
B机器：<br />
IP = 192.168.1.102</p>
<p>&nbsp;(1).在A机器中有数据库如下：</p>
<p>//数据库A<br />
<span style="background-color: #99ccff">CREATE DATABASE backup_db;<br />
USE backup_db;<br />
CREATE TABLE `backup_table` (<br />
&nbsp; `id` int(11) NOT NULL auto_increment,<br />
&nbsp; `name` varchar(20) character set utf8 NOT NULL,<br />
&nbsp; `sex` varchar(2) character set utf8 NOT NULL,<br />
&nbsp; PRIMARY KEY&nbsp; (`id`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=latin1;</span></p>
<p>#A机器的my.cnf(或my.ini)中应该配置：<br />
<span style="color: #000000; background-color: #99ccff">server-id=1<br />
log-bin=c:\mysqlback #同步事件的日志记录文件<br />
binlog-do-db=backup_db #提供数据同步服务的数据库</span></p>
<p>&nbsp;(2).在B机器中有数据库如下：</p>
<p>//数据库B<br />
<span style="background-color: #99ccff">CREATE DATABASE backup_db;<br />
USE backup_db;<br />
CREATE TABLE `backup_table` (<br />
&nbsp; `id` int(11) NOT NULL auto_increment,<br />
&nbsp; `name` varchar(20) character set utf8 NOT NULL,<br />
&nbsp; `sex` varchar(2) character set utf8 NOT NULL,<br />
&nbsp; PRIMARY KEY&nbsp; (`id`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=latin1;</span><br />
注：数据库A和B的数据库结构一定要相同，否则无法构成同步。</p>
<p>#B机器的my.cnf(或my.ini)中应该配置：<br />
<span style="background-color: #99ccff">server-id=2<br />
master-host=192.168.1.101 #主机A的地址<br />
master-user=ym #主机A提供给B的用户，该用户中需要包括数据库backup_db的权限<br />
master-password=ym #访问密码<br />
master-port=3306 #端口，主机的MYSQL端口<br />
master-connect-retry=60 #重试间隔60秒<br />
replicate-do-db=backup_db #同步的数据库</span></p>
<p>&nbsp;(3).完成了以上配置之后，将A的mysql数据的权限给B。<br />
A机器：<br />
<span style="color: #ffffff; background-color: #000000">mysql&gt;GRANT FILE ON *.* TO </span><a href="mailto:ym@'192.168.1.102'"><span style="color: #ffffff; background-color: #000000">ym@'192.168.1.102'</span></a><span style="color: #ffffff; background-color: #000000"> IDENTIFIEDBY &#8216;ym&#8217;;</span></p>
<p>&nbsp;(4).重启AB数据库，后：<br />
B机器：<br />
<span style="color: #ffffff; background-color: #000000">mysql&gt;slave start;</span></p>
<p>查看同步配置情况<br />
A机器：<br />
<span style="color: #ffffff; background-color: #000000">mysql&gt;show master status;</span><br />
B机器：<br />
<span style="color: #ffffff; background-color: #000000">mysql&gt;show slave status;</span></p>
<p>&nbsp;(5).在A中的backup_db.backup_table表中插入一些数据，查看B中的backup_db.backup_table表是否同步了数据改动。如果没有看到同步数据结果，即同步不成功，请查看错误（如下）。<br />
当有错误产生时*.err日志文件（可到mysql安装目录下找），同步的线程退出。当纠正错误后重复步骤(4)。</p>
<p>&nbsp;3、实现双向热备(A&lt;=&gt;B)：<br />
将以上的(1)-(5)步骤按A-B双向配置即可。<br />
<br />
</p>
<p>异步复制基本原理 </p>
<p>从MySQL3.23.15以后，MySQL支持单向的异步复制。也就是说，1台MySQL服务器充当Master(主库)，1台或多台MySQL服务器充当Slaves(从库)，数据从Master向Slaves进行异步复制。注意，这种复制是异步的，有别于MySQL的同步复制实现（这种实现称做MySQL集群，MySQL Cluster）。 </p>
<p>当主库有更新的时候，主库会把更新操作的SQL写入二进制日志(Bin log)，并维护一个二进制日志文件的索引，以便于日志文件轮回（Rotate）。在从库启动异步复制的时候，从库会开启两个I/O线程，其中一个线程连接主库，要求主库把二进制日志的变化部分传给从库，并把传回的日志写入本地磁盘。另一个线程则负责读取本地写入的二进制日志，并在本地执行，以反映出这种变化。较老的版本在复制的时候只启用一个I/O线程，实现这两部分的功能。 </p>
<p>有几个关键性的地方需要注意： </p>
<p>- 主库必须启用Bin log，主库和从库必须有唯一的Server Id <br />
- 从库必须清楚了解从主库的哪一个Bin log文件的哪一个偏移位置起开始复制 <br />
- 从库可以从主库只复制指定的数据库，或者数据库的某些数据表 <br />
- 主库和从库的数据库名称可以不一样，不过还是推荐使用一样的名称 <br />
- 主库和从库的MySQL版本需保持一致 </p>
<p>附：资料出处 <br />
http://www.javaeye.com/topic/153875<br />
http://blog.sina.com.cn/s/blog_4b0710d8010007eo.html</p>
<img src ="http://www.blogjava.net/lzj520/aggbug/182485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lzj520/" target="_blank">lzj520</a> 2008-02-27 14:45 <a href="http://www.blogjava.net/lzj520/archive/2008/02/27/182485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL优化(转）</title><link>http://www.blogjava.net/lzj520/archive/2008/02/27/182462.html</link><dc:creator>lzj520</dc:creator><author>lzj520</author><pubDate>Wed, 27 Feb 2008 04:30:00 GMT</pubDate><guid>http://www.blogjava.net/lzj520/archive/2008/02/27/182462.html</guid><wfw:comment>http://www.blogjava.net/lzj520/comments/182462.html</wfw:comment><comments>http://www.blogjava.net/lzj520/archive/2008/02/27/182462.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lzj520/comments/commentRss/182462.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lzj520/services/trackbacks/182462.html</trackback:ping><description><![CDATA[<p>如果这个服务可以被其他非数据库应用代替（比如很多基于数据库的计数器完全可以用WEB日志统计代替）最好将其禁用。非用数据库不可吗？虽然数据库的确可以简化很多应用的结构设计，但本身也是一个系统资源消耗比较大的应用。在某些情况下文本，DBM比数据库是更好的选择，比如：很多应用如果没有很高的实时统计需求的话，完全可以先记录到文件日志中，定期的导入到数据库中做后续统计分析。如果还是需要记录简单的2维键－值对应结构的话可以使用类似于DBM的HEAP类型表。因为HEAP表全部在内存中存取，效率非常高，但服务器突然断电时有可能出现数据丢失，所以非常适合存储在线用户信息，日志等临时数据。即使需要使用数据库的，应用如果没有太复杂的数据完整性需求的化，完全可以不使用那些支持外键的商业数据库，比如MySQL。只有非常需要完整的商业逻辑和事务完整性的时候才需要Oracle这样的大型数据库。对于高负载应用来说完全可以把日志文件，DBM，MySQL等轻量级方式做前端数据采集格式，然后用Oracle MSSQL DB2 Sybase等做数据库仓库以完成复杂的数据库挖掘分析工作。</p>
<p>数据库服务的主要瓶颈：单个服务的连接数。对于一个应用来说，如果数据库表结构的设计能够按照数据库原理的范式来设计的话，并且已经使用了最新版本的MySQL，并且按照比较优化的方式运行了，那么最后的主要瓶颈一般在于单个服务的连接数，即使一个数据库可以支持并发500个连接，最好也不要把应用用到这个地步，因为并发连接数过多数据库服务本身用于调度的线程的开销也会非常大了。所以如果应用允许的话：让一台机器多跑几个MySQL服务分担。将服务均衡的规划到多个MySQL服务端口上：比如app_1 ==&gt; 3301 app_2 ==&gt; 3302...app_9 ==&gt; 3309。一个1G内存的机器跑上10个MySQL是很正常的。让10个MySQLD承担1000个并发连接效率要比让2个MySQLD承担1000个效率高的多。当然，这样也会带来一些应用编程上的复杂度； </p>
<p>使用单独的数据库服务器（不要让数据库和前台WEB服务抢内存），MySQL拥有更多的内存就可能能有效的进行结果集的缓存；在前面的启动脚本中有一个-O key_buffer=32M参数就是用于将缺省的8M索引缓存增加到32M（当然对于） </p>
<p>应用尽量使用PCONNECT和polling机制，用于节省MySQL服务建立连接的开销，但也会造成MySQL并发链接数过多（每个HTTPD都会对应一个MySQL线程）； </p>
<p>表的横向拆分：让最常被访问的10%的数据放在一个小表里，90%的历史数据放在一个归档表里（所谓：快慢表），数据中间通过定期&#8220;搬家&#8221;和定期删除无效数据来节省，毕竟大部分应用（比如论坛）访问2个月前数据的几率会非常少，而且价值也不是很高。这样对于应用来说总是在一个比较小的结果级中进行数据选择，比较有利于数据的缓存，不要指望MySQL中对单表记录条数在10万级以上还有比较高的效率。而且有时候数据没有必要做那么精确，比如一个快表中查到了某个人发表的文章有60条结果，快表和慢表的比例是1:20，那么就可以简单的估计这个人一共发表了1200篇。Google的搜索结果数也是一样：对于很多上十万的结果数，后面很多的数字都是通过一定的算法估计出来的。 </p>
<p>数据库字段设计：表的纵向拆分（过渡范化）：将所有的定长字段（char, int等）放在一个表里，所有的变长字段（varchar,text,blob等）放在另外一个表里，2个表之间通过主键关联，这样，定长字段表可以得到很大的优化（这样可以使用HEAP表类型，数据完全在内存中存取），这里也说明另外一个原则，对于我们来说，尽量使用定长字段可以通过空间的损失换取访问效率的提高。在MySQL4中也出现了支持外键和事务的InnoDB类型表，标准的MyISAM格式表和基于HASH结构的HEAP内存表，MySQL之所以支持多种表类型，实际上是针对不同应用提供了不同的优化方式； </p>
<p>仔细的检查应用的索引设计：可以在服务启动参数中加入 --log-slow-queries[=file]用于跟踪分析应用瓶颈，对于跟踪服务瓶颈最简单的方法就是用MySQL的status查看MySQL服务的运行统计和show processlist来查看当前服务中正在运行的SQL，如果某个SQL经常出现在PROCESS LIST中，一。有可能被查询的此时非常多，二，里面有影响查询的字段没有索引，三，返回的结果数过多数据库正在排序（SORTING）；所以做一个脚本：比如每2秒运行以下show processlist;把结果输出到文件中，看到底是什么查询在吃CPU。 </p>
<p>全文检索：如果相应字段没有做全文索引的话，全文检索将是一个非常消耗CPU的功能，因为全文检索是用不上一般数据库的索引的，所以要进行相应字段记录遍历。关于全文索引可以参考一下基于Java的全文索引引擎lucene的介绍。 </p>
<p>前台应用的记录缓存：比如一个经常使用数据库认证，如果需要有更新用户最后登陆时间的操作，最好记录更新后就把用户放到一个缓存中（设置2个小时后过期），这样如果用户在2个小时内再次使用到登陆，就直接从缓存里认证，避免了过于频繁的数据库操作。 </p>
<p>&nbsp;查询优先的表应该尽可能为where和order by字句中的字段加上索引，数据库更新插入优先的应用索引越少越好。 </p>
<p>避免使用视图(viewport)与关联。视图viewport与关联都是为了程序员处理相对复杂的数据管理提供方便的手段。万物有其利，必有其弊。视图和关联提高了编程效率，都会较大地影响数据库的访问效率（事实上并不像一般资料说介绍的的那样高效），因此如果是web应用，则建议一般不要使用视图与关联。<br />
<br />
将字符串(varchar)比较变成数字型(int)比较 </p>
<p>每个系统都会有用户管理，其中必然有 昵称，密码，邮件等的字符串类型数据比较的问题。在数据库操作中，字符串比较的效率是相当低下的。因此遇到字符串的比较，必须将其转换为数字型比较。 <br />
具体做法是：在数据库表中增加相应的数字字段，比如 cNickname -&gt; iNickNumber ，其中 iNickNumber 的数值为 cNickname 的 哈希值</p>
<p>数据库表table的字段field不要太多 </p>
<p>本以为无需说明，也是发现不少的朋友，为了省事，一股脑把所有的相关字段都放在一个表中间。这样做的后果便是，程序写起来简单了，运行效率下来了。 <br />
无论字段多少，有两类字段是必须独立出去的：一是进程更新的字段，比如文章的点击次数字段iShow，二是二进制或者是text字段；<br />
<br />
</p>
<p>为每个数据库表(table)设置 datetime 字段 </p>
<p>在许多情况下，很多的表是不需要 datetime 字段用于保存时间的。本文的建议是你应该为每个表都设置 datetime 字段，而且默认值为 getdate()。 <br />
我们的经验是，datetime 是实数，占用字节不多；在进行系统维护，远程备份等环节都会发挥意想不到的效果。</p>
<br />
<img src ="http://www.blogjava.net/lzj520/aggbug/182462.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lzj520/" target="_blank">lzj520</a> 2008-02-27 12:30 <a href="http://www.blogjava.net/lzj520/archive/2008/02/27/182462.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>