<?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>一个故事@MySQL DBA &#187; MySQL</title>
	<atom:link href="http://www.orczhou.com/index.php/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.orczhou.com</link>
	<description>一个故事@MySQL DBA</description>
	<lastBuildDate>Tue, 20 Dec 2011 15:51:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>MySQL/InnoDB和Group Commit(2)</title>
		<link>http://www.orczhou.com/index.php/2011/12/time-to-group-commit-2/</link>
		<comments>http://www.orczhou.com/index.php/2011/12/time-to-group-commit-2/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 15:51:20 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Group Commit]]></category>
		<category><![CDATA[InnoDB]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=3397</guid>
		<description><![CDATA[<p>今天发现Percona Release的<a href="http://www.mysqlperformanceblog.com/2011/12/19/percona-server-5-5-18-23-0-now-with-group-commit/">Percona-Server-5-5-18-23-0</a>已经完成了Group Commit工作，而且是用最优雅的方式（移植了MariaDB的实现，而不是workaround），心里难掩激动。</p>
<p>这篇文章接<a href="http://www.orczhou.com/index.php/2010/08/time-to-group-commit-1/">前篇</a>继续介绍一下问题的背景：什么是Group Commit，现在的官方版本Group Commit做到了什么程度？</p>
<div class="myt1">1. 什么是Group Commit</div>
<p>MySQL/InnoDB在做事务的时候使用的日志先行（<a href="http://en.wikipedia.org/wiki/Write-ahead_logging">Write-ahead logging</a>）的方式保证事务的快速和持久，所以每次事务完成都要求日志必须持久化到磁盘，在Linux上对应的操作就是“<a href="http://www.orczhou.com/index.php/2009/08/innodb_flush_method-file-io/">write and fsync</a>”，write速度是很快的，一般对应的写Page Cache，而fsync则要求文件系统把对应文件的哦Page Cache必须持久化到磁盘上，而对于传统磁盘一次写操作大约需要1~3ms（不说BBU），这意味着对于传统磁盘1秒钟最多最多做333～1000个事务，这是不理想的，对硬件的利用率（吞吐量）也是非常低。</p>
<p>所以，这里就有了Group操作的概念，即当好几个线程都要fsync同一个日志文件时，我们将这些fsync合并到一次来做。简单举例：我们让系统每2ms做一次fsync，这样如果这2ms内有100个线程都需要做fsync，那就赚到了，原本100个fsync都独立来做那耗时会非常多的。</p>
<p>你肯定会说，难道这不是很简单的想法吗？是的，这就是原本是很简单、也很自然的想法。</p>
<p>但对MySQL来说却变成了一种奢求（看看这个<a href="http://bugs.mysql.com/bug.php?id=13669">Bug讨论</a>）。</p>
<div class="myt1">2. 为啥MySQL一直没有实现？</div>
<p>MySQL是不是太弱了，这么简单的事情都搞不定？不是的。</p>
<p>MySQL从开源到现在，成功的一个非常重要的原因，就是MySQL的插件式架构。如果MySQL只是MyISAM估计不会有现在的流行程度，插件式的架构让诸如Heikki Tuuri有了发挥空间，在InnoDB和MySQL一起时，MySQL才能算是一个真正的DBMS。再到后来，有Infobright、 FEDERATED、PBXT等等。</p>
<p>插件式的架构给MySQL带来了活力，做出牺牲便是在上层(MySQL)和下层(存储引擎)交互时带来的额外消耗，有时甚至上层和下层需要做一些重复工作。无法做Group Commit就是这其中的牺牲之一。</p>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/12/time-to-group-commit-2/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>今天发现Percona Release的<a href="http://www.mysqlperformanceblog.com/2011/12/19/percona-server-5-5-18-23-0-now-with-group-commit/">Percona-Server-5-5-18-23-0</a>已经完成了Group Commit工作，而且是用最优雅的方式（移植了MariaDB的实现，而不是workaround），心里难掩激动。</p>
<p>这篇文章接<a href="http://www.orczhou.com/index.php/2010/08/time-to-group-commit-1/">前篇</a>继续介绍一下问题的背景：什么是Group Commit，现在的官方版本Group Commit做到了什么程度？</p>
<div class="myt1">1. 什么是Group Commit</div>
<p>MySQL/InnoDB在做事务的时候使用的日志先行（<a href="http://en.wikipedia.org/wiki/Write-ahead_logging">Write-ahead logging</a>）的方式保证事务的快速和持久，所以每次事务完成都要求日志必须持久化到磁盘，在Linux上对应的操作就是“<a href="http://www.orczhou.com/index.php/2009/08/innodb_flush_method-file-io/">write and fsync</a>”，write速度是很快的，一般对应的写Page Cache，而fsync则要求文件系统把对应文件的哦Page Cache必须持久化到磁盘上，而对于传统磁盘一次写操作大约需要1~3ms（不说BBU），这意味着对于传统磁盘1秒钟最多最多做333～1000个事务，这是不理想的，对硬件的利用率（吞吐量）也是非常低。</p>
<p>所以，这里就有了Group操作的概念，即当好几个线程都要fsync同一个日志文件时，我们将这些fsync合并到一次来做。简单举例：我们让系统每2ms做一次fsync，这样如果这2ms内有100个线程都需要做fsync，那就赚到了，原本100个fsync都独立来做那耗时会非常多的。</p>
<p>你肯定会说，难道这不是很简单的想法吗？是的，这就是原本是很简单、也很自然的想法。</p>
<p>但对MySQL来说却变成了一种奢求（看看这个<a href="http://bugs.mysql.com/bug.php?id=13669">Bug讨论</a>）。</p>
<div class="myt1">2. 为啥MySQL一直没有实现？</div>
<p>MySQL是不是太弱了，这么简单的事情都搞不定？不是的。</p>
<p>MySQL从开源到现在，成功的一个非常重要的原因，就是MySQL的插件式架构。如果MySQL只是MyISAM估计不会有现在的流行程度，插件式的架构让诸如Heikki Tuuri有了发挥空间，在InnoDB和MySQL一起时，MySQL才能算是一个真正的DBMS。再到后来，有Infobright、 FEDERATED、PBXT等等。</p>
<p>插件式的架构给MySQL带来了活力，做出牺牲便是在上层(MySQL)和下层(存储引擎)交互时带来的额外消耗，有时甚至上层和下层需要做一些重复工作。无法做Group Commit就是这其中的牺牲之一。</p>
<p><span id="more-3397"></span></p>
<div class="myt1">3. 现在的官方版本Group Commit做到了什么程度</div>
<p>InnoDB在一次事务中，有两次fsync，分别是prepare阶段和commit阶段，对于这两次操作InnoDB都是<a href="http://www.innodb.com/wp/products/innodb_plugin/plugin-performance/innodb-plugin-1-0-4-group-commit-test-sysbench/">实现了Group操作</a>的。</p>
<p>如果你设置了binlog_sync=1，则又多了一次fsync操作（参考MYSQL_BIN_LOG::flush_and_sync），这次操作在innobase_xa_prepare和innodb_commit之间：</p>
<blockquote><p>binlog_prepare (do nothing)<br />
innodb_prepare<br />
...<br />
binlog_commit<br />
innobase_commit</p></blockquote>
<p><strong>这次fsync，在MySQL中一直都无法做Group</strong>。所以，一直以来当innodb_flush_log_at_trx_commit和binlog_sync都等于1的时候，MySQL的性能就<a href="http://www.mysqlperformanceblog.com/2011/07/13/testing-the-group-commit-fix/">非常、非常糟糕</a>。原因是为了保证InnoDB<strong>内部Commit</strong>的顺序和MySQL日志的顺序一致（<a href="http://www.orczhou.com/index.php/2010/08/time-to-group-commit-1/">参考</a>）。</p>
<div class="myt1">4. 开源社区的努力</div>
<p>难道没人去解决这个问题吗？不是的。有很多人已经做出了努力，直到Kristian Nielsen@MariaDB提出了理论和实际上的最优解决方案。</p>
<p>Mark Callaghan@Facebook关于Group Commit做的工作：<a href="http://www.facebook.com/note.php?note_id=386328905932">FB的基本实现</a> | <a href="http://www.facebook.com/note.php?note_id=438641125932">FB的问题和改进</a> | <a href="http://www.facebook.com/note.php?note_id=10150261692455933">性能</a> | <a href="http://www.facebook.com/note.php?note_id=10150211546215933">对比MariaDB的实现</a>(对比的结果是MariaDB完胜，无论是方案架构还是性能)</p>
<p>Facebooke可以说是通过<a href="http://www.facebook.com/note.php?note_id=386328905932">一个Trick</a>快速实现了Group Commit。而Kristian Nielsen@MariaDB这是从架构上根本的解决了这个问题。</p>
<p>MariaDB关于Group Commit架构和实现： <a href="http://askmonty.org/worklog/Server-Sprint/?tid=116">WL116</a> | <a href="http://askmonty.org/worklog/Server-Sprint/?tid=132">WL132</a> | <a href="http://askmonty.org/worklog/Server-RawIdeaBin/?tid=164">WL164</a></p>
<div class="myt1">5. 未完待续</div>
<p>后面还有很多值得写的，我希望自己能够一直写完这个系列。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/12/time-to-group-commit-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用tbdba-restore-mysqldump.pl切割mysqldump文件</title>
		<link>http://www.orczhou.com/index.php/2011/12/how-to-split-mysqldump-file/</link>
		<comments>http://www.orczhou.com/index.php/2011/12/how-to-split-mysqldump-file/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 14:40:42 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysqldump]]></category>
		<category><![CDATA[备份]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=3364</guid>
		<description><![CDATA[<p>这里介绍一个最近用得很多的一个小工具：<a href="https://github.com/orczhou/dba-tool/blob/master/tbdba-restore-mysqldump.pl">tbdba-restore-mysqldump.pl</a>。</p>
<p>主要有两个功能：</p>
<p>(1) 尽可能快的从一个非常大的mysqldump文件的分离出某个单表的备份文件</p>
<p>(2) 可以帮你把一个大的mysqldump文件，切割成非常小的单表备份文件（可继续做并行恢复）</p>
<div class="myt1">1. 什么时候需要这么做</div>
<p>(1) 如果把MySQL中<strong>某一个表</strong>数据弄丢了，需要从很大的mysqldump备份文件中恢复这个表</p>
<p>(2) 如果你想并行恢复整个mysqldump备份文件时，这个脚本可以帮你把大文件切割成多个小的单表备份文件，然后就可以方便并行恢复多个文件了</p>
<div class="myt1">2. 如何使用这个脚本</div>
<p>这里以实例的方式介绍如何使用该脚本：</p>
<p>(1) 从backup.sql文件中获取表process的备份：</p>
<blockquote><div style="color:blue">tbdba-restore-mysqldump.pl -t process -f backup.sql</div>
</blockquote>
<p>(2) 从backup.sql文件中获取数据库monitor中的表process的备份：</p>
<blockquote><div style="color:blue">tbdba-restore-mysqldump.pl -t process -s monitor -f backup.sql</div>
</blockquote>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/12/how-to-split-mysqldump-file/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>这里介绍一个最近用得很多的一个小工具：<a href="https://github.com/orczhou/dba-tool/blob/master/tbdba-restore-mysqldump.pl">tbdba-restore-mysqldump.pl</a>。</p>
<p>主要有两个功能：</p>
<p>(1) 尽可能快的从一个非常大的mysqldump文件的分离出某个单表的备份文件</p>
<p>(2) 可以帮你把一个大的mysqldump文件，切割成非常小的单表备份文件（可继续做并行恢复）</p>
<div class="myt1">1. 什么时候需要这么做</div>
<p>(1) 如果把MySQL中<strong>某一个表</strong>数据弄丢了，需要从很大的mysqldump备份文件中恢复这个表</p>
<p>(2) 如果你想并行恢复整个mysqldump备份文件时，这个脚本可以帮你把大文件切割成多个小的单表备份文件，然后就可以方便并行恢复多个文件了</p>
<div class="myt1">2. 如何使用这个脚本</div>
<p>这里以实例的方式介绍如何使用该脚本：</p>
<p>(1) 从backup.sql文件中获取表process的备份：</p>
<blockquote><div style="color:blue">tbdba-restore-mysqldump.pl -t process -f backup.sql</div>
</blockquote>
<p>(2) 从backup.sql文件中获取数据库monitor中的表process的备份：</p>
<blockquote><div style="color:blue">tbdba-restore-mysqldump.pl -t process -s monitor -f backup.sql</div>
</blockquote>
<p><span id="more-3364"></span></p>
<p>(3) 从backup.sql文件中获取多个表的备份文件（例如表process、users）：</p>
<blockquote><div style="color:blue">tbdba-restore-mysqldump.pl -t process,user -s monitor -f backup.sql</div>
</blockquote>
<p>(4) 直接接收来自管道的输出（如果你的mysqldump备份是压缩后，则可以使用）：</p>
<blockquote><div style="color:blue">gunzip -c backup.sql.gz|tbdba-restore-mysqldump.pl -t process,user -s monitor</div>
</blockquote>
<p>(5) 从backup.sql文件中获取数据库monitor下<strong>所有表</strong>的备份文件：</p>
<blockquote><div style="color:blue">gunzip -c backup.sql.gz|tbdba-restore-mysqldump.pl -s monitor </div>
</blockquote>
<p>(6) 从backup.sql文件中获取<strong>所有数据库下所有表</strong>的备份文件：</p>
<blockquote><div style="color:blue">gunzip -c backup.sql.gz|tbdba-restore-mysqldump.pl --all-tables</div>
</blockquote>
<p>(7) 使用-d参数，则可以看到切割的过程中的更多信息：</p>
<blockquote><div style="color:blue">date &#038;& gunzip -c /backdir/backup.sql.gz|tbdba-restore-mysqldump.pl -d -a &#038;& date</div>
</blockquote>
<div class="myt1">3. tbdba-restore-mysqldump.pl有什么优势</div>
<p>(1) 如果指定了-s（获取<strong>某个</strong>数据库中的备份）参数，则脚本在成功截取需要恢复的<strong>表</strong>后就会立刻退出，所以如果你要恢复的表恰好在备份文件的比较靠前的位置时，该脚本的速度会非常快。</p>
<p>一个实际工作例子：</p>
<blockquote><p>$ls -lh backup.sql.gz<br />
 -rw-r--r-- 1 mysql dba 14G Nov 21 04:49 backup.sql.gz<br />
$date &#038;& gunzip -c backup.sql.gz|./tbdba-restore-mysqldump.pl -s monitor_general -t monitor_host_info &#038;& date<br />
Fri Nov 25 14:35:06 CST 2011<br />
Fri Nov 25 14:46:49 CST 2011<br />
(the unzip of backup.sql.gz is 88G)</p></blockquote>
<p>如果要全量恢复的话，根据经验值：88GB的sql文件完全恢复约需要400分钟（<a href="http://www.orczhou.com/index.php/2009/12/more-about-mysqldump/">经验值</a>）。</p>
<p>(2) 为了让每个独立的单表备份文件能够准确恢复，脚本做了两个额外的处理工作：在每个单表备份前加上'use db'，让该表能够恢复到正确的数据库；为了让单表恢复时字符集不出错误，脚本在某个单表备份前加上了对应的SET NAMES utf8、SET TIME_ZONE等命令。</p>
<div class="myt1">4. 其他人都怎么做</div>
<p><a href="http://blog.tsheets.com/2008/tips-tricks/extract-a-single-table-from-a-mysqldump-file.html">Extract a Single Table from a mysqldump File</a>：这篇文章提到了三个办法，分别是：perl脚本（我这里的做法基本“雷同”），awk解析后切割，先恢复到临时库(对大文件这个不现实...)。对比了我们的Perl脚本，这里做了几个改进：可以同时解析出多个表；完成目标表的切割后，则立刻退出，不再扫描剩余部分；会把mysqldump头部输出放到每一个切割文件中，方便各种字符集的恢复；</p>
<p><a href="http://gtowey.blogspot.com/2009/11/restore-single-table-from-mysqldump.html">Restore a Single Table From mysqldump</a>：这篇文章介绍如何用Sed来完成这个工作。</p>
<p><a href="http://ushastry.blogspot.com/2009/08/mysql-restoring-single-table-from.html">MySQL - Restoring a single table from nightly backup </a>：这位朋友则，想出一个“更损”的招：只给恢复用户赋予需要恢复的表的权限，然后用--force参数恢复整个mysqldump文件。</p>
<p><a href="http://code.openark.org/blog/mysql/on-restoring-a-single-table-from-mysqldump">On restoring a single table from mysqldump</a>：这篇文章则对比了使用grep sed 和“权限控制”三种方法的速度。</p>
<p>最后，如果不喜欢mysqldump这种一股脑的备份方式，可以考虑试用mydumper。</p>
<p>OK，That's all.</p>
<p><embed src="http://www.xiami.com/widget/318706_184466/singlePlayer.swf" type="application/x-shockwave-flash" width="257" height="33" wmode="transparent"></embed></p>
<p>广告：<a href="http://www.orczhou.com/index.php/projects/we-are-hunting-mysql-hacker/">我们寻找靠谱的人</a> | <a href="http://www.orczhou.com/index.php/wish-list/">感谢作者</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/12/how-to-split-mysqldump-file/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MySQL如何传输二进制日志</title>
		<link>http://www.orczhou.com/index.php/2011/11/how-mysql-send-the-binary-log/</link>
		<comments>http://www.orczhou.com/index.php/2011/11/how-mysql-send-the-binary-log/#comments</comments>
		<pubDate>Sun, 20 Nov 2011 15:53:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Replication]]></category>
		<category><![CDATA[图解]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=3279</guid>
		<description><![CDATA[<p>MySQL Replication可以很方便的用来做应用的读扩展，也可以帮MySQL实现一定程度的HA方案。MySQL通过<a href="http://www.orczhou.com/index.php/2009/04/how-mysql-replication-works/">向备库传送二进制日志来实现Replication</a>，本文将通过二进制日志相关源代码的主要接口来解释：“<strong>MySQL如何传输二进制日志，是主库推，还是备库拉？MySQL日志传输的实时性如何？</strong>”。</p>
<p>在MySQL Replication结构中，备库端初次通过<a href="http://dev.mysql.com/doc/refman/5.1/en/change-master-to.html">CHANGE MASTER TO</a>完成Replication配置，再使用start slave命令开始复制。更细致的，备库通过IO Thread向主库发起读取binlog的请求（COM_BINLOG_DUMP命令），主库收到COM_BINLOG_DUMP请求后，使用单独线程（dump thread）不断向备库IO Thread发送Binlog。示意图(<a href="http://farm7.staticflickr.com/6237/6369693149_49d43db964_b.jpg">大图</a>)：<br />
<a href="http://www.orczhou.com/wp-content/uploads/2011/11/how_mysql_send_binary_log.jpg"><img src="http://www.orczhou.com/wp-content/uploads/2011/11/how_mysql_send_binary_log.jpg" alt="" title="how_mysql_send_binary_log" width="686" height="369" class="alignleft size-full wp-image-3292" /></a></p>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/11/how-mysql-send-the-binary-log/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>MySQL Replication可以很方便的用来做应用的读扩展，也可以帮MySQL实现一定程度的HA方案。MySQL通过<a href="http://www.orczhou.com/index.php/2009/04/how-mysql-replication-works/">向备库传送二进制日志来实现Replication</a>，本文将通过二进制日志相关源代码的主要接口来解释：“<strong>MySQL如何传输二进制日志，是主库推，还是备库拉？MySQL日志传输的实时性如何？</strong>”。</p>
<p>在MySQL Replication结构中，备库端初次通过<a href="http://dev.mysql.com/doc/refman/5.1/en/change-master-to.html">CHANGE MASTER TO</a>完成Replication配置，再使用start slave命令开始复制。更细致的，备库通过IO Thread向主库发起读取binlog的请求（COM_BINLOG_DUMP命令），主库收到COM_BINLOG_DUMP请求后，使用单独线程（dump thread）不断向备库IO Thread发送Binlog。示意图(<a href="http://farm7.staticflickr.com/6237/6369693149_49d43db964_b.jpg">大图</a>)：<br />
<a href="http://www.orczhou.com/wp-content/uploads/2011/11/how_mysql_send_binary_log.jpg"><img src="http://www.orczhou.com/wp-content/uploads/2011/11/how_mysql_send_binary_log.jpg" alt="" title="how_mysql_send_binary_log" width="686" height="369" class="alignleft size-full wp-image-3292" /></a></p>
<p><span id="more-3279"></span></p>
<p>在主库端一旦有新的日志产生后，立刻会发送一次广播，dump线程在收到广播后，则会读取二进制日志并通过网络向备库传输日志，所以这是一个主库向备库不断推送的过程；</p>
<p>新日志在产生后，只需一次广播和网络就会立刻（<1ms）向发送到备库，如果主备之间网络较好的话（例如RTT<1ms），备库端的日志也就小于2ms了。所以，一般的（依赖于RTT），备库的实时性都非常好。</p>
<p>参考：</p>
<p>1. <a href="http://dev.mysql.com/doc/refman/5.1/en/replication.html">MySQL Replication Manual</a></p>
<p>2. <a href="http://www.orczhou.com/index.php/2009/04/how-mysql-replication-works/">图解"How MySQL Replication Works" </a></p>
<p>Have fun!</p>
<p><embed src="http://www.xiami.com/widget/0_1025147/singlePlayer.swf" type="application/x-shockwave-flash" width="257" height="33" wmode="transparent"></embed></p>
<p>广告：<a href="http://www.orczhou.com/index.php/projects/we-are-hunting-mysql-hacker/">我们寻找靠谱的人</a> | <a href="http://www.orczhou.com/index.php/wish-list/">感谢作者</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/11/how-mysql-send-the-binary-log/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MySQL5.5 Semi-sync备库响应协议分析</title>
		<link>http://www.orczhou.com/index.php/2011/10/semy-sync-slave-protocol-slave-reply/</link>
		<comments>http://www.orczhou.com/index.php/2011/10/semy-sync-slave-protocol-slave-reply/#comments</comments>
		<pubDate>Tue, 18 Oct 2011 14:53:58 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[代码细节]]></category>
		<category><![CDATA[MySQL5.5]]></category>
		<category><![CDATA[semi-sync replication]]></category>
		<category><![CDATA[半同步]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=3125</guid>
		<description><![CDATA[<p>这又是一篇介绍Semi-sync的文章。</p>
<p>Semi-sync主库在一定时间内（可配置的超时时间），如果没有收到备库的响应，则会超时从而降级为普通的replication复制。如果超时发生，有时需要查清什么原因导致备库没有及时响应，一方面可以从备库的日志着手，另一方面，如果需要更细致的信息则需要从备库端的网络包查找原因。这里介绍如何分析一个Semi-sync备库响应主库的数据包。</p>
<p>概述：先使用tcpdump抓取正确（主要是src和dst都正确）的数据包；然后借助wireshark玻璃TCP/IP等层的头信息，仅保留发送的MySQL数据包；再分析MySQL Semi-sync Slave响应的协议。</p>
<div class="myt1">1. tcpdump原始数据包</div>
<p>通过如下tcpdump抓取主机的网络包：</p>
<pre>
<div class="mycode">nohup tcpdump -n -nn -tttt -i bond0 -s 65535 'port 3306 and ((dst host master.host and src host slave.host and len &#038;lt 100) or (dst host slave.host and src host master.host))' -w tcpdump.ret -C 50 &#038;
</div>
</pre>
<p>参数简单说明：</p>
<pre>
<div class="mycode">-n  表示ip不要转换为主机名
-nn表示端口号，不要转为为服务名（例如3306会被转换为mysql）
-tttt 打印出完成的格式化的时间戳
-C 50 表示抓取的结果放到文件中，文件大小不超过50MB
</div>
</pre>
<div class="myt1">2. 使用wireshark找到对应的包</div>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/10/semy-sync-slave-protocol-slave-reply/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>这又是一篇介绍Semi-sync的文章。</p>
<p>Semi-sync主库在一定时间内（可配置的超时时间），如果没有收到备库的响应，则会超时从而降级为普通的replication复制。如果超时发生，有时需要查清什么原因导致备库没有及时响应，一方面可以从备库的日志着手，另一方面，如果需要更细致的信息则需要从备库端的网络包查找原因。这里介绍如何分析一个Semi-sync备库响应主库的数据包。</p>
<p>概述：先使用tcpdump抓取正确（主要是src和dst都正确）的数据包；然后借助wireshark玻璃TCP/IP等层的头信息，仅保留发送的MySQL数据包；再分析MySQL Semi-sync Slave响应的协议。</p>
<div class="myt1">1. tcpdump原始数据包</div>
<p>通过如下tcpdump抓取主机的网络包：</p>
<pre>
<div class="mycode">nohup tcpdump -n -nn -tttt -i bond0 -s 65535 'port 3306 and ((dst host master.host and src host slave.host and len &#038;lt 100) or (dst host slave.host and src host master.host))' -w tcpdump.ret -C 50 &#038;
</div>
</pre>
<p>参数简单说明：</p>
<pre>
<div class="mycode">-n  表示ip不要转换为主机名
-nn表示端口号，不要转为为服务名（例如3306会被转换为mysql）
-tttt 打印出完成的格式化的时间戳
-C 50 表示抓取的结果放到文件中，文件大小不超过50MB
</div>
</pre>
<div class="myt1">2. 使用wireshark找到对应的包</div>
<p><span id="more-3125"></span></p>
<p>Semi-sync备库响应主库包，一般大小整个包大小约95字节。找到该网络包如下：</p>
<p><a href="http://www.orczhou.com/wp-content/uploads/2011/10/tmp.jpg"><img src="http://www.orczhou.com/wp-content/uploads/2011/10/tmp.jpg" alt="" title="tmp" width="618" height="156" class="alignleft size-full wp-image-3151" /></a></p>
<p>完整网络包内容：</p>
<pre>
<div class="mycode">0000  00 24 e8 57 76 5e 00 1d  70 82 ca c0 08 00 45 00   .$.Wv^.. p.....E.
0010  00 51 a6 e2 40 00 3e 06  89 34 ac 13 46 44 ac 17   .Q..@.>. .4..FD..
0020  6e 21 b3 35 0c ea b2 2d  26 2a da 46 3c df 80 18   n!.5...- &#038;*.F<...
0030  04 82 35 ef 00 00 01 01  08 0a 5a a2 7f cd 50 43   ..5..... ..Z...PC
0040  c1 5b 19 00 00 00 ef 38  40 01 00 00 00 00 00 6d   .[.....8 @......m
0050  79 73 71 6c 2d 62 69 6e  2e 30 30 31 35 31 36      ysql-bin .001516
</div>
</pre>
<div class="myt1">3. MySQL数据包分析</div>
<p>剥去TCP/IP等层（使用wireshark就可以了），剩下MySQL 包如下：</p>
<pre>
<div class="mycode">0040        19 00 00 00 ef 38  40 01 00 00 00 00 00 6d   .[.....8 @......m
0050  79 73 71 6c 2d 62 69 6e  2e 30 30 31 35 31 36      ysql-bin .001516
</div>
</pre>
<p>更具Semi-sync备库响应源码分析如下：</p>
<pre>
<div class="mycode">+============================+
| packetlength      0 : 4    | 对应的：19 00 00 00 表示包数据长度为0x19=25字节
+----------------------------+
| magic_num         4 : 1    | 对应的：ef 这是一个kPacketMagicNum，表示这是一个Semi-sync slave响应
+----------------------------+
| binlog_pos        5 : 4    | 对应的：38  40 01 00 Binlog Pos:0x14038 = 81976
+----------------------------+
| event_length      9 : 20   | 对应的：00 00 00 00 6d 79 73 71 6c .... 31 36 （mysql-bin.001516）
+----------------------------+
</div>
</pre>
<p>可以看出，改网络包，响应主库端的mysql-bin.001516中的偏移为81976的事务。</p>
<div class="myt1">4. 最后【更新2011-10-19】</div>
<p>通过tcpdump的网络包，我们可以看到毫秒（甚至微秒）级别数据包的传送情况。依据此，通常可以精确分析出Semi-sync在何时、何处出现超时。然后，可以继续分析为何出现超时。</p>
<p>That's all...  这篇枯燥吧，哈哈  </p>
<p><embed src="http://www.xiami.com/widget/0_1769845026/singlePlayer.swf" type="application/x-shockwave-flash" width="257" height="33" wmode="transparent"></embed></p>
<p>广告：<a href="http://www.orczhou.com/index.php/projects/we-are-hunting-mysql-hacker/">我们寻找靠谱的人</a> | <a href="http://www.orczhou.com/index.php/wish-list/">感谢作者</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/10/semy-sync-slave-protocol-slave-reply/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Percona-Server/MySQL响应时间统计</title>
		<link>http://www.orczhou.com/index.php/2011/09/thanks-percona-response-time-distribution/</link>
		<comments>http://www.orczhou.com/index.php/2011/09/thanks-percona-response-time-distribution/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 13:02:57 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Percona MySQL]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=3068</guid>
		<description><![CDATA[<p>在Percona的5.1.53和5.5.8版本，开始将RT的统计内置到MySQL Server端。Thanks, Percona.</p>
<p>Percona在提供了<a href="http://www.mysqlperformanceblog.com/2010/08/31/introducing-tcprstat-a-tcp-response-time-tool/">tcprstat工具</a>统计RT时间之后，很快就在Percona Server中集成了响应时间统计的功能。这里介绍一下该功能，各位看官如果在犹豫选择<a href="http://www.percona.com/software/percona-server/">Percona Server</a>还是<a href="http://dev.mysql.com/downloads/mysql/">MySQL Community Server</a>，这里给Percona Server加一个筹码。</p>
<p>"响应时间"（Response time，后面简称RT）在数据库应用中，特别是OLTP的场景，可以说非常重要，不过，MySQL官方版本中一直没有加上这个统计功能。最早，社区开始尝试tcmdump+perl脚本的方式查看RT，后来告警一点用<a href="http://ronaldbradford.com/blog/take-a-look-at-mk-query-digest-2009-10-08/">tcpdump+mk-query-digest</a>，再后来Ignacio Nin和Baron Schwartz完成了tcprstat。</p>
<p>在Percona的5.1.53和5.5.8版本，开始将RT的统计内置到MySQL Server端。</p>
<div class="myt1">1. 配置该功能</div>
<p>这个是功能默认是关闭的，可以通过设置参数query_response_time_stats=1打开这个功能，这是一个动态参数，所以在服务器上可以很方便的打开或者关闭这个功能。可以通过命令SHOW QUERY_RESPONSE_TIME查看响应时间统计。[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/09/thanks-percona-response-time-distribution/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>在Percona的5.1.53和5.5.8版本，开始将RT的统计内置到MySQL Server端。Thanks, Percona.</p>
<p>Percona在提供了<a href="http://www.mysqlperformanceblog.com/2010/08/31/introducing-tcprstat-a-tcp-response-time-tool/">tcprstat工具</a>统计RT时间之后，很快就在Percona Server中集成了响应时间统计的功能。这里介绍一下该功能，各位看官如果在犹豫选择<a href="http://www.percona.com/software/percona-server/">Percona Server</a>还是<a href="http://dev.mysql.com/downloads/mysql/">MySQL Community Server</a>，这里给Percona Server加一个筹码。</p>
<p>"响应时间"（Response time，后面简称RT）在数据库应用中，特别是OLTP的场景，可以说非常重要，不过，MySQL官方版本中一直没有加上这个统计功能。最早，社区开始尝试tcmdump+perl脚本的方式查看RT，后来告警一点用<a href="http://ronaldbradford.com/blog/take-a-look-at-mk-query-digest-2009-10-08/">tcpdump+mk-query-digest</a>，再后来Ignacio Nin和Baron Schwartz完成了tcprstat。</p>
<p>在Percona的5.1.53和5.5.8版本，开始将RT的统计内置到MySQL Server端。</p>
<div class="myt1">1. 配置该功能</div>
<p>这个是功能默认是关闭的，可以通过设置参数query_response_time_stats=1打开这个功能，这是一个动态参数，所以在服务器上可以很方便的打开或者关闭这个功能。可以通过命令SHOW QUERY_RESPONSE_TIME查看响应时间统计。<span id="more-3068"></span></p>
<div class="myt2">默认关闭状态：</div>
<pre>
<div class="mycode">SHOW QUERY_RESPONSE_TIME;
+----------------+---+----------------+
|                |   |                |
+----------------+---+----------------+
|       0.000001 | 0 |       0.000000 |
|       0.000010 | 0 |       0.000000 |
|       0.000100 | 0 |       0.000000 |
|       0.001000 | 0 |       0.000000 |
......
|  1000000.00000 | 0 |       0.000000 |
| TOO LONG       | 0 | TOO LONG       |
+----------------+---+----------------+</div>
</pre>
<div class="myt2">打开参数后：</div>
<pre>
<div class="mycode">set global query_response_time_stats=1;
Query OK, 0 rows affected (0.00 sec)

08:23:13>SHOW QUERY_RESPONSE_TIME;
+----------------+-------+----------------+
|                |       |                |
+----------------+-------+----------------+
|       0.000001 |  7982 |       0.000000 |
|       0.000010 | 13927 |       0.014511 |
|       0.000100 | 43811 |       1.553811 |
|       0.001000 |    29 |       0.007936 |
|       0.010000 |     1 |       0.001711 |
|       0.100000 |     0 |       0.000000 |
</div>
</pre>
<p>这里可以看到，响应时间小于0.000001<strong>秒</strong>的SQL有7982个，0.000001 &lt; RT &lt;  0.000010有13927个， 0.000010 &lt; RT &lt; 0.000100有43811  ...... 。这样整个系统的响应时间就清晰了。</p>
<div class="myt1">2. INFORMATION_SCHEMA.QUERY_RESPONSE_TIME</div>
<p>除了用命令SHOW QUERY_RESPONSE_TIME，还可以通过INFORMATION_SCHEMA里面的表QUERY_RESPONSE_TIME来查看MySQL的响应时间。</p>
<pre>
<div class="mycode">08:25:16>SELECT * from INFORMATION_SCHEMA.QUERY_RESPONSE_TIME;
+----------------+--------+----------------+
| time           | count  | total          |
+----------------+--------+----------------+
|       0.000001 |  33824 |       0.000000 |
|       0.000010 |  59222 |       0.060457 |
|       0.000100 | 186003 |       6.659908 |
|       0.001000 |    117 |       0.025163 |
|       0.010000 |      8 |       0.014534 |</div>
</pre>
<p>使用INFORMATION_SCHEMA.QUERY_RESPONSE_TIME，就可以稍微定制一下输出结果了：</p>
<pre>
<div class="mycode">
SELECT time, CONCAT(ROUND(100*count/query_count,2),"%") as percent,count
FROM(
    SELECT
    	c.count,
    	c.time,
    	(
    	    SELECT SUM(a.count)
    	    FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a
    	    WHERE a.count != 0
    	) as query_count
    FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c
    WHERE c.count > 0
) d;
+----------------+---------+--------+
| time           | percent | count  |
+----------------+---------+--------+
|       0.000001 | 12.64%  |  81557 |
|       0.000010 | 20.69%  | 133440 |
|       0.000100 | 66.62%  | 429705 |
|       0.001000 | 0.05%   |    339 |
|       0.010000 | 0.00%   |     10 |
|    1000.000000 | 0.00%   |      1 |
+----------------+---------+--------+
</div>
</pre>
<div class="myt1">3. 高端一点的功能：定制化时间区间</div>
<p>默认的时间区间是：</p>
<p>(0; 10 ^ -6], (10 ^ -6; 10 ^ -5], (10 ^ -5; 10 ^ -4], ..., (10 ^ -1; 10 ^1], (10^1; 10^2]...(10^</p>
<p>你可以通过修改参数query_response_time_range_base来缩小时间区间，默认该参数是10，时间区间如上。</p>
<p>例如我们修个set global query_response_time_range_base=2; 则区间如下：</p>
<p>(0; 2 ^ -19], (2 ^ -19; 2 ^ -18], (2 ^ -18; 2 ^ -17], ..., (2 ^ -1; 2 ^1], (2 ^ 1; 2 ^ 2]...(2 ^</p>
<p>第一个区间总是最接近0.000001区间开始(2^19次方最接近)；最后一个区间是到最接近且小于10000000处结束。</p>
<p>具体的：</p>
<div class="mycode">set global query_response_time_range_base=2;<br />
flush QUERY_RESPONSE_TIME;<br />
SHOW QUERY_RESPONSE_TIME;<br />
|       0.000001 |  711 |       0.000000 |<br />
|       0.000003 | 1456 |       0.001456 |<br />
......<br />
|       0.125000 |    0 |       0.000000 |<br />
|       0.250000 |    0 |       0.000000 |<br />
|       0.500000 |    0 |       0.000000 |<br />
|       1.000000 |    0 |       0.000000 |<br />
|       2.000000 |    0 |       0.000000 |<br />
|       4.000000 |    0 |       0.000000 |<br />
|       8.000000 |    0 |       0.000000 |<br />
|      16.000000 |    0 |       0.000000 |<br />
......<br />
|  8388608.00000 |    0 |       0.000000 |<br />
| TOO LONG       |    0 | TOO LONG       |
</div>
<div class="myt1">一些注意事项</div>
<p>在备库上，只有打开了参数<a href="log_slow_slave_statements">log_slow_slave_statements</a>(这个参数也是Percona Server上特有的)时，slave sql线程的SQL才会被统计。</p>
<p>启动变量have_response_time_distribution，不能配置，该参数只表示该Server是否具有上述的RT统计功能。</p>
<p>设置了query_response_time_range_base，必须flush QUERY_RESPONSE_TIME后才生效。这里flush做两件事情，使得QUERY_RESPONSE_TIME生效，另外清空之前的统计结果。</p>
<p>累了，听首歌，扭扭脖子吧:)</p>
<p><script type="text/javascript" src="http://www.xiami.com/widget/player-single?uid=0&#038;sid=3599116&#038;mode=js"></script></p>
<p>广告：<a href="http://www.orczhou.com/index.php/projects/we-are-hunting-mysql-hacker/">我们寻找靠谱的人</a> | <a href="http://www.orczhou.com/index.php/wish-list/">感谢作者</a></p>
<p>参考文献：</p>
<p>1. <a href="http://www.mysqlperformanceblog.com/2010/08/31/introducing-tcprstat-a-tcp-response-time-tool/">Introducing tcprstat, a TCP response time tool</a></p>
<p>2. <a href="http://www.percona.com/docs/wiki/tcprstat:start">The tcprstat User's Manual</a></p>
<p>3. <a href="http://www.megalinux.net/using-tcpdump-for-mysql-query-logging/">Using Tcpdump for MySQL query logging</a></p>
<p>4. <a href="http://www.mysqlperformanceblog.com/2011/04/18/how-to-use-tcpdump-on-very-busy-hosts/">How to use tcpdump on very busy hosts</a></p>
<p>5. <a href="http://ronaldbradford.com/blog/take-a-look-at-mk-query-digest-2009-10-08/">Take a look at mk-query-digest</a></p>
<p>6. <a href="http://www.percona.com/docs/wiki/percona-server:features:implementation_details:details_response_time_distribution">Implementation Details: Response Time Distribution</a></p>
<p>7. <a href="http://www.percona.com/docs/wiki/percona-server:features:response_time_distribution">Percona Software Documentation :Response Time Distribution</a></p>
<p>【附录】</p>
<p>既然上面读取INFORMATION_SCHEMA的SQL已经有些复杂了，那就不怕再复杂一些：</p>
<pre>
<div class="mycode">SELECT
    case TRIM(time)
    	when '0.000001' then '<  1us'
    	when '0.000010' then '< 10us'
    	when '0.000100' then '<100us'
    	when '0.001000' then '<  1ms'
    	when '0.010000' then '< 10ms'
    	when '0.100000' then '<100ms'
    	when '1.000000' then '<   1s'
    	when '10.000000' then '<  10s'
    	when '100.000000' then '<100s'
    	else '>100s'
    END as `RT area`,
    CONCAT(ROUND(100*count/query_count,2),"%") as percent,
    count
FROM(
    SELECT
    	c.count,
    	c.time,
    	(
    	    SELECT SUM(a.count)
    	    FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a
    	    WHERE a.count != 0
    	) as query_count
    FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c
    WHERE c.count > 0
) d;
+---------+---------+--------+
| RT area | percent | count  |
+---------+---------+--------+
| < 10us  | 41.92%  | 404409 |
| <100us  | 21.34%  | 205881 |
| <  1ms  | 35.20%  | 339574 |
| < 10ms  | 1.30%   |  12586 |
| <100ms  | 0.18%   |   1736 |
| <   1s  | 0.02%   |    160 |
| <  10s  | 0.04%   |    340 |
+---------+---------+--------+
</div>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/09/thanks-percona-response-time-distribution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL半同步Semi-sync原理介绍【图说】</title>
		<link>http://www.orczhou.com/index.php/2011/07/why-and-how-mysql-5-5-semi-sync-replication/</link>
		<comments>http://www.orczhou.com/index.php/2011/07/why-and-how-mysql-5-5-semi-sync-replication/#comments</comments>
		<pubDate>Thu, 21 Jul 2011 15:18:11 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQL5.5]]></category>
		<category><![CDATA[semi-sync]]></category>
		<category><![CDATA[semi-sync replication]]></category>
		<category><![CDATA[半同步]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=3044</guid>
		<description><![CDATA[<p>上图先。</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5961167474/" title="Semi-sync-why by orczhou, on Flickr"><img src="http://farm7.static.flickr.com/6017/5961167474_cb1099962f.jpg" width="500" height="424" alt="Semi-sync-why"/></a></p>
<p>如果还不了解Semi-sync可以阅读（<a href="http://dev.mysql.com/doc/refman/5.5/en/replication-semisync.html">Manual</a> &#124; <a href="http://www.orczhou.com/index.php/2009/12/mysql-55-semi-sync-replication/">概述</a>）</p>
<div class="myt1">1. 优点</div>
<p><strong>当事务返回客户端成功后，则日志一定在至少两台主机上存在。</strong></p>
<p>MySQL在<a href="http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/">加载并开启</a>Semi-sync插件后，每一个事务需等待备库接收日志后才返回给客户端。如果做的是小事务，两台主机的延迟又较小，则Semi-sync可以实现在性能很小损失的情况下的零数据丢失。</p>
<div class="myt1">2. 缺点</div>
<p>完成单条事务增加了额外的等待延迟，延迟的大小取决于网络的好坏。</p>
<p>Semi-sync不是分布式事务，主库会在自己<strong>完成事务后</strong>，等待备库接收<strong>事务日志</strong>。</p>
<div class="myt1">3. 主机Crash时的处理</div>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/07/why-and-how-mysql-5-5-semi-sync-replication/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>上图先。</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5961167474/" title="Semi-sync-why by orczhou, on Flickr"><img src="http://farm7.static.flickr.com/6017/5961167474_cb1099962f.jpg" width="500" height="424" alt="Semi-sync-why"></a></p>
<p>如果还不了解Semi-sync可以阅读（<a href="http://dev.mysql.com/doc/refman/5.5/en/replication-semisync.html">Manual</a> | <a href="http://www.orczhou.com/index.php/2009/12/mysql-55-semi-sync-replication/">概述</a>）</p>
<div class="myt1">1. 优点</div>
<p><strong>当事务返回客户端成功后，则日志一定在至少两台主机上存在。</strong></p>
<p>MySQL在<a href="http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/">加载并开启</a>Semi-sync插件后，每一个事务需等待备库接收日志后才返回给客户端。如果做的是小事务，两台主机的延迟又较小，则Semi-sync可以实现在性能很小损失的情况下的零数据丢失。</p>
<div class="myt1">2. 缺点</div>
<p>完成单条事务增加了额外的等待延迟，延迟的大小取决于网络的好坏。</p>
<p>Semi-sync不是分布式事务，主库会在自己<strong>完成事务后</strong>，等待备库接收<strong>事务日志</strong>。</p>
<div class="myt1">3. 主机Crash时的处理</div>
<p><span id="more-3044"></span></p>
<p>备库Crash时，主库会在某次等待超时后，关闭Semi-sync的特性，降级为普通的异步复制，这种情况比较简单。</p>
<p>主库Crash后，那么可能存在一些事务已经在主库Commit，但是还没有传给任何备库，我们姑且称这类事务为"<strong>墙头事务</strong>"。"墙头事务"都是没有返回给客户端的，所以发起事务的客户端并不知道这个事务是否已经完成。</p>
<p>这时，如果客户端不做切换，只是<strong>等Crash的主库恢复后，继续在主库进行操作</strong>，客户端会发现前面的"墙头事务"都已经完成，可以继续进行后续的业务处理；另一种情况，<strong>如果客户端Failover到备库上</strong>，客户端会发现前面的“墙头事务”都没有成功，则需要重新做这些事务，然后继续进行后续的业务处理。</p>
<div class="myt1">4. 其他</div>
<p>可以做多个备库，任何一个备库接收完成日志后，主库就可以返回给客户端了。</p>
<p>网络传输在并发线程较多时，一次可能传输很多日志，事务的<strong>平均</strong>延迟会降低。</p>
<p>"墙头事务"在墙头上的时候，是可以被读取的，但是这些事务在上面Failover的场景下，是被认为没有完成的。</p>
<p>累了，听首歌，伸个懒腰吧:)</p>
<p><embed src="http://www.xiami.com/widget/0_381336/singlePlayer.swf" type="application/x-shockwave-flash" width="257" height="33" wmode="transparent"></embed></p>
<p>广告：<a href="http://www.orczhou.com/index.php/projects/we-are-hunting-mysql-hacker/">我们寻找靠谱的人</a> | <a href="http://www.orczhou.com/index.php/wish-list/">感谢作者</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/07/why-and-how-mysql-5-5-semi-sync-replication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL 5.5 Semi-sync Replication安装配置、参数说明</title>
		<link>http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/</link>
		<comments>http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 05:30:52 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQL5.5]]></category>
		<category><![CDATA[semi-sync]]></category>
		<category><![CDATA[semi-sync replication]]></category>
		<category><![CDATA[半同步]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2950</guid>
		<description><![CDATA[<p>从09年12月份MySQL5.5的<a href="http://www.orczhou.com/index.php/2009/12/mysql-55-semi-sync-replication/">第一个Release</a>，再到去年<a href="http://blogs.oracle.com/MySQL/entry/mysql_55_is_ga">12月的第一个GA</a>，MySQL5.5平均<a href="http://dev.mysql.com/doc/refman/5.5/en/news-5-5-x.html">一月一个小版本号的速度</a>在默默更新。该版本最重要的特性目前仍是Semi-sync Replication，之前做了一个<a href="http://www.orczhou.com/index.php/2009/12/mysql-55-semi-sync-replication/">概述</a>，这里将继续介绍如何安装、配置Semi-sync，后续还将继续介绍其性能和一些基本的代码实现。</p>
<div class="myt1">1. Semi-sync Repication的历史</div>
<p>Semi-sync最早是由Google实现的一个补丁，代码主要由<a href="http://forge.mysql.com/wiki/ReplicationFeatures/SemiSyncReplication">Mark Callaghan、Wei Li</a>（@Google）等人贡献。Google原本是将<a href="http://code.google.com/p/google-mysql-tools/wiki/SemiSyncReplication">需求提给Hekki</a>的，但是后来等不及就自己实现了......。(现在Mark Callaghan已跳到Facebook，除了Google，<a href="http://www.linkedin.com/pub/mark-callaghan/2/249/894">他曾经还在Informix、Oracle工作过</a>)</p>
<p>在5.5之后由<a href="http://forge.mysql.com/wiki/ReplicationTeam">MySQL Replication Team</a>按照Plugin的方式将代码移植过来，并将Semi-sync独立成MySQL的一个插件，主要代码移植者是Zhenxing He（<a href="http://forge.mysql.com/wiki/ReplicationTeam">参考</a>）。</p>
<div class="myt1">2. 安装、配置Semi-sync Replication</div>
<p>在两台主机上<a href="http://www.orczhou.com/index.php/2011/06/compile-and-install-mysql-5-5-from-source/">安装好</a>MySQL5.5，编译好的插件在目录CMAKE_INSTALL_PREFIX/lib/plugin下（默认是/usr/local/mysql/lib/plugin）。例如这里编译是指定CMAKE_INSTALL_PREFIX为/home/mysql/mysql，则有：</p>
<div class="mycode">$pwd<br />
/home/mysql/mysql/lib/plugin<br />
$ls -a semisync_*<br />
semisync_master.so  semisync_slave.so</div>
<p>在主库初次启动时，执行如下语句加载semisync_master插件：</p>
<div class="mycode">mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';</div>
<p>备库上则加载semisync_slave插件：</p>
<div class="mycode">mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';</div>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>从09年12月份MySQL5.5的<a href="http://www.orczhou.com/index.php/2009/12/mysql-55-semi-sync-replication/">第一个Release</a>，再到去年<a href="http://blogs.oracle.com/MySQL/entry/mysql_55_is_ga">12月的第一个GA</a>，MySQL5.5平均<a href="http://dev.mysql.com/doc/refman/5.5/en/news-5-5-x.html">一月一个小版本号的速度</a>在默默更新。该版本最重要的特性目前仍是Semi-sync Replication，之前做了一个<a href="http://www.orczhou.com/index.php/2009/12/mysql-55-semi-sync-replication/">概述</a>，这里将继续介绍如何安装、配置Semi-sync，后续还将继续介绍其性能和一些基本的代码实现。</p>
<div class="myt1">1. Semi-sync Repication的历史</div>
<p>Semi-sync最早是由Google实现的一个补丁，代码主要由<a href="http://forge.mysql.com/wiki/ReplicationFeatures/SemiSyncReplication">Mark Callaghan、Wei Li</a>（@Google）等人贡献。Google原本是将<a href="http://code.google.com/p/google-mysql-tools/wiki/SemiSyncReplication">需求提给Hekki</a>的，但是后来等不及就自己实现了......。(现在Mark Callaghan已跳到Facebook，除了Google，<a href="http://www.linkedin.com/pub/mark-callaghan/2/249/894">他曾经还在Informix、Oracle工作过</a>)</p>
<p>在5.5之后由<a href="http://forge.mysql.com/wiki/ReplicationTeam">MySQL Replication Team</a>按照Plugin的方式将代码移植过来，并将Semi-sync独立成MySQL的一个插件，主要代码移植者是Zhenxing He（<a href="http://forge.mysql.com/wiki/ReplicationTeam">参考</a>）。</p>
<div class="myt1">2. 安装、配置Semi-sync Replication</div>
<p>在两台主机上<a href="http://www.orczhou.com/index.php/2011/06/compile-and-install-mysql-5-5-from-source/">安装好</a>MySQL5.5，编译好的插件在目录CMAKE_INSTALL_PREFIX/lib/plugin下（默认是/usr/local/mysql/lib/plugin）。例如这里编译是指定CMAKE_INSTALL_PREFIX为/home/mysql/mysql，则有：</p>
<div class="mycode">$pwd<br />
/home/mysql/mysql/lib/plugin<br />
$ls -a semisync_*<br />
semisync_master.so  semisync_slave.so</div>
<p>在主库初次启动时，执行如下语句加载semisync_master插件：</p>
<div class="mycode">mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';</div>
<p>备库上则加载semisync_slave插件：</p>
<div class="mycode">mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';</div>
<p><span id="more-2950"></span></p>
<p>在初次加载插件后，MySQL会将该插件记录到系统表mysql.plugin中，下次启动时系统则会自动加载该插件了，无需再次执行上面的命令。</p>
<p>另外，主备库的配置文件my.cnf还需要新增如下记录来打开semi-sync。主库上，新增如下参数：</p>
<div class="mycode">$vi my.cnf<br />
...<br />
rpl_semi_sync_master_enabled=1<br />
rpl_semi_sync_master_timeout=1000<br />
...</div>
<p>备库上新增：</p>
<div class="mycode">$vi my.cnf<br />
...<br />
rpl_semi_sync_slave_enabled=1<br />
...</div>
<p>那么主备在启动后，且slave线程开始dump主库的日志后，Semi-sync Replication就会开启，上面的配置(rpl_semi_sync_master_timeout=1000)表示主库在某次事务中，如果等待时间超过1000毫秒，那么则降级为普通模式，不再等待备库。如果主库再次探测到，备库恢复了，则会自动再次回到Semi-sync状态。</p>
<div class="myt1">3. 其他参数</div>
<p>Semi-sync的<a href="http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_rpl_semi_sync_master_timeout">配置参数不多</a>，按照上面配置就可以了，其他少数几个参数默认即可。</p>
<p>主库上的其他参数：</p>
<pre>
<div class="mycode">mysql> show variables like "%rpl_semi%";
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | ON    |
| rpl_semi_sync_master_timeout       | 1000  |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+
</div>
</pre>
<p>备库上有：</p>
<pre>
<div class="mycode">mysql> show variables like "%rpl_semi%";
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_wait_no_slave | ON    |
| rpl_semi_sync_slave_enabled        | ON    |
| rpl_semi_sync_slave_trace_level    | 32    |
+------------------------------------+-------+
</div>
</pre>
<p>rpl_semi_sync_master_trace_level和rpl_semi_sync_slave_trace_level是可以组合（求或）的参数，可以是下面值的组合：</p>
<blockquote><p>1 = general level (for example, time function failures)<br />
16 = detail level (more verbose information)<br />
32 = net wait level (more information about network waits)<br />
64 = function level (information about function entry and exit)</p></blockquote>
<div class="myt1">4. 运行状态查看</div>
<p>备库上很简单，只有一个状态值，查看备库是否开启了Semi-sync功能：</p>
<pre>
<div class="mycode">show status like "%rpl_semi%";
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+</div>
</pre>
<p>主库需要关注的状态值则比较多</p>
<pre>
<div class="mycode">mysql> show status like "%rpl_semi%";
+--------------------------------------------+---------------+
| Variable_name                              | Value         |
+--------------------------------------------+---------------+
| Rpl_semi_sync_master_clients               | 1             |# 有多少个Semi-sync的备库
| Rpl_semi_sync_master_net_avg_wait_time     | 732           |# 事务提交后，等待备库响应的平均时间
| Rpl_semi_sync_master_net_wait_time         | 1042785285    |# 等待网络响应的总次数
| Rpl_semi_sync_master_net_waits             | 1423323       |# 总的网络等待时间
| Rpl_semi_sync_master_no_times              | 0             |# 一共有几次从Semi-sync跌回普通状态
| Rpl_semi_sync_master_no_tx                 | 0             |# 备库未及时响应的事务数
| Rpl_semi_sync_master_status                | ON            |# 主库上Semi-sync是否正常开启
| Rpl_semi_sync_master_timefunc_failures     | 0             |# 时间函数未正常工作的次数
| Rpl_semi_sync_master_tx_avg_wait_time      | 29059         |# 开启Semi-sync，事务返回需要等待的平均时间
| Rpl_semi_sync_master_tx_wait_time          | 8164966680929 |# 事务等待备库响应的总时间
| Rpl_semi_sync_master_tx_waits              | 280974820     |# 事务等待备库响应的总次数
| Rpl_semi_sync_master_wait_pos_backtraverse | 5499398       |# 改变当前等待最小二进制日志的次数
| Rpl_semi_sync_master_wait_sessions         | 230           |# 当前有几个线程在等备库响应
| Rpl_semi_sync_master_yes_tx                | 16801244      |# Semi-sync模式下，成功的事务数
+--------------------------------------------+---------------+</div>
</pre>
<p>上面比较重要的状态值有：</p>
<p>Rpl_semi_sync_master_tx_avg_wait_time：事务因开启Semi_sync，<strong>平均</strong>需要额外等待的时间</p>
<p>Rpl_semi_sync_master_net_avg_wait_time：事务进入等待队列后，到网络平均等待时间</p>
<p>依据上面两个状态值可以知道，Semi-sync的网络消耗有多大，给某个事务带来的额外的消耗有多大。</p>
<p>Rpl_semi_sync_master_status 则表示当前Semi-sync是否正常工作。</p>
<p>从Rpl_semi_sync_master_no_times变量，可以知道一段时间内，Semi-sync是否有超时失败过，该计数器则记录了这样的失败次数。</p>
<p>比较难理解参数有：</p>
<p><a href="http://dev.mysql.com/doc/refman/5.5/en/server-status-variables.html#statvar_Rpl_semi_sync_master_wait_pos_backtraverse">Rpl_semi_sync_master_wait_pos_backtraverse</a>：这个稍微难理解一点，不过该参数并不重要。</p>
<div class="myt1">5. 关于Rpl_semi_sync_master_wait_pos_backtraverse</div>
<p>花了一些时间弄明白这个变量，继续证实了这个变量确实不重要。</p>
<p>在semisync_master中，维护了这样的两个变量wait_file_name_和wait_file_pos_，当主库上多个事务都在等待备库的响应时，这两个变量记录了所有等待中，最小的那一个Binlog位置。如果这时，一个新的事务加入等待，并且该事务需要等待的Binlog比wait_file_name_和wait_file_pos_还小的话，则更新这两个值，并将Rpl_semi_sync_master_wait_pos_backtraverse值自增一次。</p>
<p>上面的解释参考如下代码段（semisync_master.cc）：</p>
<pre>
<div class="mycode">int cmp = ActiveTranx::compare(trx_wait_binlog_name, trx_wait_binlog_pos,
                               wait_file_name_, wait_file_pos_);
if (cmp <= 0)
{
  /* This thd has a lower position, let's update the minimum info. */
  strcpy(wait_file_name_, trx_wait_binlog_name);
  wait_file_pos_ = trx_wait_binlog_pos;

  rpl_semi_sync_master_wait_pos_backtraverse++;
  if (trace_level_ &#038; kTraceDetail)
    sql_print_information("%s: move back wait position (%s, %lu),",
                          kWho, wait_file_name_, (unsigned long)wait_file_pos_);
}</div>
</pre>
<p>累了，听首歌，伸个懒腰吧:)</p>
<p><script type="text/javascript" src="http://www.xiami.com/widget/player-single?uid=318706&#038;sid=128281&#038;mode=js"></script></p>
<p>广告：<a href="http://www.orczhou.com/index.php/projects/we-are-hunting-mysql-hacker/">我们寻找靠谱的人</a> | <a href="http://www.orczhou.com/index.php/wish-list/">感谢作者</a></p>
<p>参考文献：</p>
<p>1. <a href="http://forge.mysql.com/wiki/ReplicationFeatures/SemiSyncReplication">ReplicationFeatures/SemiSyncReplication</a></p>
<p>2. <a href="http://code.google.com/p/google-mysql-tools/wiki/SemiSyncReplication">SemiSync Replication of Google-mysql-tool</a></p>
<p>3. <a href="http://code.google.com/p/google-mysql-tools/wiki/SemiSyncReplicationDesign">SemiSyncReplicationDesign</a></p>
<p>4. <a href="http://forge.mysql.com/wiki/ReplicationTeam">ReplicationTeam</a></p>
<p>5. <a href="http://dev.mysql.com/doc/refman/5.5/en/replication-semisync.html">MySQL Manual Semisynchronous Replication</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Linux下MySQL 5.5编译安装</title>
		<link>http://www.orczhou.com/index.php/2011/06/compile-and-install-mysql-5-5-from-source/</link>
		<comments>http://www.orczhou.com/index.php/2011/06/compile-and-install-mysql-5-5-from-source/#comments</comments>
		<pubDate>Tue, 21 Jun 2011 16:32:00 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQL5.5]]></category>
		<category><![CDATA[semi-sync]]></category>
		<category><![CDATA[semi-sync replication]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2940</guid>
		<description><![CDATA[<p>之前写过一篇Linux下<a href="http://www.orczhou.com/index.php/2010/06/compile-mysql-from-source/">编译安装MySQL</a>，但是在5.5版本之后MySQL自动化建构工具从<a href="http://www.gnu.org/s/hello/manual/automake/Autotools-Introduction.html">GUN Autotools</a>换成了跨平台的<a href="http://www.cmake.org/">Cmake</a>系统，编译和配置和原来有些不同，这里做一个简单的小结。</p>
<div class="myt1">1. 安装CMake</div>
<p>Cmake是跨平台的工具，如果之前就尝试过在<a href="http://dev.mysql.com/doc/refman/5.1/en/windows-source-build.html">Windows上编译MySQL</a>的同学，就应该还记得CMake。</p>
<p>我的环境是不自带CMake（环境：RHEL5.4，YUM仓库里面没有CMake），所以需要自己安装。安装过程简单、顺利，没有遇到任何依赖问题......:)</p>
<div class="mycode">$tar zxf cmake-2.6.4.tar.gz<br />
$cd cmake-2.6.4<br />
$./bootstrap<br />
$make<br />
$sudo make install
</div>
<p>CMake<a href="http://www.cmake.org/cmake/resources/software.html">下载</a>、<a href="http://www.cmake.org/cmake/help/install.html">安装参考</a>。</p>
<div class="myt1">2. CMake编译MySQL 5.5</div>
<div class="mycode">tar zxf mysql-5.5.11.tar.g<br />
cd mysql-5.5.11<br />
CFLAGS="-O3" CXX=gcc<br />
CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti"<br />
cmake . -LH&#124;more        //CMake下查看MySQL的编译配置<br />
cmake . -DCMAKE_INSTALL_PREFIX=/home/mysql/mysql -DEXTRA_CHARSETS=all<br />
make -j 8        //8核并行编译<br />
make install
</div>
<p>其中"ccmake . -D......"也可直接使用"cmake ."，这样会进入一个简单文本GUI界面进行MySQL编译参数配置；</p>
<p>另外，原来的AutoTools和现在CMake配置参数的变化，在MySQL Forge的<a href="http://forge.mysql.com/wiki/Autotools_to_CMake_Transition_Guide">Autotools to CMake Transition Guide</a>中可以查阅详细的对比说明。<br />
[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/06/compile-and-install-mysql-5-5-from-source/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>之前写过一篇Linux下<a href="http://www.orczhou.com/index.php/2010/06/compile-mysql-from-source/">编译安装MySQL</a>，但是在5.5版本之后MySQL自动化建构工具从<a href="http://www.gnu.org/s/hello/manual/automake/Autotools-Introduction.html">GUN Autotools</a>换成了跨平台的<a href="http://www.cmake.org/">Cmake</a>系统，编译和配置和原来有些不同，这里做一个简单的小结。</p>
<div class="myt1">1. 安装CMake</div>
<p>Cmake是跨平台的工具，如果之前就尝试过在<a href="http://dev.mysql.com/doc/refman/5.1/en/windows-source-build.html">Windows上编译MySQL</a>的同学，就应该还记得CMake。</p>
<p>我的环境是不自带CMake（环境：RHEL5.4，YUM仓库里面没有CMake），所以需要自己安装。安装过程简单、顺利，没有遇到任何依赖问题......:)</p>
<div class="mycode">$tar zxf cmake-2.6.4.tar.gz<br />
$cd cmake-2.6.4<br />
$./bootstrap<br />
$make<br />
$sudo make install
</div>
<p>CMake<a href="http://www.cmake.org/cmake/resources/software.html">下载</a>、<a href="http://www.cmake.org/cmake/help/install.html">安装参考</a>。</p>
<div class="myt1">2. CMake编译MySQL 5.5</div>
<div class="mycode">tar zxf mysql-5.5.11.tar.g<br />
cd mysql-5.5.11<br />
CFLAGS="-O3" CXX=gcc<br />
CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti"<br />
cmake . -LH|more        //CMake下查看MySQL的编译配置<br />
cmake . -DCMAKE_INSTALL_PREFIX=/home/mysql/mysql -DEXTRA_CHARSETS=all<br />
make -j 8        //8核并行编译<br />
make install
</div>
<p>其中"ccmake . -D......"也可直接使用"cmake ."，这样会进入一个简单文本GUI界面进行MySQL编译参数配置；</p>
<p>另外，原来的AutoTools和现在CMake配置参数的变化，在MySQL Forge的<a href="http://forge.mysql.com/wiki/Autotools_to_CMake_Transition_Guide">Autotools to CMake Transition Guide</a>中可以查阅详细的对比说明。<br />
<span id="more-2940"></span></p>
<div class="myt1">3. 编译安装Step by Step</div>
<p>除了上面编译部分不同之外，其他的过程和原来的版本都还是不变的：</p>
<pre>
<div class="mycode"># # # 新建运行MySQL的用户
groupadd dba
useradd -g dba mysql
cp mysql-5.5.11.tar.gz /home/mysql/
chown -R mysql:dba /home/mysql/mysql-5.5.11.tar.gz

# # # 开始编译、安装
su - mysql
tar zxf mysql-5.5.11.tar.gz
cd mysql-5.5.11
CFLAGS="-O3" CXX=gcc
CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti"
cmake . -LH|more        //CMake下查看MySQL的编译配置
cmake . -DCMAKE_INSTALL_PREFIX=/home/mysql/mysql -DEXTRA_CHARSETS=all
make -j 8 &#038;& make install   #-j 表示希望使用cpu核数

# # # 建立配置文件
cd /home/mysql/mysql
su - root
cp mysql/share/mysql/my-medium.cnf /etc/my.cnf
chown -R mysql:dba /etc/my.cnf

# # # 修改配置文件 配置数据文件、日志的路径
su - mysql
vi /etc/my.cnf
basedir = /home/mysql/mysql
datadir = /home/mysql/mysql/data
socket = /home/mysql/mysql/run/mysql.sock
log-error = /home/mysql/mysql/log/alert.log
log_slow_queries = /home/mysql/mysql/log/slow.log

mkdir log run tmp

# # # 初始MySQL配置表（用户表 权限表等）
./scripts/mysql_install_db --basedir=/home/mysql/mysql  --datadir=/home/mysql/mysql/data --user=mysql --force

# # # 启动MySQL
./bin/mysqld_safe &#038;</div>
</pre>
<p>参考：</p>
<p>1. <a href="http://forge.mysql.com/wiki/CMake">MySQL Forge::CMake</a></p>
<p>2. <a href="http://forge.mysql.com/wiki/Autotools_to_CMake_Transition_Guide">Autotools to CMake Transition Guide</a></p>
<p>3. <a href="http://www.orczhou.com/index.php/2010/06/compile-mysql-from-source/">编译安装MySQL</a></p>
<p>4. <a href="http://dev.mysql.com/doc/refman/5.5/en/source-configuration-options.html">MySQL Source-Configuration Options</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/06/compile-and-install-mysql-5-5-from-source/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MySQL Federated引擎实现多主一备</title>
		<link>http://www.orczhou.com/index.php/2011/04/mysql-federated-multiple-master-single-slave/</link>
		<comments>http://www.orczhou.com/index.php/2011/04/mysql-federated-multiple-master-single-slave/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 15:50:39 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Federated]]></category>
		<category><![CDATA[multiple master]]></category>
		<category><![CDATA[single slave]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2893</guid>
		<description><![CDATA[多主一丛,multiple master, single slave[......]<p class='read-more'><a href='http://www.orczhou.com/index.php/2011/04/mysql-federated-multiple-master-single-slave/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>偶尔我们需要这样做。</p>
<p>在一台主机上如果复制多个主库，可以很简单：在备库主机上启动多个MySQL实例（<a href="http://dev.mysql.com/doc/refman/5.1/en/mysqld-multi.html">mysqld_muilt</a>），每个实例使用一个端口，复制多台主库就可以了。但是如果希望复制过来的数据都在同一个实例中，事情就复杂了。</p>
<div class="myt1">1. 问题以及开源社区的尝试</div>
<p>需求：多个主库都复制到一个备库，<strong>复制过来的数据都在一个实例中</strong>，这样实现对应用层的透明。目前，MySQL本身不提供这样的功能(<a href="http://forge.mysql.com/worklog/task.php?id=1697">考虑过，但一直未实现</a>)。</p>
<p><span style="color:blue">1.1</span> 开源社区也有很多方案和想法，例如Tungsten replicator：可以支持异构数据复制，JAVA实现，数据量较大时，性能较差，而且MySQL版本更新较快，而该软件支持较慢；</p>
<p><span style="color:blue">1.2</span> 再如<a href="http://www.penglixun.com/tech/program/how_to_mysql_multi_master.html">P.Linux的尝试</a>：通过拉取多个主库上的Binlog在单个备库上应用的方式，对MySQL没有入侵，实现也较为简单。</p>
<p><span style="color:blue">1.3</span> <a href="http://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/0596101716">High Performance MySQL</a>还可以通过多级复制的方式实现：例如有主库DB1、DB2，都需要复制到S1上，则先配置D2复制D1的全部数据，然后再从S1上复制D2的全部数据就可以了。整理需要注意D2上的<a href="http://dev.mysql.com/doc/refman/5.0/en/replication-options-slave.html#option_mysqld_log-slave-updates">log-slave-update</a>需要打开，为了减少D2的压力，DB上复制过来的表可以全部使用<a href="http://dev.mysql.com/doc/refman/5.1/en/blackhole-storage-engine.html">Blackhole引擎</a>。</p>
<p><span style="color:blue">1.4 </span>另外，还有一些<a href="http://shinguz.blogspot.com/2008/10/mysql-multi-master-single-slave.html">欠成熟的Patch</a>实现。</p>
<div class="myt1">2. MySQL Federated引擎的“软链接”特性</div>
<p><a href="http://dev.mysql.com/doc/refman/5.1/en/federated-storage-engine.html">Federated引擎</a>可以在本地数据库中创建一个远端数据表的“软链接”。这样，访问远端数据表就如同访问本地数据表。（这里远端可以是不同主机上的不同实例）</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5619434764/" title="se-federated-structure by orczhou, on Flickr"><img src="http://farm6.static.flickr.com/5309/5619434764_bfd3966949.jpg" width="475" height="269" alt="se-federated-structure"></a></p>
<div class="myt1">3. 使用Federated数据表实现多主一备</div>
<p>例如，主库DB1，DB2，都需要复制到S1上，这里DB1，DB2，S1分别在主机H1，H2，H3上。首先，在主机H3(S1所在的主机)上其另外起两个MySQL实例S2、S3，分别复制主库DB1和DB2，然后在实例S1上建立多个Federated表关联S2、S3中的数据表（相当于在S1中建立到S2、S3的软连接）。</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5618939777/" title="Federated-Muilt-master by orczhou, on Flickr"><img src="http://farm6.static.flickr.com/5063/5618939777_2b3daaa899.jpg" width="500" height="439" alt="Federated-Muilt-master"></a></p>
<p>这时应用，连接到S1，就可以<strong>同时透明的</strong>访问到DB1、DB2中的<strong>实时</strong>数据表了。</p>
<div class="myt1">4. 一些说明</div>
<p><span style="color:blue">4.1</span> 上面描述的方法，也可以直接在S1上建立到DB1、DB2各个表的软连接，但是为了最大程度的减少对主库的影响，最好如上多配一层备库。</p>
<p><span style="color:blue">4.2</span> 最简单的可以直接在备库上配置多个实例，让应用连接多个实例就好了，无需上面这么复制的配置。</p>
<p>参考文献：</p>
<p>1. <a href="http://dev.mysql.com/doc/refman/5.1/en/federated-storage-engine.html">MySQL Manual: The FEDERATED Storage Engine</a></p>
<p>2. <a href="http://forums.mysql.com/read.php?26,238241,256703#msg-256703">Post of MySQL Forums : Multiple masters to single slave</a></p>
<p>3. <a href="http://bbs.chinaunix.net/viewthread.php?tid=1487796">通过tungsten replicator实现mysql多主一从的备份架构</a></p>
<p>4. <a href="http://stackoverflow.com/questions/1576603/is-it-possible-to-do-n-master-1-slave-replication-with-mysql">Is it possible to do N-master => 1-slave replication with MySQL</a></p>
<p>5. <a href="http://shinguz.blogspot.com/2008/10/mysql-multi-master-single-slave.html">MySQL Multi-Master – Single-Slave – Replication </a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/04/mysql-federated-multiple-master-single-slave/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>格式化输出SQL</title>
		<link>http://www.orczhou.com/index.php/2011/03/php-sql-format/</link>
		<comments>http://www.orczhou.com/index.php/2011/03/php-sql-format/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 14:37:04 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[代码细节]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2858</guid>
		<description><![CDATA[SQL Format,Open Source,SQL Beautifier[......]<p class='read-more'><a href='http://www.orczhou.com/index.php/2011/03/php-sql-format/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>工作中，经常需要在web页面中把SQL（MySQL）展示给开发人员，如果SQL不格式话，例如：</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5514359889/" title="sqlsample_1 by orczhou, on Flickr"><img src="http://farm6.static.flickr.com/5097/5514359889_820fb63088.jpg" width="320" height="205" alt="sqlsample_1" /></a></p>
<p>上面的SQL，咋一眼，很难看出SQL的目的是什么。而格式化的输出可以让SQL更易读懂，如：</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5366693389/" title="screenshot-sqlparser by orczhou, on Flickr"><img src="http://farm6.static.flickr.com/5170/5366693389_6f140df551.jpg" width="401" height="273" alt="screenshot-sqlparser" /></a></p>
<p>上周末做了一个简单的<a href="http://www.orczhou.com/sqlparser/sqlbeautifier/index.php">PHP SQL Format</a>工具，可以实现上述功能，这里简单的介绍如何使用<a href="http://www.orczhou.com/sqlparser/sqlbeautifier/index.php">PHP SQL Format</a>（也可以参考<a href="http://www.orczhou.com/sqlparser/">这里</a>）。</p>
<div class="myt1">1. 下载<a href="http://code.google.com/p/php-sqlformat/downloads/list">相关文件</a>并解压到你的WEB目录</div>
<p>有如下文件:</p>
<p><img src="http://www.orczhou.com/wp-content/uploads/2011/03/libfiles.png" alt="" title="libfiles" width="260" height="157" class="alignleft size-full wp-image-2865" /></p>
<p>将这些文件都放入web目录下的sqlparserlib目录下。</p>
<div class="myt1">2. 编写如下PHP/HTML代码</div>
<pre>
<div class="mycode">&#60;link rel="stylesheet" type="text/css" href="sqlparserlib/sqlsyntax.css" /&#62;
&#60;?php
     define('PARSER_LIB_ROOT', "/opt/www/sqlparserlib/");
     require_once PARSER_LIB_ROOT.'sqlparser.lib.php';
     function SQLFormatPHP($sql){
        return PMA_SQP_formatHtml(PMA_SQP_parse($sql));
     }
     $sql = "SELECT  FROM (select  from dual)";
     echo SQLFormatPHP($sql);
 ?&#62;
</div>
</pre>
<p>只要把上面php代码中的$sql改成你的输入SQL就OK了。</p>
<div class="myt1">3. 需要注意的问题</div>
<p>* 上面的代码中，路径一定要注意，在你的代码中也必须引用正确的路径</p>
<p>* 上面的sqlsyntax.css定义了很多CSS，注意不要与你的CSS冲突了</p>
<p>* 上面require_once很多函数，注意不要与你的函数冲突了</p>
<div class="myt1">4. 实现说明</div>
<p>这里使用的代码包<a href="http://www.phpmyadmin.net/phpdoc/phpMyAdmin/_libraries---sqlparser.lib.php.html">sqlparser.lib.php</a>来自<a href="http://www.phpmyadmin.net/">phpMyAdmin</a>，稍微做了一些改动，让这块代码能够独立使用。</p>
<p>看了<a href="http://stackoverflow.com/questions/2078661/use-php-to-format-an-input-sql-query-as-html">Stackoverflow</a>上很多朋友也有类似问题，所以就花了几个小时的尝试，把<a href="http://www.phpmyadmin.net/">phpMyAdmin</a>里面SQL Parser相关的代码独立出来，lib中有很多的代码都应该是无用的，我并没有做精简，所以你最求效率的话，可能需要自己再优化一下。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/03/php-sql-format/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

