﻿<?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-xiaomage234-随笔分类-db tools</title><link>http://www.blogjava.net/xiaomage234/category/28166.html</link><description>生命本就是一次凄美的漂流，记忆中放不下的，永远是孩提时代的那一份浪漫与纯真！</description><language>zh-cn</language><lastBuildDate>Wed, 13 Feb 2019 15:21:40 GMT</lastBuildDate><pubDate>Wed, 13 Feb 2019 15:21:40 GMT</pubDate><ttl>60</ttl><item><title>MySQL加锁分析【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2019/02/13/433636.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 13 Feb 2019 09:07:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2019/02/13/433636.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/433636.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2019/02/13/433636.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/433636.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/433636.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:http://www.fanyilun.me/2017/04/20/MySQL%E5%8A%A0%E9%94%81%E5%88%86%E6%9E%90/MySQL加锁分析目录前言MySQL的锁如何查看事务的加锁情况不同语句的加锁情况1. 查询命中聚簇索引（主键索引）2. 查询命中唯一索引3. 查询命中二级索引（非唯一索引）4. 查询没有命中索引5. 对索引键值有修改6. 插入数据隐式锁一...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2019/02/13/433636.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/433636.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2019-02-13 17:07 <a href="http://www.blogjava.net/xiaomage234/archive/2019/02/13/433636.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL 小心使用 replace into【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2018/12/25/433561.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 25 Dec 2018 11:19:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2018/12/25/433561.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/433561.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2018/12/25/433561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/433561.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/433561.html</trackback:ping><description><![CDATA[<p data-spm-anchor-id="a2c4e.11153940.blogcont57855.i1.46fe7101Rdg0IU" style="box-sizing: border-box; margin: 0px 0px 32px; padding: 20px 32px; background: #f9f9f9; font-size: 12px; color: #73777a; line-height: 24px; overflow: hidden; overflow-wrap: break-word; word-break: break-all; font-family: PingFangSC, &quot;helvetica neue&quot;, &quot;hiragino sans gb&quot;, arial, &quot;microsoft yahei ui&quot;, &quot;microsoft yahei&quot;, simsun, sans-serif;"><span data-spm-anchor-id="a2c4e.11153940.blogcont57855.i5.46fe7101Rdg0IU" style="box-sizing: border-box; font-weight: 700; color: #373d41;">摘要：</span>&nbsp;MySQL replace into 错误案例 背景 * MySQL5.7 * ROW模式 * 表结构 CREATE TABLE `test` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `col_1` varc</p><div markdown-body"="" style="box-sizing: border-box; margin: 0px; text-size-adjust: 100%; color: #24292e; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 32px; overflow-wrap: break-word; overflow: hidden; word-break: break-all;"><h1>MySQL replace into 错误案例</h1><h2>背景</h2><pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code perl"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;">* MySQL5.<span style="box-sizing: border-box; color: #ae81ff;">7</span>  * ROW模式   * 表结构 CREATE TABLE <span style="box-sizing: border-box; color: #e6db74;">`test`</span> (   <span style="box-sizing: border-box; color: #e6db74;">`id`</span> <span style="box-sizing: border-box; color: #f92672;">int</span>(<span style="box-sizing: border-box; color: #ae81ff;">10</span>) unsigned NOT NULL AUTO_INCREMENT,   <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_2`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_3`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   PRIMARY KEY (<span style="box-sizing: border-box; color: #e6db74;">`id`</span>),   UNIQUE KEY <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> (<span style="box-sizing: border-box; color: #e6db74;">`col_1`</span>) ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 </code></pre><h2>错误场景一</h2><blockquote style="box-sizing: border-box; padding: 0px 1em; margin: 0px 0px 16px; font-size: 17.5px; border-left-width: 0.25em; border-left-color: #dfe2e5; color: #6a737d;"><p data-spm-anchor-id="a2c4e.11153940.blogcont57855.i3.46fe7101Rdg0IU" style="box-sizing: border-box; margin: 0px; padding: 0px;">其他字段value莫名其妙的没了</p></blockquote><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">step1 初始化记录</span></li></ul><pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code ruby"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;"><span style="box-sizing: border-box; color: #66d9ef;">mater:</span>lc&gt; REPLACE INTO test (col_1,col_2,col_3) values(<span style="box-sizing: border-box; color: #e6db74;">'a'</span>,<span style="box-sizing: border-box; color: #e6db74;">'a'</span>,<span style="box-sizing: border-box; color: #e6db74;">'a'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">1</span> row affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec) --注意，这里是影响了<span style="box-sizing: border-box; color: #ae81ff;">1</span>条记录  <span style="box-sizing: border-box; color: #66d9ef;">master:</span>lc&gt; REPLACE INTO test (col_1,col_2,col_3) values(<span style="box-sizing: border-box; color: #e6db74;">'b'</span>,<span style="box-sizing: border-box; color: #e6db74;">'b'</span>,<span style="box-sizing: border-box; color: #e6db74;">'b'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">1</span> row affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec) --注意，这里是影响了<span style="box-sizing: border-box; color: #ae81ff;">1</span>条记录  <span style="box-sizing: border-box; color: #66d9ef;">master:</span>lc&gt; REPLACE INTO test (col_1,col_2,col_3) values(<span style="box-sizing: border-box; color: #e6db74;">'c'</span>,<span style="box-sizing: border-box; color: #e6db74;">'c'</span>,<span style="box-sizing: border-box; color: #e6db74;">'c'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">1</span> row affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec) --注意，这里是影响了<span style="box-sizing: border-box; color: #ae81ff;">1</span>条记录   master &gt; show create table test  <span style="box-sizing: border-box;">| test  |</span> CREATE TABLE <span style="box-sizing: border-box; color: #e6db74;">`test`</span> (   <span style="box-sizing: border-box; color: #e6db74;">`id`</span> int(<span style="box-sizing: border-box; color: #ae81ff;">10</span>) unsigned NOT NULL AUTO_INCREMENT,   <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_2`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_3`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   PRIMARY KEY (<span style="box-sizing: border-box; color: #e6db74;">`id`</span>),   UNIQUE KEY <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> (<span style="box-sizing: border-box; color: #e6db74;">`col_1`</span>) ) ENGINE=InnoDB AUTO_INCREMENT=<span style="box-sizing: border-box; color: #ae81ff;">4</span> DEFAULT CHARSET=utf8 <span style="box-sizing: border-box;">|   mater &gt; select * from test; +----+-------+-------+-------+ |</span> id <span style="box-sizing: border-box;">| col_1 |</span> col_2 <span style="box-sizing: border-box;">| col_3 |</span> +----+-------+-------+-------+ <span style="box-sizing: border-box;">|  1 |</span> a     <span style="box-sizing: border-box;">| a     |</span> a     <span style="box-sizing: border-box;">| |</span>  <span style="box-sizing: border-box; color: #ae81ff;">2</span> <span style="box-sizing: border-box;">| b     |</span> b     <span style="box-sizing: border-box;">| b     |</span> <span style="box-sizing: border-box;">|  3 |</span> c     <span style="box-sizing: border-box;">| c     |</span> c     <span style="box-sizing: border-box;">| +----+-------+-------+-------+ 3 rows <span style="box-sizing: border-box; color: #f92672;">in</span> set (0.00 sec)  </span></code></pre><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">step2 构造错误场景</span></li></ul><pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code ruby"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;"><span style="box-sizing: border-box; color: #66d9ef;">master:</span>lc&gt; replace into test(col_1,col_2) values(<span style="box-sizing: border-box; color: #e6db74;">'c'</span>,<span style="box-sizing: border-box; color: #e6db74;">'cc'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">2</span> rows affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec)  <span style="box-sizing: border-box; color: #66d9ef;">dba:</span>lc&gt; select * from test; +----+-------+-------+-------+ <span style="box-sizing: border-box;">| id |</span> col_1 <span style="box-sizing: border-box;">| col_2 |</span> col_3 <span style="box-sizing: border-box;">| +----+-------+-------+-------+ |</span>  <span style="box-sizing: border-box; color: #ae81ff;">1</span> <span style="box-sizing: border-box;">| a     |</span> a     <span style="box-sizing: border-box;">| a     |</span> <span style="box-sizing: border-box;">|  2 |</span> b     <span style="box-sizing: border-box;">| b     |</span> b     <span style="box-sizing: border-box;">| |</span>  <span style="box-sizing: border-box; color: #ae81ff;">4</span> <span style="box-sizing: border-box;">| c     |</span> cc    <span style="box-sizing: border-box;">| NULL  |</span> +----+-------+-------+-------+ <span style="box-sizing: border-box; color: #ae81ff;">3</span> rows <span style="box-sizing: border-box; color: #f92672;">in</span> set (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec)  </code></pre><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">总结</span></li></ul><ol style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;">col_3 的值，从原来的c，变成了NULL，天呐，数据不见了。 id 也变了。</li><li style="box-sizing: border-box; margin: 0.25em 0px 0px; padding: 0px;">用户原本的需求，应该是如果col_1='c' 存在，那么就改变col_2='cc'，其余的记录保持不变，结果id,col_3都变化了</li><li style="box-sizing: border-box; margin: 0.25em 0px 0px; padding: 0px;">解决方案就是：将replace into 改成 INSERT INTO &#8230; ON DUPLICATE KEY UPDATE</li></ol><p style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px;">但是你以为这样就完美的解决了吗？ 马上就会带来另外一场灾难，请看下面的错误场景</p><h2>错误场景二</h2><blockquote style="box-sizing: border-box; padding: 0px 1em; margin: 0px 0px 16px; font-size: 17.5px; border-left-width: 0.25em; border-left-color: #dfe2e5; color: #6a737d;"><p style="box-sizing: border-box; margin: 0px; padding: 0px;">ERROR 1062 (23000): Duplicate entry 'x' for key 'PRIMARY'</p></blockquote><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">step1 初始化记录</span></li></ul><pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code perl"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;"> mater:<span style="box-sizing: border-box; color: #f92672;">lc</span>&gt; REPLACE INTO test (col_1,col_2) <span style="box-sizing: border-box; color: #f92672;">values</span>(<span style="box-sizing: border-box; color: #e6db74;">'a'</span>,<span style="box-sizing: border-box; color: #e6db74;">'a'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">1</span> row affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec) --注意，这里是影响了<span style="box-sizing: border-box; color: #ae81ff;">1</span>条记录  master:<span style="box-sizing: border-box; color: #f92672;">lc</span>&gt; REPLACE INTO test (col_1,col_2) <span style="box-sizing: border-box; color: #f92672;">values</span>(<span style="box-sizing: border-box; color: #e6db74;">'b'</span>,<span style="box-sizing: border-box; color: #e6db74;">'b'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">1</span> row affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec) --注意，这里是影响了<span style="box-sizing: border-box; color: #ae81ff;">1</span>条记录  master:<span style="box-sizing: border-box; color: #f92672;">lc</span>&gt; REPLACE INTO test (col_1,col_2) <span style="box-sizing: border-box; color: #f92672;">values</span>(<span style="box-sizing: border-box; color: #e6db74;">'c'</span>,<span style="box-sizing: border-box; color: #e6db74;">'c'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">1</span> row affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec) --注意，这里是影响了<span style="box-sizing: border-box; color: #ae81ff;">1</span>条记录   master &gt; show create table test  | test  | CREATE TABLE <span style="box-sizing: border-box; color: #e6db74;">`test`</span> (   <span style="box-sizing: border-box; color: #e6db74;">`id`</span> <span style="box-sizing: border-box; color: #f92672;">int</span>(<span style="box-sizing: border-box; color: #ae81ff;">10</span>) unsigned NOT NULL AUTO_INCREMENT,   <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_2`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   PRIMARY KEY (<span style="box-sizing: border-box; color: #e6db74;">`id`</span>),   UNIQUE KEY <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> (<span style="box-sizing: border-box; color: #e6db74;">`col_1`</span>) ) ENGINE=InnoDB AUTO_INCREMENT=<span style="box-sizing: border-box; color: #ae81ff;">4</span> DEFAULT CHARSET=utf8 |   slave &gt; show create table test  | test  | CREATE TABLE <span style="box-sizing: border-box; color: #e6db74;">`test`</span> (   <span style="box-sizing: border-box; color: #e6db74;">`id`</span> <span style="box-sizing: border-box; color: #f92672;">int</span>(<span style="box-sizing: border-box; color: #ae81ff;">10</span>) unsigned NOT NULL AUTO_INCREMENT,   <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_2`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   PRIMARY KEY (<span style="box-sizing: border-box; color: #e6db74;">`id`</span>),   UNIQUE KEY <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> (<span style="box-sizing: border-box; color: #e6db74;">`col_1`</span>) ) ENGINE=InnoDB AUTO_INCREMENT=<span style="box-sizing: border-box; color: #ae81ff;">4</span> DEFAULT CHARSET=utf8 |</code></pre><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">step2 构造错误场景</span></li></ul><pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code ruby"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;">* master  <span style="box-sizing: border-box; color: #66d9ef;">mater:</span>lc&gt; REPLACE INTO test (col_1,col_2) values(<span style="box-sizing: border-box; color: #e6db74;">'c'</span>,<span style="box-sizing: border-box; color: #e6db74;">'cc'</span>); Query OK, <span style="box-sizing: border-box; color: #ae81ff;">2</span> rows affected (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec)  --注意，这里是影响了两条记录  <span style="box-sizing: border-box; color: #66d9ef;">mater:</span>lc&gt; show create table test  <span style="box-sizing: border-box;">| test  |</span> CREATE TABLE <span style="box-sizing: border-box; color: #e6db74;">`test`</span> (   <span style="box-sizing: border-box; color: #e6db74;">`id`</span> int(<span style="box-sizing: border-box; color: #ae81ff;">10</span>) unsigned NOT NULL AUTO_INCREMENT,   <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_2`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   PRIMARY KEY (<span style="box-sizing: border-box; color: #e6db74;">`id`</span>),   UNIQUE KEY <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> (<span style="box-sizing: border-box; color: #e6db74;">`col_1`</span>) ) ENGINE=InnoDB AUTO_INCREMENT=<span style="box-sizing: border-box; color: #ae81ff;">5</span> DEFAULT CHARSET=utf8 <span style="box-sizing: border-box;">|  master:lc&gt; select * from test +----+-------+-------+ |</span> id <span style="box-sizing: border-box;">| col_1 |</span> col_2 <span style="box-sizing: border-box;">| +----+-------+-------+ |</span>  <span style="box-sizing: border-box; color: #ae81ff;">1</span> <span style="box-sizing: border-box;">| a     |</span> a     <span style="box-sizing: border-box;">| |</span>  <span style="box-sizing: border-box; color: #ae81ff;">2</span> <span style="box-sizing: border-box;">| b     |</span> b     <span style="box-sizing: border-box;">| |</span>  <span style="box-sizing: border-box; color: #ae81ff;">4</span> <span style="box-sizing: border-box;">| c     |</span> cc    <span style="box-sizing: border-box;">| +----+-------+-------+ 3 rows <span style="box-sizing: border-box; color: #f92672;">in</span> set (0.00 sec)  * slave  slave:lc&gt; show create table test  |</span> test  <span style="box-sizing: border-box;">| CREATE TABLE `test` (   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   `col_1` varchar(100) DEFAULT NULL,   `col_2` varchar(100) DEFAULT NULL,   PRIMARY KEY (`id`),   UNIQUE KEY `col_1` (`col_1`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |</span>  <span style="box-sizing: border-box; color: #66d9ef;">slave:</span>lc&gt; select * from test +----+-------+-------+ <span style="box-sizing: border-box;">| id |</span> col_1 <span style="box-sizing: border-box;">| col_2 |</span> +----+-------+-------+ <span style="box-sizing: border-box;">|  1 |</span> a     <span style="box-sizing: border-box;">| a     |</span> <span style="box-sizing: border-box;">|  2 |</span> b     <span style="box-sizing: border-box;">| b     |</span> <span style="box-sizing: border-box;">|  4 |</span> c     <span style="box-sizing: border-box;">| cc    |</span> +----+-------+-------+ <span style="box-sizing: border-box; color: #ae81ff;">3</span> rows <span style="box-sizing: border-box; color: #f92672;">in</span> set (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec) </code></pre><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">step3 错误案例产生</span></li></ul><pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code perl"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;">* 假设有一天，master 挂了， 由slave 提升为 new mater  原slave:<span style="box-sizing: border-box; color: #f92672;">lc</span>&gt; show create table test  | test  | CREATE TABLE <span style="box-sizing: border-box; color: #e6db74;">`test`</span> (   <span style="box-sizing: border-box; color: #e6db74;">`id`</span> <span style="box-sizing: border-box; color: #f92672;">int</span>(<span style="box-sizing: border-box; color: #ae81ff;">10</span>) unsigned NOT NULL AUTO_INCREMENT,   <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   <span style="box-sizing: border-box; color: #e6db74;">`col_2`</span> varchar(<span style="box-sizing: border-box; color: #ae81ff;">100</span>) DEFAULT NULL,   PRIMARY KEY (<span style="box-sizing: border-box; color: #e6db74;">`id`</span>),   UNIQUE KEY <span style="box-sizing: border-box; color: #e6db74;">`col_1`</span> (<span style="box-sizing: border-box; color: #e6db74;">`col_1`</span>) ) ENGINE=InnoDB AUTO_INCREMENT=<span style="box-sizing: border-box; color: #ae81ff;">4</span> DEFAULT CHARSET=utf8 |  原slave:<span style="box-sizing: border-box; color: #f92672;">lc</span>&gt; <span style="box-sizing: border-box; color: #f92672;">select</span> * from test +----+-------+-------+ | id | col_1 | col_2 | +----+-------+-------+ |  <span style="box-sizing: border-box; color: #ae81ff;">1</span> | a     | a     | |  <span style="box-sizing: border-box; color: #ae81ff;">2</span> | b     | b     | |  <span style="box-sizing: border-box; color: #ae81ff;">4</span> | c     | cc    | +----+-------+-------+ <span style="box-sizing: border-box; color: #ae81ff;">3</span> rows in set (<span style="box-sizing: border-box; color: #ae81ff;">0</span>.<span style="box-sizing: border-box; color: #ae81ff;">00</span> sec)   ===注意==  root:<span style="box-sizing: border-box; color: #f92672;">lc</span>&gt; REPLACE INTO test (col_1,col_2) <span style="box-sizing: border-box; color: #f92672;">values</span>(<span style="box-sizing: border-box; color: #e6db74;">'d'</span>,<span style="box-sizing: border-box; color: #e6db74;">'d'</span>); ERROR <span style="box-sizing: border-box; color: #ae81ff;">1062</span> (<span style="box-sizing: border-box; color: #ae81ff;">23000</span>): Duplicate entry <span style="box-sizing: border-box; color: #e6db74;">'4'</span> <span style="box-sizing: border-box; color: #f92672;">for</span> key <span style="box-sizing: border-box; color: #e6db74;">'PRIMARY'</span>  </code></pre><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">总结</span></li></ul><pre data-spm-anchor-id="a2c4e.11153940.blogcont57855.i4.46fe7101Rdg0IU" style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code markdown"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;"><span style="box-sizing: border-box; color: #ae81ff;">* </span>Row 模式，主从情况下，replace into 和 INSERT INTO &#8230; ON DUPLICATE KEY UPDATE 都会导致以上问题的发生 <span style="box-sizing: border-box; color: #ae81ff;">* </span>解决方案： 最后可以通过alter table auto_increment值解决，但是这样已经造成mater的表很长时间没有写入了。。。</code></pre><h2>最后总结</h2><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">replace with unique key</span></li></ul><pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px;"><code sql"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;">1. 禁止 <span style="box-sizing: border-box; color: #f92672;">replace</span> <span style="box-sizing: border-box; color: #f92672;">into</span> (错误一，错误二 都会发生) <span style="box-sizing: border-box; color: #ae81ff;">2.</span> 禁止 <span style="box-sizing: border-box; color: #f92672;">INSERT</span> <span style="box-sizing: border-box; color: #f92672;">INTO</span> &#8230; <span style="box-sizing: border-box; color: #f92672;">ON</span> <span style="box-sizing: border-box; color: #f92672;">DUPLICATE</span> <span style="box-sizing: border-box; color: #f92672;">KEY</span> <span style="box-sizing: border-box; color: #f92672;">UPDATE</span> （错误二 会发生）</code></pre><ul style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 0px 0px 2em; list-style-position: initial; list-style-image: initial;"><li style="box-sizing: border-box; margin: 0px; padding: 0px;"><span style="box-sizing: border-box; font-weight: 600;">replace with primary key</span></li></ul><pre data-spm-anchor-id="a2c4e.11153940.blogcont57855.i6.46fe7101Rdg0IU" style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; padding: 16px; margin-top: 0px; line-height: 1.45; color: #f8f8f2; word-break: break-all; overflow-wrap: normal; background-color: #333333; border: 1px solid #cccccc; border-radius: 3px; margin-bottom: 0px !important;"><code sql"="" style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, &quot;Liberation Mono&quot;, Menlo, Courier, monospace; font-size: 13.6px; background: transparent; border-radius: 3px; padding: 0px; margin: 0px; display: inline; overflow: visible; word-break: normal; border: 0px; line-height: inherit; overflow-wrap: normal;">1. 禁止 <span style="box-sizing: border-box; color: #f92672;">replace</span> <span style="box-sizing: border-box; color: #f92672;">into</span> (会发生错误场景一的案例，丢失部分字段数据) <span style="box-sizing: border-box; color: #ae81ff;">2.</span> 可以使用<span style="box-sizing: border-box; color: #f92672;">INSERT</span> <span style="box-sizing: border-box; color: #f92672;">INTO</span> &#8230; <span style="box-sizing: border-box; color: #f92672;">ON</span> <span style="box-sizing: border-box; color: #f92672;">DUPLICATE</span> <span style="box-sizing: border-box; color: #f92672;">KEY</span> <span style="box-sizing: border-box; color: #f92672;">UPDATE</span> 代替 <span style="box-sizing: border-box; color: #f92672;">replace</span> <span style="box-sizing: border-box; color: #f92672;">into</span></code></pre></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/433561.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2018-12-25 19:19 <a href="http://www.blogjava.net/xiaomage234/archive/2018/12/25/433561.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL 开发实践 8 问，你能 hold 住几个？【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2018/12/03/433534.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 03 Dec 2018 07:55:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2018/12/03/433534.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/433534.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2018/12/03/433534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/433534.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/433534.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:https://cloud.tencent.com/developer/article/1004475最近研发的项目对 DB 依赖比较重，梳理了这段时间使用MySQL遇到的8个比较具有代表性的问题，答案也比较偏自己的开发实践，没有 DBA专业和深入，有出入的请使劲拍砖！MySQL读写性能是多少，有哪些性能相关的配置参数？MySQL负载高时，如何找到是由哪些SQL引起的？如何针对具体的SQ...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2018/12/03/433534.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/433534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2018-12-03 15:55 <a href="http://www.blogjava.net/xiaomage234/archive/2018/12/03/433534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐几本学习MySQL的好书【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2018/12/03/433533.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 03 Dec 2018 07:54:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2018/12/03/433533.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/433533.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2018/12/03/433533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/433533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/433533.html</trackback:ping><description><![CDATA[from:http://mingxinglai.com/cn/2015/12/material-of-mysql/<br /><br /><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">我这里推荐几本MySQL的好书，应该能够有效避免学习MySQL的弯路，并且达到一个不错的水平。 我这里推荐的书或材料分为两个部分，分别是MySQL的使用和MySQL的源码学习。在介绍的过程中，我会穿插简单的评语或感想。</p><h2>1.MySQL的使用</h2><h4>1.1 MySQL技术内幕:InnoDB存储引擎</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">学习MySQL的使用，首推姜承尧的《MySQL技术内幕:InnoDB存储引擎》，当然不是因为姜sir是我的经理才推荐这本书。这本书确实做到了由渐入深、深入浅出，是中国人写的最赞的MySQL技术书籍，符合国人的思维方式和阅读习惯，而且，这本书简直就是面试宝典，对于近期有求职MySQL相关岗位的朋友，可以认真阅读，对找工作有很大的帮助。当然，也有人说这本书入门难度较大，这个就自己取舍了，个人建议就以这本书入门即可，有不懂的地方可以求助官方手册和google。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-1.jpg" alt="MySQL技术内幕" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><h4>1.2 MySQL的官方手册</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">我刚开始学习MySQL的时候误区就是，没有好好阅读MySQL的官方手册。例如，我刚开始很难理解InnoDB的锁，尤其是各个情况下如何加锁，这个问题在我师弟进入百度做DBA时，也困扰了他一阵子，我们两还讨论来讨论去，其实，MySQL官方手册已经写得清清楚楚，什么样的SQL语句加什么样的锁，当然，MySQL的官方手册非常庞大，一时半会很难看完，建议先看InnoDB相关的部分。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><a href="http://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">http://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html</a></p><h4>1.3 MySQL排错指南</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">《<a href="http://book.douban.com/subject/26591051/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">MySQL排错指南</a>》是2015年夏天引入中国的书籍，这本书可以说是DBA速成指南，介绍的内容其实比较简单，但是也非常实用，对于DBA这个讲究经验的工种，这本书就是传授经验的，可能对有较多工作经验的DBA来说，这本书基本没有什么用，但是，对于刚入职场的新人，或学校里的学生，这本书会有较大的帮助，非常推荐。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-2.jpg" alt="MySQL排错指南" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><h4>1.4 高性能MySQL</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">《<a href="http://book.douban.com/subject/23008813/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">高性能MySQL</a>》是MySQL领域的经典之作，拥有广泛的影响力，学习MySQL的朋友都应该有所耳闻，所以我就不作过多介绍，唯一的建议就是仔细看、认真看、多看几遍，我每次看都会有不小的收获。这就是一本虽然书很厚，但是需要一页一页、一行一行都认真看的书。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-3.jpg" alt="高性能MySQL" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><h4>1.5 数据库索引设计与优化</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">如果认真学习完前面几本书，基本上都已经对MySQL掌握得不错了，但是，如果不了解如何设计一个好的索引，仍然不能成为牛逼的DBA，牛逼的DBA和不牛逼的DBA，一半就是看对索引的掌握情况，《<a href="http://book.douban.com/subject/26419771/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">数据库索引设计与优化</a>》就是从普通DBA走向牛逼DBA的捷径，这本书在淘宝内部非常推崇，但是在中国名气却不是很大，很多人不了解。这本书也是今年夏天刚有中文版本的，非常值得入手以后跟着练习，虽然知道的人不多，豆瓣上也几乎没有什么评价，但是，强烈推荐、吐血推荐！</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-4.jpg" alt="数据库索引设计与优化" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><h4>1.6 Effective MySQL系列</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">《<a href="http://book.douban.com/subject/11653424/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">Effective MySQL系列</a>》是指:</p><ul style="padding: 0px; margin: 0px; border: none; outline: none; list-style-position: inside; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><li style="padding: 0.2em 0px; margin: 0px; border: none; outline: none;">Effective MySQL Replication Techniques in Depth</li><li style="padding: 0.2em 0px; margin: 0px; border: none; outline: none;">Effective MySQL之SQL语句最优化</li><li style="padding: 0.2em 0px; margin: 0px; border: none; outline: none;">Effective MySQL之备份与恢复</li></ul><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-5.jpg" alt="effective" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">这一系列并不如前面推荐的好，其中，我只看了前两本，这几本书只能算是小册子，如果有时间可以看看，对某一个&#8221;模块&#8221;进入深入了解。</p><h2>2.MySQL的源码</h2><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">关于MySQL源码的书非常少，还好现在市面上有两本不错的书，而且刚好一本讲server层，一本讲innodb存储引擎层，对于学习MySQL源码会很有帮助，至少能够更加快速地了解MySQL的原理和宏观结构，然后再深入细节。此外，还有一些博客或PPT将得也很不错，这里推荐最好的几份材料。</p><h4>2.1 InnoDB - A journey to the core</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">《<a href="https://www.percona.com/live/mysql-conference-2013/sites/default/files/slides/InnoDB%20-%20A%20journey%20to%20the%20core%20-%20PLMCE%202013.pdf" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">InnoDB - A journey to the core</a>》 是MySQL大牛Jeremy Cole写的PPT，介绍InnoDB的存储模块，即表空间、区、段、页的格式、记录的格式、槽等等。是学习Innodb存储的最好的材料。感谢Jeremy Cole!</p><h4>2.2 深入MySQL源码</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">登博的分享《<a href="http://hotpu-meeting.b0.upaiyun.com/2014dtcc/post_pdf/hedengcheng.pdf" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">深入MySQL源码</a>》，相信很多想了解MySQL源码的朋友已经知道这份PPT，就不过多介绍，不过，要多说一句，登博的参考资料里列出的几个博客，都要关注一下，干货满满，是学习MySQL必须关注的博客。</p><h4>2.3 深入理解MySQL核心技术</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">《<a href="http://book.douban.com/subject/4022870/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">深入理解MySQL核心技术</a>》是第一本关于MySQL源码的书，着重介绍了MySQL的Server层，重点介绍了宏观架构，对于刚开始学习MySQL源码的人，相信会有很大的帮助，我在学习MySQL源码的过程中，反复的翻阅了几遍，这本书刚开始看的时候会很痛苦，但是，对于研究MySQL源码，非常有帮助，就看你是否需要，如果没有研究MySQL源码的决心，这本书应该会被唾弃。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-6.jpg" alt="深入理解MySQL核心技术" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><h4>2.4 MySQL内核：InnoDB存储引擎</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">我们组的同事写的《<a href="http://img4.douban.com/lpic/s27266366.jpg" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">MySQL内核：InnoDB存储引擎</a>》，可能宇宙范围内这本书就数我学得最认真了，虽然书中有很多编辑错误，但是，平心而论，还是写得非常好的，相对于《深入理解MySQL核心技术》，可读性更强一些，建议研究Innodb存储引擎的朋友，可以了解一下，先对Innodb有一个宏观的概念，对大致原理有一个整体的了解，然后再深入细节，肯定会比自己从头开始研究会快很多，这本书可以帮助你事半功倍。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-7.jpg" alt="MySQL内核" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><h4>2.5 MySQL Internals Manual</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">《<a href="http://dev.mysql.com/doc/internals/en/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">MySQL Internals Manual</a>》相对于MySQL Manual来说，写的太粗糙，谁让人家是官方文档呢，研究MySQL源码的时候可以简单地参考一下，但是，还是不要指望文档能够回答你的问题，还需要看代码才行。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><a href="http://dev.mysql.com/doc/internals/en/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">http://dev.mysql.com/doc/internals/en/</a></p><h4>2.6 MariaDB原理与实现</h4><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">评论里提到的《<a href="https://book.douban.com/subject/26340413/" style="padding: 0px; margin: 0px; border: none; outline: none; color: #dd0000; text-decoration-line: none;">MariaDB原理与实现</a>》我也买了一本，还不错，MariaDB讲的并不多，重点讲了Group Commit、线程池和复制的实现，都是MySQL Server层的知识，对MySQL Server层感兴趣的可以参考一下。</p><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://mingxinglai.com/cn/image/mysql-book-8.jpg" alt="MariaDB" style="padding: 0px; margin: 4px auto; border: none; outline: none; max-width: 800px; display: block; box-shadow: #999999 1px 1px 4px;" /></p><h2>3. 后记</h2><p style="padding: 0.5em 0.2em; margin: 0px; border: none; outline: none; font-family: Galdeano, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Trebuchet, &quot;Trebuchet MS&quot;, Tahoma, &quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Verdana, sans-serif; font-size: 16px; background-color: #ffffff;">希望这里推荐的材料对学习MySQL的同学、朋友有所帮助，也欢迎推荐靠谱的学习材料，大家共同进步。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/433533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2018-12-03 15:54 <a href="http://www.blogjava.net/xiaomage234/archive/2018/12/03/433533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习Cassandra资料的一些整理【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2017/07/18/432666.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 18 Jul 2017 01:57:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2017/07/18/432666.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/432666.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2017/07/18/432666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/432666.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/432666.html</trackback:ping><description><![CDATA[<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">from:<span style="font-family: verdana, &quot;courier new&quot;; font-size: 14px;">http://www.cnblogs.com/foohack/p/5627163.html</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">Cassandra note:</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">依赖：需要java 8 （http://www.oracle.com/technetwork/java/javase/downloads/index.html）</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">数据模型: 与Hbase同样是属于列式数据库，Key-Value存储系统。（http://www.ibm.com/developerworks/cn/opensource/os-cn-cassandra/）<br style="margin: 0px; padding: 0px;" />http://www.datastax.com/dev/blog/basic-rules-of-cassandra-data-modeling</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">集群中的数据是靠partion key的hash code均匀映射到不同的节点上去的。partionkey是primary key的第一个元素，所以选一个好的主<br style="margin: 0px; padding: 0px;" />key才能使数据更好的均匀存储在不同的节点上。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />Cassandra的节点实例叫Cluster，里面可以包含一个或多个键空间(KeysSpace).键空间是存放列族（Column Family）的容器，相当于<br style="margin: 0px; padding: 0px;" />关系数据中的database，schema。列族是存放列（column）的容器，类似与关系数据库中的table。超级列（Super column）是一种<br style="margin: 0px; padding: 0px;" />特殊的列，它的value值可以包含多个column。 columns是cassandra的最基本单位，有name，value，timestamp构成。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列式数据库的优点:&nbsp;<br style="margin: 0px; padding: 0px;" />1.适合存储大量数据，而不是小量数据。因为数据是是基于列存储的，所以可以忽略不需要的列的数据，提高查找效率。<br style="margin: 0px; padding: 0px;" />与之对应的是行数据库。<br style="margin: 0px; padding: 0px;" />2.高压缩比。节省存储空间，也节省CPU和内存。<br style="margin: 0px; padding: 0px;" />3.高装载速度。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列式数据库的缺点:<br style="margin: 0px; padding: 0px;" />1.不适合扫描小量数据。<br style="margin: 0px; padding: 0px;" />2.不适合随机更新数据。<br style="margin: 0px; padding: 0px;" />3.不适合做含有删除的更新的实时操作。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />查询数据:<br style="margin: 0px; padding: 0px;" />Cassandra有自己的一套查询语言CQL（类似SQL），在数据访问方式上亦是如此。客户端可以与集群中的任意节点相连，并访问任意的数据。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">cassandra在写入数据之前需要记录日志(CommitLog),然后数据开始写入到 Column Family 对应的 Memtable 中，<br style="margin: 0px; padding: 0px;" />Memtable 是一种按照 key 排序数据的内存结构，在满足一定条件时，再把 Memtable 的数据批量的刷新到磁盘上，存储为 SSTable 。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">存储二进制大文件（不推荐存储）：http://wiki.apache.org/cassandra/FAQ#large_file_and_blob_storage</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">Cassandra的GUI管理工具整理：http://wiki.apache.org/cassandra/FAQ#gui 也有自带的CLI工具连接Cassandra</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">Cassandra集群种子的概念（很重要）：http://wiki.apache.org/cassandra/FAQ#seed<br style="margin: 0px; padding: 0px;" />类似与Cassandra集群的初始化节点（集线器），各个节点通过种子节点互相学习（交换）各自的数据（状态），所以新加入的Cassandra节点都需要给它<br style="margin: 0px; padding: 0px;" />指定种子节点，下次启动的时候就不需要了。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />Cassandra 的C++ 接口：<br style="margin: 0px; padding: 0px;" />Cassandra的各种编程语言的接口是有Thrift这个开源工具生成的，语言无关的Thrift输入文件（cassandra.thrift）Cassandra已经自带<br style="margin: 0px; padding: 0px;" />，安装thrift运行 thrift.exe -gen cpp cassandra.thrift生成就可以了。 cpp的接口依赖thrift的核心库叫libthrift，libthrift依赖boost1.53.0<br style="margin: 0px; padding: 0px;" />版本和openssl</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />Cassandra windows 安装配置:<br style="margin: 0px; padding: 0px;" />解压，配置好CASSANDRA_HOME环境变量的路径（也就是你解压的cassandra根目录），然后运行bin下的cassandra.bat，如果发现logs<br style="margin: 0px; padding: 0px;" />目录底下的system.log文件中有INFO - Starting up server gossip，那么恭喜你，Cassandra已经在你的本机启动起来了。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">*****************************************Cassandra的基本操作************************************************</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">数据模型：多维的hash表，每行可以有不同的列。每行都有个键. keyspace包含若干列族<br style="margin: 0px; padding: 0px;" />(列族和表是同一个概念：http://stackoverflow.com/questions/18824390/whats-the-difference-between-creating-a-table-and-creating-a-columnfamily-in-ca)，<br style="margin: 0px; padding: 0px;" />keyspace在逻辑上是容纳列族和某些配置属性的命名空间。列族定义了相关的数据名字和它们的排序方式。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">入门必读：http://wiki.apache.org/cassandra/GettingStarted</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">CQLSH中运行外部创建的cql脚本文件: SOURCE '[file_path]'</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的创建:&nbsp;<br style="margin: 0px; padding: 0px;" />CREATE KEYSPACE [keyspace_name] WITH REPLICATION = {'class' : 'NetworkTopologyStrategy', 'datacenter1' : 3};</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">----键空间的创建要附带副本属性，class可以指定NetworkTopologyStrategy或SimpleStrategy。SimpleStrategy只用于测试评估Cassandra<br style="margin: 0px; padding: 0px;" />生产环境使用NetworkTopologyStrategy. 键空间类似关系型数据库中的数据库（database）</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的修改：<br style="margin: 0px; padding: 0px;" />ALTER KEYSPACE [keyspace_name] WITH REPLICATION = {};</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的删除:<br style="margin: 0px; padding: 0px;" />DROP KEYSPACE [keyspace_name]</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的使用:<br style="margin: 0px; padding: 0px;" />USE [keyspace_name]</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />列出已存在的键空间:<br style="margin: 0px; padding: 0px;" />DESCRIBE keyspaces;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列出某个键空间下的所有表：<br style="margin: 0px; padding: 0px;" />USE [keyspace_name];<br style="margin: 0px; padding: 0px;" />DESCRIBE tables;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列出某个键空间下的所有列族：<br style="margin: 0px; padding: 0px;" />USE [keyspace_name];<br style="margin: 0px; padding: 0px;" />DESCRIBE columnfamilies;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列出特定的表的基本信息：<br style="margin: 0px; padding: 0px;" />DESCRIBE TABLE [keyspace_name].[table_name];</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">建表：<br style="margin: 0px; padding: 0px;" />http://docs.datastax.com/en/cql/3.1/cql/cql_using/create_table_t.html<br style="margin: 0px; padding: 0px;" />表的主键可以是复合的，就是多个列组成一个主键：<br style="margin: 0px; padding: 0px;" />CREATE TABLE emp (<br style="margin: 0px; padding: 0px;" />empID int,<br style="margin: 0px; padding: 0px;" />deptID int,<br style="margin: 0px; padding: 0px;" />first_name varchar,<br style="margin: 0px; padding: 0px;" />last_name varchar,<br style="margin: 0px; padding: 0px;" />PRIMARY KEY (empID, deptID)); //主键的第一个键就是分区键（empID），分区键的目的就是把表中的数据均分到集群中的<br style="margin: 0px; padding: 0px;" />各个节点中</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">更改表：<br style="margin: 0px; padding: 0px;" />ALERT TABLE [table_name] [some change]<br style="margin: 0px; padding: 0px;" />https://docs.datastax.com/en/cql/3.0/cql/cql_reference/alter_table_r.html<br style="margin: 0px; padding: 0px;" />没办法更改主键，因为主键涉及到数据的物理储存</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">给表的某列建立索引：<br style="margin: 0px; padding: 0px;" />CREATE INDEX ON [table_name] (column_name);</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />查表：<br style="margin: 0px; padding: 0px;" />SELCT [column_name] FROM [keyspace].[table_name] WHERE [column_name] = [value] //其中column_name必须是主键的其中部分，<br style="margin: 0px; padding: 0px;" />如果有多个条件必须其中有一个是分区键</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">更新表中的值:<br style="margin: 0px; padding: 0px;" />UPDATE [keyspace].[table_name] SET [column_name] = [new_value] WHERE [column_name]=[value]</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">删除表中列或行：<br style="margin: 0px; padding: 0px;" />删除列中值：DELETE [column_name] FROM [table_name] WHERE [column_name] = [value] # 同查表<br style="margin: 0px; padding: 0px;" />删除一整行：DELETE FROM [table_name] WHERE [column_name] = [value] #同上</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">自定义数据类型(http://docs.datastax.com/en/cql/3.1/cql/cql_using/cqlUseUDT.html):<br style="margin: 0px; padding: 0px;" />CREATE TYPE [keyspace_name].[type_name] (<br style="margin: 0px; padding: 0px;" />street text,<br style="margin: 0px; padding: 0px;" />city text,<br style="margin: 0px; padding: 0px;" />zip_code int,<br style="margin: 0px; padding: 0px;" />phones set&lt;text&gt;<br style="margin: 0px; padding: 0px;" />);<br style="margin: 0px; padding: 0px;" />自定义的数据类型的字面值是json-style的风格。</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">内建的数据类型(http://docs.datastax.com/en/cql/3.1/cql/cql_reference/cql_data_types_c.html)：<br style="margin: 0px; padding: 0px;" />ascii,bigint,blob,boolean,counter,double,float,inet,int,list,map,set,text,uuid,<br style="margin: 0px; padding: 0px;" />timestamp,tuple,varchar(UTF-8 encoded string) ,varint</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />查看集群信息：<br style="margin: 0px; padding: 0px;" />SELECT * FROM system.peers;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">本地帮助文档的查看:<br style="margin: 0px; padding: 0px;" />HELP [COMMAND]<br style="margin: 0px; padding: 0px;" />比如：查看创建键空间 HELP CREATE_KEYSPACE;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />CQL语句支持多语句提交（Batch）：<br style="margin: 0px; padding: 0px;" />可以减少Node之间的流量交换，类似于事务，是原子的。<br style="margin: 0px; padding: 0px;" />http://docs.datastax.com/en/cql/3.1/cql/cql_reference/batch_r.html#reference_ds_djf_xdd_xj__batch-conditional<br style="margin: 0px; padding: 0px;" />http://docs.datastax.com/en/cql/3.1/cql/cql_using/use-batch-static.html</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />给数据设置存活期：<br style="margin: 0px; padding: 0px;" />超过存活期的数据，将被销毁。<br style="margin: 0px; padding: 0px;" />INSERT INTO [table_name]<br style="margin: 0px; padding: 0px;" />([column_name1], [column_name2])<br style="margin: 0px; padding: 0px;" />VALUES ([column_value1], [column_value2]) USING TTL 86400; # 86400 sec 大概是一天的存活期<br style="margin: 0px; padding: 0px;" />是给column_name2设置的</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />UPDATE [table_name] USING TTL 432000 SET [column_name] = [column_value]<br style="margin: 0px; padding: 0px;" />WHERE user_name = 'cbrown';</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/432666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2017-07-18 09:57 <a href="http://www.blogjava.net/xiaomage234/archive/2017/07/18/432666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一篇文章，掌握所有开源数据库的现状</title><link>http://www.blogjava.net/xiaomage234/archive/2016/09/08/431781.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 08 Sep 2016 07:05:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/09/08/431781.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431781.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/09/08/431781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431781.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431781.html</trackback:ping><description><![CDATA[from:http://www.oschina.net/news/74775/open-source-database-situation<div id="OSChina_News_74775" newscontent=""  textcontent"="" style="margin: 10px 0px; line-height: 1.6; font-size: 10.5pt; overflow: hidden; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun;"><p style="margin: 0px 0px 15pt; padding: 0px;">数据库作为业务的核心，是整个基础软件栈非常重要的一环。近几年的开源社区，新的思想和方案层出不穷，我将总结一下近几年一些主流的开源数据库方案，及其背后的设计思想以及适用场景。本人才疏学浅如有遗漏或者错误请见谅。本次分享聚焦于数据库即结构化数据存储 OLTP 及 NoSQL 领域，不会涉及 OLAP、对象存储以及分布式文件系统。</p><h3><strong style="margin: 0px; padding: 0px;">开源 RDBMS 与互联网的崛起</strong></h3><p style="margin: 0px 0px 15pt; padding: 0px;">很长时间以来，关系型数据库一直是大公司的专利，市场被 Oracle / DB2 等企业数据库牢牢把持。但是随着互联网的崛起和开源社区的发展，上世纪九十年代 MySQL 1.0 的发布，标志着在关系型数据库的领域，社区终于有了可选择的方案。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">MySQL</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">第一个介绍的单机 RDBMS 就是 MySQL。相信大多数朋友都已经对 MySQL 非常熟悉，基本上 MySQL 的成长史就是互联网的成长史。我接触的第一个 MySQL 版本是 MySQL 4.0，后来的 MySQL 5.5 更是经典&#8212;&#8212;基本上所有的互联网公司都在使用。MySQL 也普及了「可插拔」引擎这一概念，即针对不同的业务场景选用不同的存储引擎，这也是 MySQL tuning 的一个重要方式。比如对于有事务需求的场景使用 InnoDB；对于并发读取的场景 MyISAM 可能比较合适；但是现在我推荐绝大多数情况还是使用 InnoDB，毕竟 MySQL 5.6 后它已经成为了官方的默认引擎。MySQL适用于几乎所有需要持久化结构化数据的场景， 大多数朋友应该都知道，我就不赘述了。</p><p style="margin: 0px 0px 15pt; padding: 0px;">另外值得一提的是 MySQL 5.6 中引入了多线程复制和 GTID，使得故障恢复和主从的运维变得比较方便。另外，MySQL 5.7（目前处于 GA 版本） 发布了一个重大更新，主要是在读写性能和复制性能上有了长足的进步：在5.6版本中实现了 SCHEMA 级别的并行复制。不过意义不大，倒是 MariaDB 的多线程并行复制大放异彩，有不少人因为这个特性选择 MariaDB。另外，MySQL 5.7 MTS 支持两种模式，一种是和5.6一样，另一种则是基于 binlog group commit 实现的多线程复制，也就是MASTER上同时提交的 binlog 在 SLAVE 端也可以同时被 apply，实现并行复制。如果有单机数据库技术选型的朋友，基本上只需要考虑 MySQL 5.7 或者 MariaDB 就好了，而且 MySQL 5.6和5.7 由 Oracle 接手后，性能和稳定性都有了明显的提升。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">PostgreSQL</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">PostgreSQL 的历史也非常悠久，其前身是 UCB 的 Ingres，主持这个项目的 Michael Stronebraker 于 2015 年获得图灵奖。后来该项目更名为 Post-Ingres，基于 BSD license 下开源。 1995 年几个 UCB 的学生为 Post-Ingres 开发了 SQL 的接口，正式发布了 PostgreSQL95，随后一步步在开源社区中成长起来。和 MySQL 一样，PostgreSQL 也是一个单机的关系型数据库，但是与 MySQL 方便用户过度扩展的 SQL 文法不一样的是，PostgreSQL 的 SQL 支持非常强大，不管是内置类型、JSON 支持、GIS 类型以及对于复杂查询的支持，PL/SQL 等都比 MySQL 强大得多，而且从代码质量上来看，PostgreSQL 的代码质量是优于 MySQL 的。另外，相对于MySQL 5.7以前的版本， PostgreSQL 的 SQL 优化器比 MySQL 强大很多，几乎所有稍微复杂的查询PostgreSQL 的表现都优于 MySQL。</p><p style="margin: 0px 0px 15pt; padding: 0px;">从近几年的趋势上来看，PostgreSQL 的势头也很强劲，我认为 PostgreSQL 的不足之处在于没有 MySQL 那样强大的社区和群众基础。MySQL 经过那么多年的发展，积累了很多的运维工具和最佳实践，但是 PostgreSQL 作为后起之秀，拥有更优秀的设计和更丰富的功能。PostgreSQL 9 以后的版本也足够稳定，在做新项目技术选型的时候，是一个很好的选择。另外也有很多新的数据库项目是基于 PostgreSQL 源码的基础上进行二次开发，比如 Greenplum 等。</p><p style="margin: 0px 0px 15pt; padding: 0px;">我认为，单机数据库的时代很快就会过去。摩尔定律带来的硬件红利总是有上限的，现代业务的数据规模、流量以及现代的数据科学对于数据库的要求，单机已经很难满足。比如，网卡磁盘 IO 和 CPU 总有瓶颈，线上敏感的业务系统可能还得承担 SPOF（单点故障） 的风险，主从复制模型在主挂掉时到底切还是不切？切了以后数据如何恢复？如果只是出现主从机器网络分区问题呢？甚至是监控环境出现网络分区问题呢？这些都是单机数据库面临的巨大挑战。所以我的观点是，无论单机性能多棒（很多令人乍舌的评测数据都是针对特定场景的优化，另外甚至有些都是本机不走网络，而大多数情况数据库出现的第一个瓶颈其实是网卡和并发连接&#8230;&#8230;），随着互联网的蓬勃发展和移动互联网的出现，数据库系统迎来了第一次分布式的洗礼。</p><h3><strong style="margin: 0px; padding: 0px;">分布式时代：NoSQL 的复兴和模型简化的力量</strong></h3><p style="margin: 0px 0px 15pt; padding: 0px;">在介绍 NoSQL 之前，我想提两个公司，一个是 Google，另一个是 Amazon。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">Google</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">Google&nbsp;<span font-size:="" style="margin: 0px; padding: 0px;">应该是第一个将分布式存储技术应用到大规模生产环境的公司，同时也是在分布式系统上积累最深的公司，可以说目前工业界的分布式系统的工程实践及思想大都来源于 Google。比如 2003 年的 GFS 开创了分布式文件系统，2006 年的 Bigtable 论文开创了分布式键值系统，直接催生的就是 Hadoop 的生态；至于 2012 年发表论文的 Spanner 和 F1更是一个指明未来关系型数据库发展方向的里程碑式的项目，这个我们后续会说。</span></p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">Amazon</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">另一个公司是 Amazon。2007 年发表的 Dynamo的论文 尝试引入了最终一致性的概念， WRN 的模型及向量时钟的应用，同时将一致性 HASH、merkle tree 等当时一些很新潮的技术整合起来，正式标志着 NoSQL 的诞生。NoSQL&#8212;&#8212;对后来业界的影响非常也是很大，包括后来的 Cassandra、RiakDB、Voldemort 等数据库都是基于 Dynamo 的设计发展起来的。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">新思潮</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">另外这个时期（2006 年前后持续至今）一个比较重要的思潮就是数据库（持久化）和缓存开始有明确的分离&#8212;&#8212;我觉得这个趋势是从 memcached 开始的。随着业务的并发越来越高，对于低延迟的要求也越来越高；另外一个原因是随着内存越来越便宜，基于内存的存储方案渐渐开始普及。当然内存缓存方案也经历了一个从单机到分布式的过程，但是这个过程相比关系型数据库的进化要快得多。这是因为 NoSQL 的另外一个重要的标志&#8212;&#8212;数据模型的变化&#8212;&#8212;大多 NoSQL 都抛弃了关系模型，选择更简单的键值或者文档类型进行存储。数据结构和查询接口都相对简单，没有了 SQL 的包袱，实现的难度会降低很多。另外 NoSQL 的设计几乎都选择牺牲掉复杂 SQL 的支持及 ACID 事务换取弹性扩展能力，也是从当时互联网的实际情况出发：业务模型简单、爆发性增长带来的海量并发及数据总量爆炸、历史包袱小、工程师强悍，等等。其中最重要的还是业务模型相对简单。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">嵌入式存储引擎</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">在开始介绍具体的开源的完整方案前，我想介绍一下嵌入式存储引擎们。</p><p style="margin: 0px 0px 15pt; padding: 0px;">随着 NoSQL 的发展，不仅仅缓存和持久化存储开始细分，再往后的存储引擎也开始分化并走上前台。之前很难想象一个存储引擎独立于数据库直接对外提供服务，就像你不会直接拿着 InnoDB 或者 MyISAM甚至一个 B-tree 出来用一样<span font-family:="" style="margin: 0px; padding: 0px;">（当然，bdb 这样鼎鼎大名的除外）</span>。人们基于这些开源的存储引擎进行进一步的封装，比如加上网络协议层、加上复制机制等等，一步步构建出完整的风格各异的 NoSQL 产品。</p><p style="margin: 0px 0px 15pt; padding: 0px;">这里我挑选几个比较著名的存储引擎介绍一下。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">TC</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">我最早接触的是 Tokyo Cabinet（TC）。TC 相信很多人也都听说过，TC 是由日本最大的社交网站 Mixi 开发并开源的一个混合 Key-Value 存储引擎，其中包括 HASH Table 和 B+ Tree 的实现。但是这个引擎的一个缺陷是随着数据量的膨胀，性能的下降会非常明显，而且现在也基本不怎么维护了，所以入坑请慎重。与于 TC 配合使用的 Tokyo Tyrant（TT） 是一个网络库，为 TC 提供网络的接口使其变成一个数据库服务，TT + TC 应该是比较早的 NoSQL 的一个尝试。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">LevelDB</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">在 2011 年，Google 开源了 Bigtable 的底层存储引擎： LevelDB。LevelDB 是一个使用 C++ 开发的嵌入式的 Key-Value 存储引擎，数据结构采用了 LSM-Tree，具体 LSM-Tree 的算法分析可以很容易在网上搜索到，我就不赘述了。其特点是，对于写入极其友好，LSM 的设计避免了大量的随机写入；对于特定的读也能达到不错的性能（热数据在内存中）；另外 LSM-Tree 和 B-tree 一样是支持有序 Scan 的；而且 LevelDB 是出自 Jeff Dean 之手，他的事迹做分布式系统的朋友一定都知道，不知道的可以去 Google 搜一下。</p><p style="margin: 0px 0px 15pt; padding: 0px;">LevelDB 拥有极好的写性能，线程安全，BatcTCh Write 和 Snapshot 等特性，使其很容易的在上层构建 MVCC 系统或者事务模型，这对于数据库来说非常重要。另外值得一说的是，Facebook 维护了一个活跃的 LevelDB 的分支，名为 RocksDB。RocksDB 在 LevelDB 上做了很多的改进，比如多线程 Compactor、分层自定义压缩、多 MemTable 等。另外 RocksDB 对外暴露了很多 ConfigurationConfigration ，可以根据不同业务的形态进行调优；同时 Facebook 在内部正在用 RocksDB 来实现一个全新的 MySQL 存储引擎：MyRocks，值得关注。RocksDB 的社区响应速度很快也很友好，实际上 PingCAP 也是 RocksDB 的社区贡献者。我建议新的项目如果在 LevelDB 和 RocksDB 之间纠结的话，请果断选择 RocksDB。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">B-tree&nbsp;</strong><strong style="margin: 0px; padding: 0px;">家族</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">当然，除了 LSM-Tree 外，B-tree 的家族也还是有很多不错的引擎。首先大多数传统的单机数据库的存储引擎都选择了B+Tree，B+Tree 对磁盘的读比较友好，第三方存储引擎比较著名的纯 B+Tree 实现是 LMDB。首先 LMDB 选择在内存映像文件 (mmap) 实现 B+Tree，而且同时使用了 Copy-On-Write 实现了 MVCC 实现并发事务无锁读的能力，对于高并发读的场景比较友好；同时因为使用的是 mmap 所以拥有跨进程读取的能力。不过因为我并没有在生产环境中使用过 LMDB ，所以并不能给出 LMDB 的一些缺陷，见谅。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">混合引擎</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">还有一部分的存储引擎选择了多种引擎混合，比如最著名的应该是 WiredTiger，大概是2014年去年被 MongoDB 收购，现在成为了 MongoDB 的默认存储引擎。WiredTiger 内部有 LSM-Tree 和 B-tree 两种实现，对外提供相同的一套接口，根据业务的情况可自由选择。另外一些特殊数据结构的存储引擎在某些特殊场合下非常抢眼，比如极高压缩比 TokuDB，采用了名为分形树的数据结构，在维持一个可接受的读写压力的情况下，能拥有 10 倍以上的压缩率。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">NoSQL</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">说完了几个比较著名的存储引擎，我们来讲讲比较著名的 NoSQL。在我的定义中，NoSQL 是 Not Only SQL 的缩写，所以可能包含的范围有内存数据库，持久化数据库等。总之就是和单机的关系型数据库不一样的结构化数据存储系统。</p><p style="margin: 0px 0px 15pt; padding: 0px;">我们先从缓存开始。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">memcached</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">前面提到了 memcached 应该是第一个大规模在业界使用的缓存数据库，memcached 的实现极其简单，相当于将内存用作大的 HASH Table，只能在上面进行 get/set/ 计数器等操作，在此之上用 libevent 封装了一层网络层和文本协议（也有简单的二进制协议），虽然支持一些 CAS 的操作，但是总体上来看，还是非常简单的。但是 memcached 的内存利用率并不太高，这是这个因为 memcached 为了避免频繁申请内存导致的内存碎片的问题，采用了自己实现的 slab allocator 的方式。即内存的分配都是一块一块的，最终存储在固定长度的 chunk 上，内存最小的分配单元是 chunk，另外 libevent 的性能也并没有优化到极致。但是这些缺点并不妨碍 memcached 成为当时的开源缓存事实标准。（另外，八卦一下，memcached 的作者 Brad Fitzpatrick 现在在 Google，大家如果用 Golang 的话，Go 的官方 HTTP 包就是这哥们写的，是个很高产的工程师）。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">Redis</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">如果我没记错的话，在 2009 年前后，一位意大利的工程师 Antirez ，开源了 Redis。从此彻底颠覆了缓存的市场，到现在大多数缓存的业务都已用上 Redis，memcached 基本退出了历史舞台。Redis 最大的特点是拥有丰富的数据结构支持，不仅仅是简单的 Key-Value，还包括队列、集合、Sorted Set 等等，提供了非常丰富的表达力，而且 Redis 还提供 sub/pub 等超出数据库范畴的便捷功能，使得几乎一夜之间大家纷纷投入 Redis 的怀抱。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">Twemproxy</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">但是随着 Redis 渐渐的普及，而且越用越狠，另外内存也越来越便宜，人们开始寻求扩展单机 Redis 的方案，最早的尝试是 twitter 开源的 twemproxy。twemproxy 是一个 Redis 中间件，基本只有最简单的数据路由功能，并没有动态的伸缩能力，但是还是受到了很多公司的追捧，因为确实没其他替代方案。随后的 Redis Cluster 也是难产了好久，时隔好几年，中间出了 7 个RC 版本，最后才发布；2014 年底，我们开源了 Codis，解决了 Redis 中间件的数据弹性伸缩问题，目前广泛应用于国内各大互联网公司中，这个在网上也有很多文章介绍，我也就不展开了。所以在缓存上面，开源社区现在倒是非常统一，就是 Redis 及其极其周边的扩展方案。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">MongoDB</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">在 NoSQL 的大家庭中，MongoDB 其实是一个异类，大多 NoSQL 舍弃掉 SQL 是为了追求更极致的性能和可扩展能力，而 MongoDB 主动选择了文档作为对外的接口，非常像 JSON 的格式。Schema-less 的特性对于很多轻量级业务和快速变更的了互联网业务意义很大，而且 MongoDB 的易用性很好，基本做到了开箱即用，开发者不需要费心研究数据的表结构，只需要往里存就好了，这确实笼络了一大批开发者。</p><p style="margin: 0px 0px 15pt; padding: 0px;">尽管 MongoDB 早期的版本各种不稳定，性能也不太好（早期的 Mongo 并没有存储引擎，直接使用了 mmap 文件），集群模式还全是问题（比如至今还未解决的 Cluster 同步带宽占用过多的问题），但是因为确实太方便了，在早期的项目快速迭代中，Mongo 是一个不错的选择。但是这也正是它的问题，我不止一次听到当项目变得庞大或者「严肃」的时候，团队最后还是回归了关系型数据库。Anyway，在 2014 年底 MongoDB 收购了 WiredTiger 后，在 2.8 版本中正式亮相，同时 3.0 版本后更是作为默认存储引擎提供，性能和稳定性有了非常大的提升。</p><p style="margin: 0px 0px 15pt; padding: 0px;">但是，从另一方面讲，Schema-less 到底对软件工程是好事还是坏事这个问题还是有待商榷。我个人是站在 Schema 这边的，不过在一些小项目或者需要快速开发的项目中使用 Mongo 确实能提升很多的开发效率，这是毋庸置疑的。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">✦</strong><strong style="margin: 0px; padding: 0px;">HBase</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">说到 NoSQL 不得不提的是 HBase，HBase 作为 Hadoop 旗下的重要产品，Google Bigtable 的正统开源实现，是不是有一种钦定的感觉 :)。提到 HBase 就不得不提一下 Bigtable， Bigtable 是 Google 内部广泛使用的分布式数据库，接口也不是简单的Key-Value，按照论文的说法叫：multi-dimensional sorted map，也就是 Value 是按照列划分的。Bigtable 构建在 GFS 之上，弥补了分布式文件系统对于海量、小的、结构化数据的插入、更新以及、随机读请求的缺陷。</p><p style="margin: 0px 0px 15pt; padding: 0px;">HBase&nbsp;<span font-size:="" style="margin: 0px; padding: 0px;">就是这么一个系统的实现，底层依赖 HDFS。HBase 本身并不实际存储数据，持久化的日志和 SST file (HBase 也是 LSM-Tree 的结构) 直接存储在 HDFS 上，Region Server (RS) 维护了 MemTable 以提供快速的查询，写入都是写日志，后台进行 Compact，避免了直接随机读写 HDFS。数据通过 Region 在逻辑上进行分割，负载均衡通过调节各个 Region Server 负责的 Region 区间实现。当某 Region 太大时，这个 Region 会分裂，后续可能由不同的 RS 负责，但是前面提到了，HBase 本身并不存储数据，这里的 Region 仅是逻辑上的，数据还是以文件的形式存储在 HDFS 上，所以 HBase 并不关心 Replication 、水平扩展和数据的分布，统统交给 HDFS 解决。</span></p><p style="margin: 0px 0px 15pt; padding: 0px;">和 Bigtable 一样，HBase 提供行级的一致性，严格来说在 CAP 理论中它是一个 CP 的系统，但遗憾的是并没有更进一步提供 ACID 的跨行事务。HBase 的好处就不用说了，显而易见，通过扩展 RS 可以几乎线性提升系统的吞吐，及 HDFS 本身就具有的水平扩展能力。</p><p style="margin: 0px 0px 15pt; padding: 0px;">但是缺点仍然是有的。首先，Hadoop 的软件栈是 Java，JVM 的 GC Tuning 是一个非常烦人的事情，即使已经调得很好了，平均延迟也得几十毫秒；另外在架构设计上，HBase 本身并不存储数据，所以可能造成客户端请求的 RS 并不知道数据到底存在哪台 HDFS DataNode 上，凭空多了一次 RPC；第三，HBase 和 Bigtable 一样，并不支持跨行事务，在 Google 内部不停的有团队基于 Bigtable 来做分布式事务的支持，比如 MegaStore、Percolator。后来 Jeff Dean 有次接受采访也提到非常后悔没有在 Bigtable 中加入跨行事务，不过还好这个遗憾在 Spanner 中得到了弥补，这个一会儿说。总体来说，HBase 还是一个非常健壮且久经考验的系统，但是需要你有对于 Java 和 Hadoop 比较深入的了解后，才能玩转，这也是 Hadoop 生态的一个问题，易用性真是不是太好，而且社区演进速度相对缓慢，也是因为历史包袱过重的缘故吧。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">Cassandra</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">提到 Cassandra (<span font-family:="" style="margin: 0px; padding: 0px;">C*</span>)，虽然也是 Dynamo 的开源实现，但就没有这种钦定的感觉了。C* 确实命途多舛，最早 2008 由 Facebook 开发并开源，早期的 C* 几乎全是 bug，Facebook 后来索性也不再维护转过头搞 HBase 去了，一个烂摊子直接丢给社区。还好 DataStax 把这个项目捡起来商业化，搞了两年，终于渐渐开始流行起来。</p><p style="margin: 0px 0px 15pt; padding: 0px;">C* 不能简单的归纳为读快写慢，或者读慢写快，因为采用了 qourm 的模型，调整复制的副本数以及读的数量，可以达到不同的效果，对于一致性不是特别高的场景，可以选择只从一个节点读取数据，达到最高的读性能。另外 C* 并不依赖分布式文件系统，数据直接存储在磁盘上，各个存储节点之间自己维护复制关系，减少了一层 RPC 调用，延迟上对比 HBase 还是有一定优势的。</p><p style="margin: 0px 0px 15pt; padding: 0px;">不过即使使用 qourm 的模型也并不代表&nbsp;<span font-size:="" style="margin: 0px; padding: 0px;">C*</span>&nbsp;是一个强一致的系统。C* 并不帮你解决冲突，即使你 W(写的副本数) + R(读请求的副本数) &gt; N(节点总数)，C* 也没办法帮你决定哪些副本拥有更新的版本，因为每个数据的版本是一个 NTP 的时间戳或者客户端自行提供，每台机器可能都有误差，所以有可能并不准确，这也就是为什么 C* 是一个 AP 的系统。不过 C* 一个比较友好的地方是提供了 CQL，一个简单的 SQL 方言，比起 HBase 在易用性上有明显优势。</p><p style="margin: 0px 0px 15pt; padding: 0px;">即使作为一个 AP 系统，C* 已经挺快了，但是人们追求更高性能的脚步还是不会停止。应该是今年年初，ScyllaDB 的发布就是典型的证明，ScyllaDB 是一个兼容 C* 的 NoSQL 数据库，不一样的是，ScyllaDB 完全用 C++ 开发，同时使用了类似 DPDK 这样的黑科技，具体我就不展开了，有兴趣可以到 Scylla 的官网去看看。BTW， 国内的蘑菇街第一时间使用了 ScyllaDB，同时在 Scylla 的官网上 share 了他们的方案，性能还是很不错的。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">中间件与分库分表</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">NoSQL 就先介绍到这里，接下来我想说的是一些在基于单机关系型数据库之上的中间件和分库分表方案。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;"><span font-family:="" style="margin: 0px; padding: 0px;">这些技术确实历史悠久，而且也是没有办法的选择。关系型数据库不比 Redis，并不是简单的写一个类似 Twemproxy 的中间件就搞定了。数据库的中间件需要考虑很多，比如解析 SQL，解析出 sharding key，然后根据 sharding key 分发请求，再合并；另外数据库有事务，在中间件这层还需要维护 Session 及事务状态，而且大多数方案并没有办法支持跨 shard 的事务。这就不可避免的导致了业务使用起来会比较麻烦，需要重写代码，而且会增加逻辑的复杂度，更别提动态的扩容缩容和自动的故障恢复了。在集群规模越来越大的情况下，运维和 DDL 的复杂度是指数级上升的。</span></p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">中间件项目盘点</strong></p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;"><span font-family:="" style="margin: 0px; padding: 0px;">数据库中间件最早的项目大概是 MySQL Proxy，用于实现读写分离。后来国人在这个领域有过很多著名项目，比如阿里的 Cobar 和 TDDL（并未完全开源）；后来社区基于 Cobar 改进的 MyCAT、360 开源的 Atlas 等，都属于这一类中间件产品；在中间件这个方案上基本走到头的开源项目应该是 Youtube 的 Vitess。Vitess 基本上是一个集大成的中间件产品，内置了热数据缓存、水平动态分片、读写分离等等，但是代价也是整个项目非常复杂，另外文档也不太好。大概1年多以前，我们尝试搭建起完整的 Vitess 集群，但是并未成功，可见其复杂度。</span></p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;"><span font-family:="" style="margin: 0px; padding: 0px;">另外一个值得一提的是 Postgres-XC 这个项目，Postgres-XC 的野心还是很大的，整体的架构有点像早期版本的 OceanBase，由一个中央节点来处理协调分布式事务 / 解决冲突，数据分散在各个存储节点上，应该是目前 PostgreSQL 社区最好的分布式扩展方案。其他的就不提了。</span></p><h3><strong style="margin: 0px; padding: 0px;">未来在哪里？NewSQL！</strong></h3><p style="margin: 0px 0px 15pt; padding: 0px;">一句话，NewSQL 就是未来。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">2012 年 Google 在 OSDI 上发表了 Spanner 的论文，2013 年在 SIGMOD 发表了 F1 的论文。这两篇论文让业界第一次看到了关系模型和 NoSQL 的扩展性在超庞大集群规模上融合的可能性。在此之前，大家普遍认为这个是不可能的，即使是 Google 也经历了 Megastore 这样的失败。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">Spanner</strong><strong style="margin: 0px; padding: 0px;">综述</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">但是 Spanner 的创新之处在于通过硬件（GPS时钟+原子钟）来解决时钟同步的问题。在分布式系统里，时钟是最让人头痛的问题，刚才提到了 C* 为什么不是一个强 C 的系统，正是因为时钟的问题。而 Spanner 的厉害之处在于即使两个数据中心隔得非常远，不需要有通信（因为通信的代价太大，最快也就是光速）就能保证 TrueTime API的时钟误差在一个很小的范围内（10ms）。另外 Spanner 沿用了很多 Bigtable 的设计，比如 Tablet / Directory 等，同时在 Replica 这层使用 Paxos 复制，并未完全依赖底层的分布式文件系统。但是 Spanner 的设计底层仍然沿用了 Colossus，不过论文里也说是可以未来改进的点。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">Google 的内部的数据库存储业务，大多是 3～5 副本，重要一点的 7 副本，遍布全球各大洲的数据中心，由于普遍使用了 Paxos，延迟是可以缩短到一个可以接受的范围（Google 的风格一向是追求吞吐的水平扩展而不是低延迟，从悲观锁的选择也能看得出来，因为跨数据中心复制是必选的，延迟不可能低，对于低延迟的场景，业务层自己解决或者依赖缓存）。另外由 Paxos 带来的 Auto-Failover 能力，更是能让整个集群即使数据中心瘫痪，业务层都是透明无感知的。另外 F1 构建在 Spanner 之上，对外提供了更丰富的 SQL 语法支持，F1 更像一个分布式 MPP SQL&#8212;&#8212;F1 本身并不存储数据，而是将客户端的 SQL 翻译成类似 MapReduce 的任务，调用 Spanner 来完成请求。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;"><span font-family:="" style="margin: 0px; padding: 0px;">其实 Spanner 和 F1 除了 TrueTime 整个系统并没有用什么全新的算法，其意义在于这是近些年来第一个 NewSQL 在生产环境中提供服务的分布式系统技术。</span></p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">Spanner&nbsp;</strong><strong style="margin: 0px; padding: 0px;">和 F1 有以下几个重点：</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;"><em style="margin: 0px; padding: 0px;">1.&nbsp;</em><em style="margin: 0px; padding: 0px;">完整的 SQL 支持，ACID 事务；2. 弹性伸缩能力；</em></p><p style="margin: 0px 0px 15pt; padding: 0px;"><em style="margin: 0px; padding: 0px;">3.&nbsp;</em><em style="margin: 0px; padding: 0px;">自动的故障转移和故障恢复，多机房异地灾备。</em></p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">NewSQL 特性确实非常诱人，在 Google 内部，大量的业务已经从原来的 Bigtable 切换到 Spanner 之上。我相信未来几年，整个业界的趋势也是如此，就像当年的 Hadoop 一样，Google 的基础软件的技术趋势是走在社区前面的。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">社区反应</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">Spanner 的论文发表之后，当然也有社区的追随者开始实现（比如我们 :D ），第一个团队是在纽约的 CockroachDB。CockroachDB 的团队的组成还是非常豪华的，早期团队由是 Google 的分布式文件系统 Colossus 团队的成员组成；技术上来说，Cockroach 的设计和 Spanner 很像，不一样的地方是没有选择 TrueTime而是 HLC （Hybrid logical clock），也就是 NTP +逻辑时钟来代替 TrueTime 时间戳；另外 Cockroach 选用了 Raft 代替 Paxos 实现复制和自动容灾，底层存储依赖 RocksDB 实现，整个项目使用 Go 语言开发，对外接口选用 PostgreSQL 的 SQL 子集。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">TiDB</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">目前从全球范围来看，另一个朝着 Spanner / F1 的开源实现这个目标上走的产品是 TiDB（终于谈到我们的产品了）。TiDB 本质上是一个更加正统的 Spanner 和 F1 实现，并不像 CockroachDB 那样选择将 SQL 和 Key-Value 融合，而是像 Spanner 和 F1 一样选择分离，这样分层的思想也是贯穿整个 TiDB 项目始终的。对于测试、滚动升级以及各层的复杂度控制会比较有优势；另外 TiDB 选择了 MySQL 协议和语法的兼容，MySQL 社区的 ORM 框架和运维工具，直接可以应用在 TiDB 上。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;"><span font-family:="" style="margin: 0px; padding: 0px;">和 F1 一样，TiDB 是一个无状态的 MPP SQL Layer，整个系统的底层是依赖 TiKV 来提供分布式存储和分布式事务的支持。TiKV 的分布式事务模型采用的是 Google Percolator 的模型，但是在此之上做了很多优化。Percolator 的优点是去中心化程度非常高，整个集群不需要一个独立的事务管理模块，事务提交状态这些信息其实是均匀分散在系统的各个 Key 的 meta 中，整个模型唯一依赖的是一个授时服务器。在我们的系统上，极限情况这个授时服务器每秒能分配 400w 以上个单调递增的时间戳，大多数情况基本够用了（毕竟有 Google 量级的场景并不多见）；同时在 TiKV中，这个授时服务本身是高可用的，也不存在单点故障的问题。</span></p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">TiKV 和 CockroachDB 一样也是选择了 Raft 作为整个数据库的基础；不一样的是，TiKV 整体采用 Rust 语言开发，作为一个没有 GC 和 Runtime 的语言，在性能上可以挖掘的潜力会更大。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">关于未来</strong></p><p style="margin: 0px 0px 15pt; padding: 0px;">我觉得未来的数据库会有几个趋势，也是 TiDB 项目追求的目标：</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">&#9679;数据库会随着业务云化，未来一切的业务都会跑在云端，不管是私有云、公有云还是混合云，运维团队接触的可能再也不是真实的物理机，而是一个个隔离的容器或者「计算资源」。这对数据库也是一个挑战，因为数据库天生就是有状态的，数据总是要存储在物理的磁盘上，而移动数据的代价比移动容器的代价可能大很多。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">&#9679;多租户技术会成为标配，一个大数据库承载一切的业务，数据在底层打通，上层通过权限，容器等技术进行隔离；但是数据的打通和扩展会变得异常简单，结合第一点提到的云化，业务层可以再也不用关心物理机的容量和拓扑，只需要认为底层是一个无穷大的数据库平台即可，不用再担心单机容量和负载均衡等问题。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">&#9679;OLAP 和 OLTP 会进一步细分，底层存储也许会共享一套，但是SQL优化器这层的实现一定是千差万别的。对于用户而言，如果能使用同一套标准的语法和规则来进行数据的读写和分析，会有更好的体验。</p><p text-justify:="" style="margin: 0px 0px 15pt; padding: 0px;">&#9679;在未来分布式数据库系统上，主从日志同步这样落后的备份方式会被 Multi-Paxos / Raft 这样更强的分布式一致性算法替代，人工的数据库运维在管理大规模数据库集群时是不可能的，所有的故障恢复和高可用都会是高度自动化的。</p><hr style="margin: 0px; padding: 0px;" /><p style="margin: 0px 0px 15pt; padding: 0px;">Q&amp;<span font-family:="" style="margin: 0px; padding: 0px;">A</span></p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">问：</strong>HANA等内存数据库怎么保证系统掉电而处理结果不丢？传统数据库也用缓存，可是HANA用的内存太大。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">黄东旭：</strong>没用过 HANA，但是直观感觉这类内存数据库的可用性可能通过集中方式保证：&#9679;写入会先写 WAL；</p><p style="margin: 0px 0px 15pt; padding: 0px;">&gt; -&nbsp;<span font-size:="" style="margin: 0px; padding: 0px;">写入可能会通过主从或者paxos 之类的算法做同步和冗余复制还有 HANA 本身就是内存数据库，会尽可能把数据放到内存里，这样查询才能快呀。</span>&nbsp;</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">问：</strong><span font-size:="" style="margin: 0px; padding: 0px;">对于传统创业公司如何弥补NoSQL的技术短板？快速的引入NoSQL提高效率？</span></p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">黄东旭：</strong>选用 NoSQL 主要注意两点：1.做好业务的调研，估计并发量，数据量，数据的结构看看适不适合；2.对各种 NoSQL 擅长和不擅长的地方都尽可能了解。</p><p style="margin: 0px 0px 15pt; padding: 0px;">不要盲目相信关系型数据库，也不要盲目相信 NoSQL，没有银弹的。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">问：</strong>有多个条件 &nbsp;比如年龄20到30或年龄35到40 并且加入购物车或下单 &nbsp;这种数据怎么存储？</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">黄东旭：</strong>购物车这种场景是典型的 OLTP 的场景，可以选用关系型数据库 MySQL PostgreSQL 什么的，如果对于扩展性的数据跨机房有要求的话，可以调研一下 NewSQL，比如我们的 TiDB。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">问：</strong>多纬度查询应该选择哪种数据库？</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">黄东旭：</strong>多纬度查询可以说是一个 OLAP 的场景，可以选用 Greenplum 或者 Vertica 之类的分析性数据库。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">问：</strong>想知道为什么需要这些开源的数据库，既然已经有了MySQL、DB2、Oracle这些成熟的数据库，成本考虑，还是传统数据库满足不了需求？</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">黄东旭：</strong>对，传统数据库的扩展性是有问题的，在海量并发和数据量的场景下很难支持业务。所以可以看到比较大的互联网公司基本都有自己的分布式数据库方案。</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">问：</strong>未来可能不再需要数据仓库吗？</p><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">黄东旭：</strong>大家可以想想数据仓库的定义，如果是还需要离线的从线上库倒腾数据到数据仓库上，这样很难做到实时查询，而且空间的利用率也低，我认为是目前并没有太好的方案的情况下的折衷&#8230;&#8230;如果有一个更好的数据库能解决数据仓库的场景，为什么还需要一个独立的数据仓库？</p><hr style="margin: 0px; padding: 0px;" /><p style="margin: 0px 0px 15pt; padding: 0px;"><strong style="margin: 0px; padding: 0px;">关于作者</strong></p><p line-height:="" style="margin: 0px 0px 15pt; padding: 0px;">黄东旭，PingCAP 联合创始人兼 CTO。PingCAP 是一家专注于研发下一代的开源的分布式数据库的公司，主要作品是 TiDB / TiKV，是 Google Spanner 及 F1 的开源实现。</p></div><div style="margin: 0px; font-size: 10.5pt; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: normal;"><h3>相关链接</h3><ul style="margin: 1em 0px 1em 2.5em; padding: 0px; line-height: 22px;"></ul><p style="margin: 0px; padding: 0px;">想通过手机客户端（支持 Android、iPhone 和 Windows Phone）访问开源中国：<a href="http://www.oschina.net/app" target="_blank" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">请点这里</a></p></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/431781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-09-08 15:05 <a href="http://www.blogjava.net/xiaomage234/archive/2016/09/08/431781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么 Uber 工程师将 Postgres 数据库换成 MySQL？</title><link>http://www.blogjava.net/xiaomage234/archive/2016/09/08/431775.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 08 Sep 2016 06:32:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/09/08/431775.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431775.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/09/08/431775.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431775.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431775.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:https://coyee.com/article/10690-why-uber-engineering-switched-from-postgres-to-mysql介绍早期的 Uber 架构是由&nbsp;Python 编写的，使用的是 Postgres 数据库存储。从那时起，Uber 的架构就一直在变化，变成微服务模型和新的数据平台。具体的说，很多我们以前使用 Postgres 的...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2016/09/08/431775.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/431775.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-09-08 14:32 <a href="http://www.blogjava.net/xiaomage234/archive/2016/09/08/431775.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎样打造一个分布式数据库</title><link>http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 23 Aug 2016 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431664.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431664.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431664.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">在技术方面，我自己热衷于 Open Source，写了很多 Open Source 的东西，擅长的是 Infrastructure 领域。Infrastructure 领域现在范围很广，比如说很典型的分布式 Scheduler、Mesos、Kubernetes，另外它和 Microservices 所结合的东西也特别多。Infrastructure 领域还有比如 Database 有分 AP（分析型）和 TP（事务型），比如说很典型的大家知道的 Spark、Greenplum、Apache Phoenix 等等，这些都属于在 AP 的，它们也会去尝试支持有限的 TP。另外，还有一个比较有意思的就是 Kudu&#8212;&#8212;Cloudera Open Source 的那个项目，它的目标很有意思：我不做最强的 AP 系统，也不做最强的 TP 系统，我选择一个相对折中的方案。从文化哲学上看，它比较符合中国的中庸思想。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，我先后创建了 Codis、TiDB。去年12月份创建了 TiKV 这个 project，TiKV 在所有的 rust 项目里目前排名前三。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">首先我们聊聊 Database 的历史，在已经有这么多种数据库的背景下我们为什么要创建另外一个数据库；以及说一下现在方案遇到的困境，说一下 Google Spanner 和 F1、TiKV 和 TiDB，说一下架构的事情，在这里我们会重点聊一下 TiKV。因为我们产品的很多特性是 TiKV 提供的，比如说跨数据中心的复制、Transaction、auto-scale。</p><div style="margin: 0px; border: 0px; height: 0px; clear: both; font-size: 0px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">接下来聊一下为什么 TiKV 用 Raft 能实现所有这些重要的特性，以及 scale、MVCC 和事务模型。东西非常多，我今天不太可能把里面的技术细节都描述得特别细，因为几乎每一个话题都可以找到一篇或者是多篇论文，所以详细的技术问题大家可以单独来找我聊。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">后面再说一下我们现在遇到的窘境，就是大家常规遇到的分布式方案有哪些问题，比如 MySQL Sharding。我们创建了无数 MySQL Proxy，比如官方的 MySQL proxy、Youtube 的 Vitess、淘宝的 Cobar、TDDL以及基于 Cobar 的 MyCAT、金山的 Kingshard、360 的 Atlas、京东的 JProxy，我在豌豆荚也写了一个。可以说，随便一个大公司都会造一个 MySQL Sharding 的方案。</p><h2>为什么我们要创建另外一个数据库？</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">昨天晚上我还跟一个同学聊到，基于 MySQL 的方案它的天花板在哪里，它的天花板特别明显。有一个思路是能不能通过 MySQL 的 server 把 InnoDB 变成一个分布式数据库，听起来这个方案很完美，但是很快就会遇到天花板。因为 MySQL 生成的执行计划是个单机的，它认为整个计划的 cost 也是单机的，我读取一行和读取下一行之间的开销是很小的，比如迭代 next row 可以立刻拿到下一行。实际上在一个分布式系统里面，这是不一定的。</p><div id="lowerFullwidthVCR" style="margin: 0px; border: 0px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; line-height: 25.2px; background-color: #ffffff;"></div><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，你把数据都拿回来计算这个太慢了，很多时候我们需要把我们的 expression 或者计算过程等等运算推下去，向上返回一个最终的计算结果，这个一定要用分布式的 plan，前面控制执行计划的节点，它必须要理解下面是分布式的东西，才能生成最好的 plan，这样才能实现最高的执行效率。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说你做一个 sum，你是一条条拿回来加，还是让一堆机器一起算，最后给我一个结果。 例如我有 100 亿条数据分布在 10 台机器上，并行在这 10台机器我可能只拿到 10 个结果，如果把所有的数据每一条都拿回来，这就太慢了，完全丧失了分布式的价值。聊到 MySQL 想实现分布式，另外一个实现分布式的方案就是 Proxy。但是 Proxy 本身的天花板在那里，就是它不支持分布式的 transaction，它不支持跨节点的 join，它无法理解复杂的 plan，一个复杂的 plan 打到 Proxy 上面，Proxy 就傻了，我到底应该往哪一个节点上转发呢，如果我涉及到 subquery sql 怎么办？所以这个天花板是瞬间会到，在传统模型下面的修改，很快会达不到我们的要求。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外一个很重要的是，MySQL 支持的复制方式是半同步或者是异步，但是半同步可以降级成异步，也就是说任何时候数据出了问题你不敢切换，因为有可能是异步复制，有一部分数据还没有同步过来，这时候切换数据就不一致了。前一阵子出现过某公司突然不能支付了这种事件，今年有很多这种类似的 case，所以微博上大家都在说&#8220;说好的异地多活呢？&#8221;&#8230;&#8230;</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">为什么传统的方案在这上面解决起来特别的困难，天花板马上到了，基本上不可能解决这个问题。另外是多数据中心的复制和数据中心的容灾，MySQL 在这上面是做不好的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/10.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">在前面三十年基本上是关系数据库的时代，那个时代创建了很多伟大的公司，比如说 IBM、Oracle、微软也有自己的数据库，早期还有一个公司叫 Sybase，有一部分特别老的程序员同学在当年的教程里面还可以找到这些东西，但是现在基本上看不到了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外是 NoSQL。NoSQL 也是一度非常火，像 Cassandra、MongoDB 等等，这些都属于在互联网快速发展的时候创建这些能够 scale 的方案，但 Redis scale 出来比较晚，所以很多时候大家把 Redis 当成一个 Cache，现在慢慢大家把它当成存储不那么重要的数据的数据库。因为它有了 scale 支持以后，大家会把更多的数据放在里面。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">然后到了 2015，严格来讲是到 2014 年到 2015 年之间，Raft 论文发表以后，真正的 NewSQL 的理论基础终于完成了。我觉得 NewSQL 这个理论基础，最重要的划时代的几篇论文，一个是谷歌的 Spanner，是在 2013 年初发布的；再就是 Raft 是在 2014 年上半年发布的。这几篇相当于打下了分布式数据库 NewSQL 的理论基础，这个模型是非常重要的，如果没有模型在上面是堆不起来东西的。说到现在，大家可能对于模型还是可以理解的，但是对于它的实现难度很难想象。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">前面我大概提到了我们为什么需要另外一个数据库，说到 Scalability 数据的伸缩，然后我们讲到需要 SQL，比如你给我一个纯粹的 key-velue 系统的 API，比如我要查找年龄在 10 岁到 20 岁之间的 email 要满足一个什么要求的。如果只有 KV 的 API 这是会写死人的，要写很多代码，但是实际上用 SQL 写一句话就可以了，而且 SQL 的优化器对整个数据的分布是知道的，它可以很快理解你这个 SQL，然后会得到一个最优的 plan，他得到这个最优的 plan 基本上等价于一个真正理解 KV 每一步操作的人写出来的程序。通常情况下，SQL 的优化器是为了更加了解或者做出更好的选择。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外一个就是 ACID 的事务，这是传统数据库必须要提供的基础。以前你不提供 ACID 就不能叫数据库，但是近些年大家写一个内存的 map 也可以叫自己是数据库。大家写一个 append-only 文件，我们也可以叫只读数据库，数据库的概念比以前极大的泛化了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外就是高可用和自动恢复，他们的概念是什么呢？有些人会有一些误解，因为今天还有朋友在现场问到，出了故障，比如说一个机房挂掉以后我应该怎么做切换，怎么操作。这个实际上相当于还是上一代的概念，还需要人去干预，这种不算是高可用。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">未来的高可用一定是系统出了问题马上可以自动恢复，马上可以变成可用。比如说一个机房挂掉了，十秒钟不能支付，十秒钟之后系统自动恢复了变得可以支付，即使这个数据中心再也不起来我整个系统仍然是可以支付的。Auto-Failover 的重要性就在这里。大家不希望在睡觉的时候被一个报警给拉起来，我相信大家以后具备这样一个能力，5 分钟以内的报警不用理会，挂掉一个机房，又挂掉一个机房，这种连续报警才会理。我们内部开玩笑说，希望大家都能睡个好觉，很重要的事情就是这个。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">说完应用层的事情，现在很有很多业务，在应用层自己去分片，比如说我按照 user ID在代码里面分片，还有一部分是更高级一点我会用到一致性哈希。问题在于它的复杂度，到一定程度之后我自动的分库，自动的分表，我觉得下一代数据库是不需要理解这些东西的，不需要了解什么叫做分库，不需要了解什么叫做分表，因为系统是全部自动搞定的。同时复杂度，如果一个应用不支持事务，那么在应用层去做，通常的做法是引入一个外部队列，引入大量的程序机制和状态转换，A 状态的时候允许转换到 B 状态，B 状态允许转换到 C 状态。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">举一个简单的例子，比如说在京东上买东西，先下订单，支付状态之后这个商品才能出库，如果不是支付状态一定不能出库，每一步都有严格的流程。</p><h2>Google Spanner / F1</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">说一下 Google 的 Spanner 和 F1，这是我非常喜欢的论文，也是我最近几年看过很多遍的论文。 Google Spanner 已经强大到什么程度呢？Google Spanner 是全球分布的数据库，在国内目前普遍做法叫做同城两地三中心，它们的差别是什么呢？以 Google 的数据来讲，谷歌比较高的级别是他们有 7 个副本，通常是美国保存 3 个副本，再在另外 2 个国家可以保存 2 个副本，这样的好处是万一美国两个数据中心出了问题，那整个系统还能继续可用，这个概念就是比如美国 3 个副本全挂了，整个数据都还在，这个数据安全级别比很多国家的安全级别还要高，这是 Google 目前做到的，这是全球分布的好处。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">现在国内主流的做法是两地三中心，但现在基本上都不能自动切换。大家可以看到很多号称实现了两地三中心或者异地多活，但是一出现问题都说不好意思这段时间我不能提供服务了。大家无数次的见到这种 case， 我就不列举了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Spanner 现在也提供一部分 SQL 特性。在以前，大部分 SQL 特性是在 F1 里面提供的，现在 Spanner 也在逐步丰富它的功能，Google 是全球第一个做到这个规模或者是做到这个级别的数据库。事务支持里面 Google 有点黑科技（其实也没有那么黑），就是它有<span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">GPS 时钟和原子钟</span>。大家知道在分布式系统里面，比如说数千台机器，两个事务启动先后顺序，这个顺序怎么界定(事务外部一致性)。这个时候 Google 内部使用了 GPS 时钟和原子钟，正常情况下它会使用一个GPS 时钟的一个集群，就是说我拿的一个时间戳，并不是从一个 GPS 上来拿的时间戳，因为大家知道所有的硬件都会有误差。如果这时候我从一个上拿到的 GPS 本身有点问题，那么你拿到的这个时钟是不精确的。而 Google 它实际上是在一批 GPS 时钟上去拿了能够满足 majority 的精度，再用时间的算法，得到一个比较精确的时间。大家知道 GPS 也不太安全，因为它是美国军方的，对于 Google 来讲要实现比国家安全级别更高的数据库，而 GPS 是可能受到干扰的，因为 GPS 信号是可以调整的，这在军事用途上面很典型的，大家知道导弹的制导需要依赖 GPS，如果调整了 GPS 精度，那么导弹精度就废了。所以他们还<span style="font-weight: 600; margin: 0px; border: 0px; padding: 0px;">用原子钟去校正 GPS</span>，如果 GPS 突然跳跃了，原子钟上是可以检测到 GPS 跳跃的，这部分相对有一点黑科技，但是从原理上来讲还是比较简单，比较好理解的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">最开始它 Spanner 最大的用户就是 Google 的 Adwords，这是 Google 最赚钱的业务，Google 就是靠广告生存的，我们一直觉得 Google 是科技公司，但是他的钱是从广告那来的，所以一定程度来讲 Google 是一个广告公司。Google 内部的方向先有了 Big table ，然后有了 MegaStore ，MegaStore 的下一代是 Spanner ，F1 是在 Spanner 上面构建的。</p><h2>TiDB and TiKV</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">TiKV 和 TiDB 基本上对应 Google Spanner 和 Google F1，用 Open Source 方式重建。目前这两个项目都开放在 GitHub 上面，两个项目都比较火爆，TiDB 是更早一点开源的， 目前 TiDB 在 GitHub 上 有 4300 多个 Star，每天都在增长。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，对于现在的社会来讲，我们觉得 Infrastructure 领域闭源的东西是没有任何生存机会的。没有任何一家公司，愿意把自己的身家性命压在一个闭源的项目上。举一个很典型的例子，在美国有一个数据库叫 FoundationDB，去年被苹果收购了。FoundationDB 之前和用户签的合约都是一年的合约。比如说，我给你服务周期是一年，现在我被另外一个公司收购了，我今年服务到期之后，我是满足合约的。但是其他公司再也不能找它服务了，因为它现在不叫 FoundationDB 了，它叫 Apple了，你不能找 Apple 给你提供一个 Enterprise service。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/11.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">TiDB 和 TiKV 为什么是两个项目，因为它和 Google 的内部架构对比差不多是这样的：TiKV 对应的是 Spanner，TiDB 对应的是 F1 。F1 里面更强调上层的分布式的 SQL 层到底怎么做，分布式的 Plan 应该怎么做，分布式的 Plan 应该怎么去做优化。同时 TiDB 有一点做的比较好的是，它兼容了 MySQL 协议，当你出现了一个新型的数据库的时候，用户使用它是有成本的。大家都知道作为开发很讨厌的一个事情就是，我要每个语言都写一个 Driver，比如说你要支持 C++、你要支持 Java、你要支持 Go 等等，这个太累了，而且用户还得改他的程序，所以我们选择了一个更加好的东西兼容 MySQL 协议，让用户可以不用改。一会我会用一个视频来演示一下，为什么一行代码不改就可以用，用户就能体会到 TiDB 带来的所有的好处。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/12.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这个图实际上是整个协议栈或者是整个软件栈的实现。大家可以看到整个系统是高度分层的，从最底下开始是 RocksDB ，然后再上面用 Raft 构建一层可以被复制的 RocksDB ，在这一层的时候它还没有 Transaction，但是整个系统现在的状态是所有写入的数据一定要保证它复制到了足够多的副本。也就是说只要我写进来的数据一定有足够多的副本去 cover 它，这样才比较安全，在一个比较安全的 Key-value store 上面， 再去构建它的多版本，再去构建它的分布式事务，然后在分布式事务构建完成之后，就可以轻松的加上 SQL 层，再轻松的加上MySQL 协议的支持。然后，这两天我比较好奇，自己写了 MongoDB 协议的支持，然后我们可以用 MongoDB 的客户端来玩，就是说协议这一层是高度可插拔的。TiDB 上可以在上面构建一个 MongoDB 的协议，相当于这个是构建一个 SQL 的协议，可以构建一个 NoSQL 的协议。这一点主要是用来验证 TiKV 在模型上面的支持能力。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/13.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是整个 TiKV 的架构图，从这个看来，整个集群里面有很多 Node，比如这里画了四个 Node ，分别对应了四个机器。每一个 Node 上可以有多个 Store，每个 Store 里面又会有很多小的 Region，就是说一小片数据，就是一个 Region 。从全局来看所有的数据被划分成很多小片，每个小片默认配置是 64M，它已经足够小，可以很轻松的从一个节点移到另外一个节点，Region 1 有三个副本，它分别在 Node1、Node 2 和 Node4 上面， 类似的Region 2，Region 3 也是有三个副本。每个 Region 的所有副本组成一个 Raft Group，整个系统可以看到很多这样的 Raft groups。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Raft 细节我不展开了，大家有兴趣可以找我私聊或者看一下相应的资料。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">因为整个系统里面我们可以看到上一张图里面有很多 Raft group 给我们，不同 Raft group 之间的通讯都是有开销的。所以我们有一个类似于 MySQL 的 group commit 机制 ，你发消息的时候实际上可以 share 同一个 connection ， 然后 pipeline + batch 发送，很大程度上可以省掉大量 syscall 的开销。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外，其实在一定程度上后面我们在支持压缩的时候，也有非常大的帮助，就是可以减少数据的传输。对于整个系统而言，可能有数百万的 Region，它的大小可以调整，比如说 64M、128M、256M，这个实际上依赖于整个系统里面当前的状况。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说我们曾经在有一个用户的机房里面做过测试，这个测试有一个香港机房和新加坡的机房。结果我们在做复制的时候，新加坡的机房大于 256M 就复制不过去，因为机房很不稳定，必须要保证数据切的足够小，这样才能复制过去。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">如果一个 Region 太大以后我们会自动做 SPLIT，这是非常好玩的过程，有点像细胞的分裂。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">然后 TiKV 的 Raft 实现，是从 etcd 里面 port 过来的，为什么要从 etcd 里面 port 过来呢？首先 TiKV 的 Raft 实现是用 Rust 写的。作为第一个做到生产级别的 Raft 实现，所以我们从 etcd 里面把它用 Go 语言写的 port 到这边。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/14.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这个是 Raft 官网上面列出来的 TiKV在里面的状态，大家可以看到 TiKV 把所有 Raft 的 feature 都实现了。 比如说 Leader Election、Membership Changes，这个是非常重要的，整个系统的 scale 过程高度依赖 Membership Changes，后面我用一个图来讲这个过程。后面这个是 Log Compaction，这个用户不太关心。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/15.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是很典型的细胞分裂的图，实际上 Region 的分裂过程和这个是类似的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">我们看一下扩容是怎么做的。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/16.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说以现在的系统假设，我们刚开始说只有三个节点，有 Region1 分别是在 1 、2、4，我用虚线连接起来代表它是一个 Raft group ，大家可以看到整个系统里面有三个 Raft group ，在每一个 Node 上面数据的分布是比较均匀的，在这个假设每一个 Region 是 64M ，相当于只有一个 Node 上面负载比其他的稍微大一点点。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">一个在线视频默认我们都是推荐 3 个副本或者 5 个副本的配置。Raft 本身有一个特点，如果一个 leader down 掉之后，其它的节点会选一个新的 leader ，那么这个新的 leader 会把它还没有 commit 但已经 reply 过去的 log 做一个 commit ，然后会再做 apply ，这个有点偏 Raft 协议，细节我不讲了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">复制数据的小的 Region，它实际上是跨多个数据中心做的复制。这里面最重要的一点是永远不丢失数据，无论如何我保证我的复制一定是复制到 majority ，任何时候我只要对外提供服务，允许外面写入数据一定要复制到 majority 。很重要的一点就是恢复的过程一定要是自动化的，我前面已经强调过，如果不能自动化恢复，那么中间的宕机时间或者对外不可服务的时间，便不是由整个系统决定的，这是相对回到了几十年前的状态。</p><h2>MVCC</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">MVCC 我稍微仔细讲一下这一块。MVCC 的好处，它很好支持 Lock-free 的 snapshot read ，一会儿我有一个图会展示 MVCC 是怎么做的。isolation level 就不讲了， MySQL 里面的级别是可以调的，我们的 TiKV 有 SI，还有 SI+lock，默认是支持 SI 的这种隔离级别，然后你写一个 select for update 语句，这个会自动的调整到 SI 加上 lock 这个隔离级别。这个隔离级别基本上和 SSI 是一致的。还有一个就是 GC 的问题，如果你的系统里面的数据产生了很多版本，你需要把这个比较老的数据给 GC 掉，比如说正常情况下我们是不删除数据的， 你写入一行，然后再写入一行，不断去 update 同一行的时候，每一次 update 会产生新的版本，新的版本就会在系统里存在，所以我们需要一个 GC 的模块把比较老的数据给 GC 掉，实际上这个 GC 不是 Go 里面的GC，不是 Java 的 GC，而是数据的 GC。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;"><img _href="img://null" _p="true" src="http://cdn2.infoqstatic.com/statics_s2_20160816-0334/resource/articles/how-to-build-a-distributed-database/zh/resources/17.png" width="550" style="border: 0px; margin: 0px 10px 10px 0px; padding: 0px;"  alt="" /></p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是一个数据版本，大家可以看到我们的数据分成两块，一个是 meta，一个是 data。meta 相对于描述我的数据当前有多少个版本。大家可以看到绿色的部分，比如说我们的 meta key 是 A ，keyA 有三个版本，是 A1 、A2、A3，我们把 key 自己和 version 拼到一起。那我们用 A1、A2、A3 分别描述 A 的三个版本，那么就是 version 1/2/3。meta 里面描述，就是我的整个 key 相对应哪个版本，我想找到那个版本。比如说我现在要读取 key A 的版本10，但显然现在版本 10 是没有的，那么小于版本 10 最大的版本是 3，所以这时我就能读取到 3，这是它的隔离级别决定的。关于 data，我刚才已经讲过了。</p><h2>分布式事务模型</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">接下来是分布式事务模型，其实是基于 Google Percolator，这是 Google 在 2006 发表的一篇论文，是 Google 在做内部增量处理的时候发现了这个方法，本质上还是二阶段提交的。这使用的是一个乐观锁，比如说我提供一个 transaction ，我去改一个东西，改的时候是发布在本地的，并没有马上 commit 到数据存储那一端，这个模型就是说，我修改的东西我马上去 Lock 住，这个基本就是一个悲观锁。但如果到最后一刻我才提交出去，那么锁住的这一小段的时间，这个时候实现的是乐观锁。乐观锁的好处就是当你冲突很小的时候可以得到非常好的性能，因为冲突特别小，所以我本地修改通常都是有效的，所以我不需要去 Lock ，不需要去 roll back 。本质上分布式事务就是 2PC (两阶段提交) 或者是 2+x PC，基本上没有 1PC，除非你在别人的级别上做弱化。比如说我允许你读到当前最新的版本，也允许你读到前面的版本，书里面把这个叫做幻读。如果你调到这个程度是比较容易做 1PC 的，这个实际上还是依赖用户设定的隔离级别的，如果用户需要更高的隔离级别，这个 1PC就不太好做了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这是一个路由，正常来讲，大家可能会好奇一个 SQL 语句怎么最后会落到存储层，然后能很好的运行，最后怎么能映射到 KV 上面，又怎么能路由到正确的节点，因为整个系统可能有上千个节点，你怎么能正确路由到那一个的节点。我们在 TiDB 有一个 TiKV driver ， 另外 TiKV 对外使用的是 Google Protocol Buffer 来作为通讯的编码格式。</p><h2>Placement Driver</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">来说一下 Placement Driver 。Placement Driver 是什么呢？整个系统里面有一个节点，它会时刻知道现在整个系统的状态。比如说每个机器的负载，每个机器的容量，是否有新加的机器，新加机器的容量到底是怎么样的，是不是可以把一部分数据挪过去，是不是也是一样下线， 如果一个节点在十分钟之内无法被其他节点探测到，我认为它已经挂了，不管它实际上是不是真的挂了，但是我也认为它挂了。因为这个时候是有风险的，如果这个机器万一真的挂了，意味着你现在机器的副本数只有两个，有一部分数据的副本数只有两个。那么现在你必须马上要在系统里面重新选一台机器出来，它上面有足够的空间，让我现在只有两个副本的数据重新再做一份新的复制，系统始终维持在三个副本。整个系统里面如果机器挂掉了，副本数少了，这个时候应该会被自动发现，马上补充新的副本，这样会维持整个系统的副本数。这是很重要的 ，为了避免数据丢失，必须维持足够的副本数，因为副本数每少一个，你的风险就会再增加。这就是 Placement Driver 做的事情。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">同时，Placement Driver 还会根据性能负载，不断去 move 这个 data 。比如说你这边负载已经很高了，一个磁盘假设有 100G，现在已经用了 80G，另外一个机器上也是 100G，但是他只用了 20G，所以这上面还可以有几十 G 的数据，比如 40G 的数据，你可以 move 过去，这样可以保证系统有很好的负载，不会出现一个磁盘巨忙无比，数据已经多的装不下了，另外一个上面还没有东西，这是 Placement Driver 要做的东西。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Raft 协议还提供一个很高级的特性叫 leader transfer。leader transfer 就是说在我不移动数据的时候，我把我的 leadership 给你，相当于从这个角度来讲，我把流量分给你，因为我是 leader，所以数据会到我这来，但我现在把 leader给你，我让你来当 leader，原来打给我的请求会被打给你，这样我的负载就降下来。这就可以很好的动态调整整个系统的负载，同时又不搬移数据。不搬移数据的好处就是，不会形成一个抖动。</p><h2>MySQL Sharding</h2><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">MySQL Sharding 我前面已经提到了它的各种天花板，MySQL Sharding 的方案很典型的就是解决基本问题以后，业务稍微复杂一点，你在 sharding 这一层根本搞不定。它永远需要一个 sharding key，你必须要告诉我的 proxy，我的数据要到哪里找，对用户来说是极不友好的，比如我现在是一个单机的，现在我要切入到一个分布式的环境，这时我必须要改我的代码，我必须要知道我这个 key ，我的 row 应该往哪里 Sharding。如果是用 ORM ，这个基本上就没法做这个事情了。有很多 ORM 它本身假设我后面只有一个 MySQL。但 TiDB 就可以很好的支持，因为我所有的角色都是对的，我不需要关注 Sharding 、分库、分表这类的事情。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">这里面有一个很重要的问题没有提，我怎么做 DDL。如果这个表非常大的话，比如说我们有一百亿吧，横跨了四台机器，这个时候你要给它做一个新的 Index，就是我要添加一个新的索引，这个时候你必须要不影响任何现有的业务，实际上这是多阶段提交的算法，这个是 Google 和 F1 一起发出来那篇论文。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">简单来讲是这样的，先把状态标记成 delete only ，delete only 是什么意思呢？因为在分布式系统里面，所有的系统对于 schema 的视野不是一致的，比如说我现在改了一个值，有一部分人发现这个值被改了，但是还有一部分人还没有开始访问这个，所以根本不知道它被改了。然后在一个分布系统里，你也不可能实时通知到所有人在同一时刻发现它改变了。比如说从有索引到没有索引，你不能一步切过去，因为有的人认为它有索引，所以他给它建了一个索引，但是另外一个机器他认为它没有索引，所以他就把数据给删了，索引就留在里面了。这样遇到一个问题，我通过索引找的时候告诉我有， 实际数据却没有了，这个时候一致性出了问题。比如说我 count 一个 email 等于多少的，我通过 email 建了一个索引，我认为它是在，但是 UID 再转过去的时候可能已经不存在了。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">比如说我先标记成 delete only，我删除它的时候不管它现在有没有索引，我都会尝试删除索引，所以我的数据是干净的。如果我删除掉的话，我不管结果是什么样的，我尝试去删一下，可能这个索引还没 build 出来，但是我仍然删除，如果数据没有了，索引一定没有了，所以这可以很好的保持它的一致性。后面再类似于前面，先标记成 write only 这种方式，连续再迭代这个状态，就可以迭代到一个最终可以对外公开的状态。比如说当我迭代到一定程度的时候，我可以从后台 build index ，比如说我一百亿，正在操作的 index 会马上 build，但是还有很多没有 build index ，这个时候后台不断的跑 map-reduce 去 build index ，直到整个都 build 完成之后，再对外 public ，就是说我这个索引已经可用了，你可以直接拿索引来找，这个是非常经典的。在这个 Online，Asynchronous Schema Change in F1 paper之前，大家都不知道这事该怎么做。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">Proxy Sharding 的方案不支持分布式事务，更不用说跨数据中心的一致性事务了。 TiKV 很好的支持 transaction，刚才提到的 Raft 除了增加副本之外，还有 leader transfer，这是一个传统的方案都无法提供的特性。以及它带来的好处，当我瞬间平衡整个系统负载的时候，对外是透明的， 做 leader transfer 的时候并不需要移动数据，只是个简单的 leader transfer 消息。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">然后说一下如果大家想参与我们项目的话是怎样的过程，因为整个系统是完全开源的，如果大家想参与其中任何一部分都可以，比如说我想参与到分布式 KV，可以直接贡献到 TiKV。TiKV 需要写 Rust，如果大家对这块特别有激情可以体验写 Rust 的感觉 。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">TiDB 是用 Go 写的，Go 在中国的群众基础是非常多的，目前也有很多人在贡献。整个 TiDB 和TiKV 是高度协作的项目，因为 TiDB 目前还用到了 etcd ，我们在和 CoreOS 在密切的合作，也特别感谢 CoreOS 帮我们做了很多的支持，我们也为 CoreOS 的 etcd 提了一些 patch。同时，TiKV 使用 RocksDB ，所以我们也为 RocksDB 提了一些 patch 和 test，我们也非常感谢 Facebook RocksDB team 对我们项目的支持。</p><p style="margin: 0px 0px 15px; padding: 0px; border: 0px; float: none; line-height: 25.2px; clear: none; width: 610px; font-family: &quot;Lantinghei SC&quot;, &quot;Open Sans&quot;, Arial, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, STHeiti, &quot;WenQuanYi Micro Hei&quot;, SimSun, Helvetica, sans-serif; background-color: #ffffff;">另外一个是 PD，就是我们前面提的 Placement Driver，它负责监控整个系统。这部分的算法比较好玩，大家如果有兴趣的话，可以去自己控制整个集群的调度，它和 Kubernetes 或者是Mesos 的调度算法是不一样的，因为它调度的维度实际上比那个要更多。比如说磁盘的容量，你的 leader 的数量，你的网络当前的使用情况，你的 IO 的负载和 CPU 的负载都可以放进去。同时你还可以让它调度不要跨一个机房里面建多个副本。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/431664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-08-23 15:12 <a href="http://www.blogjava.net/xiaomage234/archive/2016/08/23/431664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Mac上安装MySQL</title><link>http://www.blogjava.net/xiaomage234/archive/2016/04/15/430102.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 15 Apr 2016 02:14:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/04/15/430102.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/430102.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/04/15/430102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/430102.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/430102.html</trackback:ping><description><![CDATA[<p>我安装的MySQL版本是5.7.10 。 官网最新版本下载地址是：<a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL下载地址</a></p><p>1、选择一个DMG 后 &nbsp;下载-&gt;安装</p><p>安装完后会提示一句话 如下</p><p>A temporary password is generated for root@localhost: dwstkti5xJ&lt;5</p><p>If you lose this password, please consult the section How to Reset the Root Password in the MySQL reference manual.</p><p>把root@localhost: dwstkti5xJ&lt;5 复制到一个地方 后面要用。</p><p>mysql 默认是安装到了&nbsp; usr/local/mysql &nbsp;下面</p><p>2、安装完后 在偏好设置里启动MySQL服务，点击"Start MySQL Server"</p><div imagebubble"="" widget="ImageBubble"> <img src="http://upload-images.jianshu.io/upload_images/559028-7431f937b46a8e2e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="http://upload-images.jianshu.io/upload_images/559028-7431f937b46a8e2e.png?imageMogr2/auto-orient/strip" data-image-slug="7431f937b46a8e2e" data-width="350" data-height="316"  alt="" /><br /><div></div> </div><div imagebubble"="" widget="ImageBubble"> <img src="http://upload-images.jianshu.io/upload_images/559028-ac08739d34923cd3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="http://upload-images.jianshu.io/upload_images/559028-ac08739d34923cd3.png?imageMogr2/auto-orient/strip" data-image-slug="ac08739d34923cd3" data-width="572" data-height="160"  alt="" /><br /><div></div> </div><p>3、添加MySQL的快捷 命令 方式 。 为什么要弄这个？ 为了方便的直接在终端默认打开的目录下使用mysql xxx 命令 而不用麻烦的进入mysql的安装目录下 进行操作。 有如下两个：</p><p>alias mysql=/usr/local/mysql/bin/mysql<br /></p><p>alias mysqladmin=/usr/local/mysql/bin/mysqladmin</p><p>4、重置(修改)MySQL的root密码。为什么要重置呢？MySQL安装完后会给一个临时的密码 也就是上文中的 dwstkti5xJ&lt;5 &nbsp; ，如果你不修改这个密码 使用临时密码登陆mysql 后 各种命令是不能用的，会一直提示你 &nbsp;需要重置密码。</p><p>mysqladmin -u root -p password hahaha&nbsp; &nbsp; &nbsp; #hahaha是我要修改为的密码&nbsp;  回车后 输入临时密码dwstkti5xJ&lt;5 &nbsp; 就算是修改成功了</p><p>5、使用 步骤4里设置的新密码来登陆。 为什么要登陆？登陆后才能在mysql里创建数据库和各种表 等等。</p><p>mysql -u root -p<br /></p><p>输入新密码 后 回车</p><p>6、设置配置文件。为什么要弄配置文件 ？&nbsp; 其实到第五步 就算是安装完成了，但是正常情况下mysql需要一个配置文件，里面存放了 许多属性 比如字符编码啦&nbsp; 连接数啦 什么的。这个配置文件默认是在 /usr/local/mysql/support-files/&nbsp;  下面&nbsp; 叫做 my-default.cnf 。 mysql启动时默认会从下面四个位置寻找my.cnf 然后使用 , 大家都使用第一种情况，所以咱也使用。</p><p>&nbsp;/etc/my.cnf &nbsp; &nbsp; &nbsp;/etc/mysql/my.cnf &nbsp; &nbsp; &nbsp;/usr/local/mysql/etc/my.cnf &nbsp; &nbsp; &nbsp; ~/.my.cnf</p><p>所以现在要做的就是 把my-default.cnf 复制到 /etc 的下面，并且修改名字为my.cnf 。 命令如下：</p><p>sudo cp -rv /usr/local/mysql/support-files/my-default.cnf &nbsp;/etc&nbsp;  #复制 配置文件 到etc下面</p><p>sudo mv my-default.cnf my.cnf&nbsp; &nbsp; #修改名字为my.cnf</p><p>配置文件就算是弄好了 &nbsp;要想使之生效 必须重启mysql ，还是到偏好设置里 先停止 再开启。</p><p>7、修改配置文件my.cnf 。为什么要修改呢？可以不改&nbsp; 本步骤只是根据一个例子 说明如何修改配置文件。本步骤修改的是字符的编码。 &nbsp;使用新密码登陆mysql后&nbsp;</p><p>mysql&gt; show variables like '%char%';&nbsp; &nbsp; #回车后&nbsp; 会 看到如下文字</p><p>| Variable_name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | Value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</p><p>| character_set_client&nbsp; &nbsp;  | utf8&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |</p><p>| character_set_connection | utf8&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |</p><p>| character_set_database&nbsp;  | latin1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |</p><p>| character_set_filesystem | binary&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |</p><p>| character_set_results&nbsp; &nbsp; | utf8&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |</p><p>| character_set_server&nbsp; &nbsp;  | latin1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |</p><p>| character_set_system&nbsp; &nbsp;  | utf8&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  |</p><p>| character_sets_dir&nbsp; &nbsp; &nbsp;  | /usr/local/mysql-5.7.10-osx10.9-x86_64/share/charsets/</p><p>可以看到character_set_server和character_set_database的字符编码是latin1&nbsp; 我现在就是要把它改为utf8格式的。</p><p>sudo chmod a+w /etc/my.cnf &nbsp; #修改权限为可写&nbsp; 因为复制过来的这个my-default.cnf文件(现在改名为my.cnf了) 是只读权限的 要想修改里面的内容当然要改为可写权限的了。<br /></p><p>vi&nbsp;  /etc/my.cnf&nbsp; #进去后开始修改&nbsp; 找到 [mysqld]&nbsp; 这个标示后在它的下面粘贴上需要配置的参数 &nbsp;最终效果如下</p><div imagebubble"="" widget="ImageBubble"> <img src="http://upload-images.jianshu.io/upload_images/559028-f2f46074c6c91a92.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="http://upload-images.jianshu.io/upload_images/559028-f2f46074c6c91a92.png?imageMogr2/auto-orient/strip" data-image-slug="f2f46074c6c91a92" data-width="1526" data-height="266"  alt="" /><br /><div></div> </div><p>修改完后 保存退出。</p><p>sudo chmod a-w /etc/my.cnf &nbsp; #取消my.cnf 的可写权限&nbsp; 因为如果不取消这个配置文件的可写权限&nbsp; mysql启动时就不理你修改好的这个配置文件 就是给你忽略掉了，意思就是说 这个配置文件必须是只读的。<br /></p><p>修改完后再在偏好设置里重启一下mysql。</p><p>各种字符编码的意义如下 （网上抄的）</p><p>character_set_client&nbsp; 为客户端使用的字符集；<br /></p><p>character_set_connection 为连接数据库的字符集设置类型 如果程序没有指明连接数据库使用的字符集类型 则按照服务器端默认的字符集设置。</p><p>character_set_database&nbsp;  为数据库服务器中某个库使用的字符集设定，如果建库时没有指明 将使用服务器安装时指定的字符集设置。</p><p>character_set_results&nbsp; 为数据库 给客户端返回时使用的字符集设定 如果没指明 使用服务端默认的字符集。</p><p>character_set_server&nbsp;  为服务器安装时指定的默认字符集设定</p><p>character_set_system&nbsp; &nbsp; 为数据库系统使用的字符集设定</p><p><br /></p><p>结束。</p><br /><br /><div>文／大象飞（简书作者）<br />原文链接：http://www.jianshu.com/p/65ee08a4a0d0<br />著作权归作者所有，转载请联系作者获得授权，并标注&#8220;简书作者&#8221;。</div><img src ="http://www.blogjava.net/xiaomage234/aggbug/430102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-04-15 10:14 <a href="http://www.blogjava.net/xiaomage234/archive/2016/04/15/430102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring加Mybatis实现MySQL数据库主从读写分离</title><link>http://www.blogjava.net/xiaomage234/archive/2016/01/12/429021.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 12 Jan 2016 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/01/12/429021.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/429021.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/01/12/429021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/429021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/429021.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">1. 数据源也就是jdbc.properties，因为是主从读写分离，那么肯定有两个数据源了</p><pre ruby"="" style="padding: 0.3em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #333333; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 12px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background-color: #f6f6f6;">jdbc.driver=org.mariadb.jdbc.Driver  <span style="color: #999988; font-style: italic;"># 从库，只读</span> slave.jdbc.url=<span style="color: #990073;">jdbc:</span><span style="color: #990073;">mariadb:</span>/<span style="color: #009926;">/xxx.xxx.xxx.xxx:3306/xxx</span><span style="color: #009999;">?c</span>haracterEncoding=UTF-<span style="color: #009999;">8</span>&amp;zeroDateTimeBehavior=convertToNull&amp;noAccessToProcedureBodies=<span style="font-weight: bold;">true</span>&amp;autoReconnect=<span style="font-weight: bold;">true</span> slave.jdbc.username=xxx slave.jdbc.password=xxx  <span style="color: #999988; font-style: italic;"># 主库，需要写</span> master.jdbc.url=<span style="color: #990073;">jdbc:</span><span style="color: #990073;">mariadb:</span>/<span style="color: #009926;">/xxx.xxx.xxx.xxx:3306/xxx</span><span style="color: #009999;">?c</span>haracterEncoding=UTF-<span style="color: #009999;">8</span>&amp;zeroDateTimeBehavior=convertToNull&amp;noAccessToProcedureBodies=<span style="font-weight: bold;">true</span>&amp;autoReconnect=<span style="font-weight: bold;">true</span> master.jdbc.username=xxx master.jdbc.password=xxx</pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">这个非常简单和普通的区别不是很大，另外数据库的驱动是：mariadb，动下面就是第二个配置文件spring.xml</p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">2. spring.xml</p><pre xml"="" style="padding: 0.3em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #333333; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 12px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background-color: #f6f6f6;"><span style="color: #999999; font-weight: bold;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span> <span style="color: #000080;">&lt;beans <span style="color: #008080;">xmlns</span>=<span style="color: #dd1144;">"http://www.springframework.org/schema/beans"</span>  <span style="color: #008080;">xmlns:xsi</span>=<span style="color: #dd1144;">"http://www.w3.org/2001/XMLSchema-instance"</span> <span style="color: #008080;">xmlns:context</span>=<span style="color: #dd1144;">"http://www.springframework.org/schema/context"</span>  <span style="color: #008080;">xsi:schemaLocation</span>=<span style="color: #dd1144;">" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "</span>&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- Import properties file --&gt;</span>  <span style="color: #000080;">&lt;context:property-placeholder <span style="color: #008080;">location</span>=<span style="color: #dd1144;">"classpath:jdbc.properties"</span> /&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- Auto Scan --&gt;</span>  <span style="color: #000080;">&lt;context:component-scan <span style="color: #008080;">base-package</span>=<span style="color: #dd1144;">"cn.bridgeli.demo"</span> /&gt;</span> <span style="color: #000080;">&lt;/beans&gt;</span> </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">这个文件很简单，有两个作用，&#9312;. 引入数据源配置文件；&#9313;. spring扫描的文件的路径</p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">3. spring-mybatis.xml配置文件</p><pre xml"="" style="padding: 0.3em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #333333; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 12px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background-color: #f6f6f6;"><span style="color: #999999; font-weight: bold;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span> <span style="color: #000080;">&lt;beans <span style="color: #008080;">xmlns</span>=<span style="color: #dd1144;">"http://www.springframework.org/schema/beans"</span> <span style="color: #008080;">xmlns:xsi</span>=<span style="color: #dd1144;">"http://www.w3.org/2001/XMLSchema-instance"</span> <span style="color: #008080;">xmlns:tx</span>=<span style="color: #dd1144;">"http://www.springframework.org/schema/tx"</span> <span style="color: #008080;">xmlns:aop</span>=<span style="color: #dd1144;">"http://www.springframework.org/schema/aop"</span> <span style="color: #008080;">xsi:schemaLocation</span>=<span style="color: #dd1144;">" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd "</span>&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"slaveDataSourceImpl"</span> <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"com.jolbox.bonecp.BoneCPDataSource"</span> <span style="color: #008080;">destroy-method</span>=<span style="color: #dd1144;">"close"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"driverClass"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${jdbc.driver}"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"jdbcUrl"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${slave.jdbc.url}"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"username"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${slave.jdbc.username}"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"password"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${slave.jdbc.password}"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 检查数据库连接池中空闲连接的间隔时间，单位是分，默认值：240，如果要取消则设置为0 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"idleConnectionTestPeriodInMinutes"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"10"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 连接池中未使用的链接最大存活时间，单位是分，默认值：60，如果要永远存活设置为0 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"idleMaxAgeInMinutes"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"10"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 每个分区最大的连接数 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"maxConnectionsPerPartition"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"20"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 每个分区最小的连接数 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"minConnectionsPerPartition"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"10"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 分区数 ，默认值2，最小1，推荐3-4，视应用而定 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"partitionCount"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"3"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 每次去拿数据库连接的时候一次性要拿几个,默认值：2 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"acquireIncrement"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"3"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 缓存prepared statements的大小，默认值：0 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"statementsCacheSize"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"50"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 在做keep-alive的时候的SQL语句 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"connectionTestStatement"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"select 1 from dual"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 在每次到数据库取连接的时候执行的SQL语句，只执行一次 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"initSQL"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"select 1 from dual"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"closeConnectionWatch"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"false"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"logStatementsEnabled"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"true"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"transactionRecoveryEnabled"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"true"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"masterDataSourceImpl"</span> <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"com.jolbox.bonecp.BoneCPDataSource"</span> <span style="color: #008080;">destroy-method</span>=<span style="color: #dd1144;">"close"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"driverClass"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${jdbc.driver}"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"jdbcUrl"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${master.jdbc.url}"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"username"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${master.jdbc.username}"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"password"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"${master.jdbc.password}"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 检查数据库连接池中空闲连接的间隔时间，单位是分，默认值：240，如果要取消则设置为0 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"idleConnectionTestPeriodInMinutes"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"10"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 连接池中未使用的链接最大存活时间，单位是分，默认值：60，如果要永远存活设置为0 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"idleMaxAgeInMinutes"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"10"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 每个分区最大的连接数 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"maxConnectionsPerPartition"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"20"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 每个分区最小的连接数 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"minConnectionsPerPartition"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"10"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 分区数 ，默认值2，最小1，推荐3-4，视应用而定 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"partitionCount"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"3"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 每次去拿数据库连接的时候一次性要拿几个,默认值：2 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"acquireIncrement"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"3"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 缓存prepared statements的大小，默认值：0 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"statementsCacheSize"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"50"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 在做keep-alive的时候的SQL语句 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"connectionTestStatement"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"select 1 from dual"</span> /&gt;</span>   <span style="color: #999988; font-style: italic;">&lt;!-- 在每次到数据库取连接的时候执行的SQL语句，只执行一次 --&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"initSQL"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"select 1 from dual"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"closeConnectionWatch"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"false"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"logStatementsEnabled"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"true"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"transactionRecoveryEnabled"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"true"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- DataSource/Master --&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"masterDataSource"</span>   <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"targetDataSource"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"masterDataSourceImpl"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"masterTransactionManager"</span>   <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"dataSource"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"masterDataSource"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"masterTransactionTemplate"</span>   <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.springframework.transaction.support.TransactionTemplate"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"transactionManager"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"masterTransactionManager"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- DataSource/Slave --&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"slaveDataSource"</span>   <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"targetDataSource"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"slaveDataSourceImpl"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"slaveTransactionManager"</span>   <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"dataSource"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"slaveDataSource"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"slaveTransactionTemplate"</span>   <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.springframework.transaction.support.TransactionTemplate"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"transactionManager"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"slaveTransactionManager"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- Mybatis/Master --&gt;</span>   <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"masterSqlSessionFactory"</span> <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.mybatis.spring.SqlSessionFactoryBean"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"dataSource"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"masterDataSource"</span>&gt;</span><span style="color: #000080;">&lt;/property&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"configLocation"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"classpath:mybatis.xml"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"typeAliasesPackage"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"cn.bridgeli.demo.entity"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"mapperLocations"</span>&gt;</span>    <span style="color: #000080;">&lt;list&gt;</span>     <span style="color: #000080;">&lt;value&gt;</span>classpath:cn/bridgeli/demo/mapper/master/*.xml<span style="color: #000080;">&lt;/value&gt;</span>    <span style="color: #000080;">&lt;/list&gt;</span>   <span style="color: #000080;">&lt;/property&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.mybatis.spring.mapper.MapperScannerConfigurer"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"basePackage"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"cn.bridgeli.demo.mapper.master"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"sqlSessionFactoryBeanName"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"masterSqlSessionFactory"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- Mybatis/Slave --&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"slaveSqlSessionFactory"</span> <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.mybatis.spring.SqlSessionFactoryBean"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"dataSource"</span> <span style="color: #008080;">ref</span>=<span style="color: #dd1144;">"slaveDataSource"</span>&gt;</span><span style="color: #000080;">&lt;/property&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"configLocation"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"classpath:mybatis.xml"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"typeAliasesPackage"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"cn.bridgeli.demo.entity"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"mapperLocations"</span>&gt;</span>    <span style="color: #000080;">&lt;list&gt;</span>     <span style="color: #000080;">&lt;value&gt;</span>classpath:cn/bridgeli/demo/mapper/slave/*.xml<span style="color: #000080;">&lt;/value&gt;</span>    <span style="color: #000080;">&lt;/list&gt;</span>   <span style="color: #000080;">&lt;/property&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #000080;">&lt;bean <span style="color: #008080;">class</span>=<span style="color: #dd1144;">"org.mybatis.spring.mapper.MapperScannerConfigurer"</span>&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"basePackage"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"cn.bridgeli.demo.mapper.slave"</span> /&gt;</span>   <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"sqlSessionFactoryBeanName"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"slaveSqlSessionFactory"</span> /&gt;</span>  <span style="color: #000080;">&lt;/bean&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- Configuration transaction advice --&gt;</span>  <span style="color: #000080;">&lt;tx:advice <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"txAdvice"</span> <span style="color: #008080;">transaction-manager</span>=<span style="color: #dd1144;">"masterTransactionManager"</span>&gt;</span>   <span style="color: #000080;">&lt;tx:attributes&gt;</span>    <span style="color: #000080;">&lt;tx:method <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"add*"</span> <span style="color: #008080;">propagation</span>=<span style="color: #dd1144;">"REQUIRED"</span> /&gt;</span>    <span style="color: #000080;">&lt;tx:method <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"update*"</span> <span style="color: #008080;">propagation</span>=<span style="color: #dd1144;">"REQUIRED"</span> /&gt;</span>    <span style="color: #000080;">&lt;tx:method <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"delete*"</span> <span style="color: #008080;">propagation</span>=<span style="color: #dd1144;">"REQUIRED"</span> /&gt;</span>    <span style="color: #000080;">&lt;tx:method <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"get*"</span> <span style="color: #008080;">read-only</span>=<span style="color: #dd1144;">"true"</span> <span style="color: #008080;">propagation</span>=<span style="color: #dd1144;">"SUPPORTS"</span> /&gt;</span>    <span style="color: #000080;">&lt;tx:method <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"list*"</span> <span style="color: #008080;">read-only</span>=<span style="color: #dd1144;">"true"</span> <span style="color: #008080;">propagation</span>=<span style="color: #dd1144;">"SUPPORTS"</span> /&gt;</span>   <span style="color: #000080;">&lt;/tx:attributes&gt;</span>  <span style="color: #000080;">&lt;/tx:advice&gt;</span>  <span style="color: #999988; font-style: italic;">&lt;!-- Configuration transaction aspect --&gt;</span>  <span style="color: #000080;">&lt;aop:config&gt;</span>   <span style="color: #000080;">&lt;aop:pointcut <span style="color: #008080;">id</span>=<span style="color: #dd1144;">"systemServicePointcut"</span>    <span style="color: #008080;">expression</span>=<span style="color: #dd1144;">"execution(* cn.bridgeli.demo.service.*.*(..))"</span> /&gt;</span>   <span style="color: #000080;">&lt;aop:advisor <span style="color: #008080;">advice-ref</span>=<span style="color: #dd1144;">"txAdvice"</span> <span style="color: #008080;">pointcut-ref</span>=<span style="color: #dd1144;">"systemServicePointcut"</span> /&gt;</span>  <span style="color: #000080;">&lt;/aop:config&gt;</span> <span style="color: #000080;">&lt;/beans&gt;</span> </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">这个配置文件老夫是完整的copy了下来，看起来也比较易懂，就不做解释了，需要说明的mybatis下那些dao的接口，分别对应cn.bridgeli.demo.mapper.master、cn.bridgeli.demo.mapper.slave，cn.bridgeli.demo.mapper.master下的这些dao接口是要写的，另一个是读的，这些接口对应的配置文件肯定就是他们对应的文件夹下面的xml文件了，在将来的项目中几乎可以照抄</p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">4. mybatis的配置文件mybatis.xml</p><pre xml"="" style="padding: 0.3em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #333333; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 12px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background-color: #f6f6f6;"><span style="color: #999999; font-weight: bold;">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span>   <span style="color: #999999; font-weight: bold;">&lt;!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"&gt;</span> <span style="color: #000080;">&lt;configuration&gt;</span>  <span style="color: #000080;">&lt;settings&gt;</span>   <span style="color: #000080;">&lt;setting <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"cacheEnabled"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"true"</span> /&gt;</span>   <span style="color: #000080;">&lt;setting <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"lazyLoadingEnabled"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"true"</span> /&gt;</span>  <span style="color: #000080;">&lt;/settings&gt;</span>  <span style="color: #000080;">&lt;plugins&gt;</span>   <span style="color: #000080;">&lt;plugin    interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor"&gt;</span>    <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"dialectClass"</span>     <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect"</span> /&gt;</span>    <span style="color: #000080;">&lt;property <span style="color: #008080;">name</span>=<span style="color: #dd1144;">"asyncTotalCount"</span> <span style="color: #008080;">value</span>=<span style="color: #dd1144;">"true"</span> /&gt;</span>   <span style="color: #000080;">&lt;/plugin&gt;</span>  <span style="color: #000080;">&lt;/plugins&gt;</span> <span style="color: #000080;">&lt;/configuration&gt;</span> </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">这个配置文件就一个分页，在前一篇文章中写过，就不多做解释了</p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">5. 最后因为用的数据源的问题，就把pom.xml文件需要引入的几个依赖，也摘出如下</p><pre xml"="" style="padding: 0.3em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #333333; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 12px; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background-color: #f6f6f6;"><span style="color: #000080;">&lt;dependency&gt;</span>   <span style="color: #000080;">&lt;groupId&gt;</span>com.jolbox<span style="color: #000080;">&lt;/groupId&gt;</span>   <span style="color: #000080;">&lt;artifactId&gt;</span>bonecp<span style="color: #000080;">&lt;/artifactId&gt;</span>   <span style="color: #000080;">&lt;version&gt;</span>0.8.0.RELEASE<span style="color: #000080;">&lt;/version&gt;</span> <span style="color: #000080;">&lt;/dependency&gt;</span>  <span style="color: #000080;">&lt;dependency&gt;</span>   <span style="color: #000080;">&lt;groupId&gt;</span>com.jolbox<span style="color: #000080;">&lt;/groupId&gt;</span>   <span style="color: #000080;">&lt;artifactId&gt;</span>bonecp-spring<span style="color: #000080;">&lt;/artifactId&gt;</span>   <span style="color: #000080;">&lt;version&gt;</span>0.8.0.RELEASE<span style="color: #000080;">&lt;/version&gt;</span> <span style="color: #000080;">&lt;/dependency&gt;</span>  <span style="color: #000080;">&lt;dependency&gt;</span>   <span style="color: #000080;">&lt;groupId&gt;</span>org.mariadb.jdbc<span style="color: #000080;">&lt;/groupId&gt;</span>   <span style="color: #000080;">&lt;artifactId&gt;</span>mariadb-java-client<span style="color: #000080;">&lt;/artifactId&gt;</span>   <span style="color: #000080;">&lt;version&gt;</span>1.1.7<span style="color: #000080;">&lt;/version&gt;</span> <span style="color: #000080;">&lt;/dependency&gt;</span> </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 27.2000007629395px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #fefefe;">需要说明的我们用常见的c3p0或者dbcp的数据源也是可以的，至于本例中为什么用了这个没有听说过的jolbox（老夫是没听说过），老夫也不知道，知道他和常见的c3p0和dbcp有什么区别的请留言交流，谢谢</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/429021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-01-12 19:43 <a href="http://www.blogjava.net/xiaomage234/archive/2016/01/12/429021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Mongodb集群搭建的三种方式</title><link>http://www.blogjava.net/xiaomage234/archive/2016/01/04/428919.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 04 Jan 2016 07:39:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/01/04/428919.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/428919.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/01/04/428919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/428919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/428919.html</trackback:ping><description><![CDATA[<p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">Mongodb是时下流行的NoSql数据库，它的存储方式是文档式存储，并不是Key-Value形式。关于Mongodb的特点，这里就不多介绍了，大家可以去看看官方说明：<a target="_blank" href="http://docs.mongodb.org/manual/" style="color: #ca0000; text-decoration: none;">http://docs.mongodb.org/manual/</a></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><a target="_blank" href="http://docs.mongodb.org/manual/" style="color: #ca0000; text-decoration: none;"><br /></a></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 今天主要来说说Mongodb的三种集群方式的搭建：Replica Set / Sharding / Master-Slaver。这里只说明最简单的集群搭建方式（生产环境），如果有多个节点可以此类推或者查看官方文档。OS是Ubuntu_x64系统，客户端用的是Java客户端。Mongodb版本是mongodb-linux-x86_64-2.2.2.tgz</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-size: 18px;"><strong>Replica Set</strong></span></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 中文翻译叫做副本集，不过我并不喜欢把英文翻译成中文，总是感觉怪怪的。其实简单来说就是集群当中包含了多份数据，保证主节点挂掉了，备节点能继续提供数据服务，提供的前提就是数据需要和主节点一致。如下图：</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><img src="http://img.my.csdn.net/uploads/201301/13/1358056331_2790.png" alt="" height="172" width="364" style="border: none; max-width: 100%;" /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Mongodb(M)表示主节点，Mongodb(S)表示备节点，Mongodb(A)表示仲裁节点。主备节点存储数据，仲裁节点不存储数据。客户端同时连接主节点与备节点，不连接仲裁节点。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认设置下，主节点提供所有增删查改服务，备节点不提供任何服务。但是可以通过设置使备节点提供查询服务，这样就可以减少主节点的压力，当客户端进行数据查询时，请求自动转到备节点上。这个设置叫做<a href="http://docs.mongodb.org/manual/applications/replication/#read-preference-modes" style="color: #ca0000; text-decoration: none;">Read Preference Modes</a>，同时Java客户端提供了简单的配置方式，可以不必直接对数据库进行操作。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 仲裁节点是一种特殊的节点，它本身并不存储数据，主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点，所以客户端不需要连接此节点。这里虽然只有一个备节点，但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点，但是自己也试过没仲裁节点的话，主节点挂了备节点还是备节点，所以咱们还是需要它的。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">介绍完了集群方案，那么现在就开始搭建了。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">1.建立数据文件夹</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">一般情况下不会把数据目录建立在mongodb的解压目录下，不过这里方便起见，就建在mongodb解压目录下吧。<br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 1262px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">mkdir&nbsp;-p&nbsp;/mongodb/data/master&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">mkdir&nbsp;-p&nbsp;/mongodb/data/slaver&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">mkdir&nbsp;-p&nbsp;/mongodb/data/arbiter&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">#三个目录分别对应主，备，仲裁节点&nbsp;&nbsp;</li></ol></div><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">2.建立配置文件</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">由于配置比较多，所以我们将配置写到文件里。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 1455px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">#master.conf&nbsp;&nbsp;</li><li style="line-height: 18px;">dbpath=/mongodb/data/master&nbsp;&nbsp;</li><li style="line-height: 18px;">logpath=/mongodb/log/master.log&nbsp;&nbsp;</li><li style="line-height: 18px;">pidfilepath=/mongodb/master.pid&nbsp;&nbsp;</li><li style="line-height: 18px;">directoryperdb=true&nbsp;&nbsp;</li><li style="line-height: 18px;">logappend=true&nbsp;&nbsp;</li><li style="line-height: 18px;">replSet=testrs&nbsp;&nbsp;</li><li style="line-height: 18px;">bind_ip=10.10.148.130&nbsp;&nbsp;</li><li style="line-height: 18px;">port=27017&nbsp;&nbsp;</li><li style="line-height: 18px;">oplogSize=10000&nbsp;&nbsp;</li><li style="line-height: 18px;">fork=true&nbsp;&nbsp;</li><li style="line-height: 18px;">noprealloc=true&nbsp;&nbsp;</li></ol></div><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 1722px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">#slaver.conf&nbsp;&nbsp;</li><li style="line-height: 18px;">dbpath=/mongodb/data/slaver&nbsp;&nbsp;</li><li style="line-height: 18px;">logpath=/mongodb/log/slaver.log&nbsp;&nbsp;</li><li style="line-height: 18px;">pidfilepath=/mongodb/slaver.pid&nbsp;&nbsp;</li><li style="line-height: 18px;">directoryperdb=true&nbsp;&nbsp;</li><li style="line-height: 18px;">logappend=true&nbsp;&nbsp;</li><li style="line-height: 18px;">replSet=testrs&nbsp;&nbsp;</li><li style="line-height: 18px;">bind_ip=10.10.148.131&nbsp;&nbsp;</li><li style="line-height: 18px;">port=27017&nbsp;&nbsp;</li><li style="line-height: 18px;">oplogSize=10000&nbsp;&nbsp;</li><li style="line-height: 18px;">fork=true&nbsp;&nbsp;</li><li style="line-height: 18px;">noprealloc=true&nbsp;&nbsp;</li></ol></div><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 1989px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">#arbiter.conf&nbsp;&nbsp;</li><li style="line-height: 18px;">dbpath=/mongodb/data/arbiter&nbsp;&nbsp;</li><li style="line-height: 18px;">logpath=/mongodb/log/arbiter.log&nbsp;&nbsp;</li><li style="line-height: 18px;">pidfilepath=/mongodb/arbiter.pid&nbsp;&nbsp;</li><li style="line-height: 18px;">directoryperdb=true&nbsp;&nbsp;</li><li style="line-height: 18px;">logappend=true&nbsp;&nbsp;</li><li style="line-height: 18px;">replSet=testrs&nbsp;&nbsp;</li><li style="line-height: 18px;">bind_ip=10.10.148.132&nbsp;&nbsp;</li><li style="line-height: 18px;">port=27017&nbsp;&nbsp;</li><li style="line-height: 18px;">oplogSize=10000&nbsp;&nbsp;</li><li style="line-height: 18px;">fork=true&nbsp;&nbsp;</li><li style="line-height: 18px;">noprealloc=true&nbsp;&nbsp;</li></ol></div><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">参数解释：</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">dbpath：数据存放目录</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">logpath：日志存放路径</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">pidfilepath：进程文件，方便停止mongodb</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">directoryperdb：为每一个数据库按照数据库名建立文件夹存放</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">logappend：以追加的方式记录日志</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">replSet：replica set的名字</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">bind_ip：mongodb所绑定的ip地址</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">port：mongodb进程所使用的端口号，默认为27017</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">oplogSize：mongodb操作日志文件的最大大小。单位为Mb，默认为硬盘剩余空间的5%</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">fork：以后台方式运行进程</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">noprealloc：不预先分配存储</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">3.启动mongodb</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">进入每个mongodb节点的bin目录下</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_java"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[java]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 557px; top: 2664px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./monood&nbsp;-f&nbsp;master.conf&nbsp;&nbsp;</li><li style="line-height: 18px;">./mongod&nbsp;-f&nbsp;slaver.conf&nbsp;&nbsp;</li><li style="line-height: 18px;">./mongod&nbsp;-f&nbsp;arbiter.conf&nbsp;&nbsp;</li></ol></div><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">注意配置文件的路径一定要保证正确，可以是相对路径也可以是绝对路径。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">4.配置主，备，仲裁节点</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">可以通过客户端连接mongodb，也可以直接在三个节点中选择一个连接mongodb。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 2891px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./mongo&nbsp;10.10.148.130:27017&nbsp;&nbsp;&nbsp;#ip和port是某个节点的地址&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;use&nbsp;admin&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;cfg={&nbsp;_id:"testrs",&nbsp;members:[&nbsp;{_id:0,host:'10.10.148.130:27017',priority:2},&nbsp;{_id:1,host:'10.10.148.131:27017',priority:1},&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">{_id:2,host:'10.10.148.132:27017',arbiterOnly:true}]&nbsp;};&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;rs.initiate(cfg)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#使配置生效&nbsp;&nbsp;</li></ol></div><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cfg是可以任意的名字，当然最好不要是mongodb的关键字，conf，config都可以。最外层的_id表示replica set的名字，members里包含的是所有节点的地址以及优先级。优先级最高的即成为主节点，即这里的10.10.148.130:27017。特别注意的是，对于仲裁节点，需要有个特别的配置&#8212;&#8212;arbiterOnly:true。这个千万不能少了，不然主备模式就不能生效。</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 配置的生效时间根据不同的机器配置会有长有短，配置不错的话基本上十几秒内就能生效，有的配置需要一两分钟。如果生效了，执行rs.status()命令会看到如下信息：</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 3180px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"set"&nbsp;:&nbsp;"testrs",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"date"&nbsp;:&nbsp;ISODate("2013-01-05T02:44:43Z"),&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"myState"&nbsp;:&nbsp;1,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"members"&nbsp;:&nbsp;[&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"_id"&nbsp;:&nbsp;0,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name"&nbsp;:&nbsp;"10.10.148.130:27017",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"health"&nbsp;:&nbsp;1,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"state"&nbsp;:&nbsp;1,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"stateStr"&nbsp;:&nbsp;"PRIMARY",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"uptime"&nbsp;:&nbsp;200,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"optime"&nbsp;:&nbsp;Timestamp(1357285565000,&nbsp;1),&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"optimeDate"&nbsp;:&nbsp;ISODate("2013-01-04T07:46:05Z"),&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"self"&nbsp;:&nbsp;true&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"_id"&nbsp;:&nbsp;1,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name"&nbsp;:&nbsp;"10.10.148.131:27017",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"health"&nbsp;:&nbsp;1,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"state"&nbsp;:&nbsp;2,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"stateStr"&nbsp;:&nbsp;"SECONDARY",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"uptime"&nbsp;:&nbsp;200,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"optime"&nbsp;:&nbsp;Timestamp(1357285565000,&nbsp;1),&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"optimeDate"&nbsp;:&nbsp;ISODate("2013-01-04T07:46:05Z"),&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"lastHeartbeat"&nbsp;:&nbsp;ISODate("2013-01-05T02:44:42Z"),&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"pingMs"&nbsp;:&nbsp;0&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"_id"&nbsp;:&nbsp;2,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name"&nbsp;:&nbsp;"10.10.148.132:27017",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"health"&nbsp;:&nbsp;1,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"state"&nbsp;:&nbsp;7,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"stateStr"&nbsp;:&nbsp;"ARBITER",&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"uptime"&nbsp;:&nbsp;200,&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"lastHeartbeat"&nbsp;:&nbsp;ISODate("2013-01-05T02:44:42Z"),&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"pingMs"&nbsp;:&nbsp;0&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;],&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ok"&nbsp;:&nbsp;1&nbsp;&nbsp;</li><li style="line-height: 18px;">}&nbsp;&nbsp;</li></ol></div><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">如果配置正在生效，其中会包含如下信息：</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 4013px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">"stateStr"&nbsp;:&nbsp;"RECOVERING"&nbsp;&nbsp;</li></ol></div><br style="font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">同时可以查看对应节点的日志，发现正在等待别的节点生效或者正在分配数据文件。</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在基本上已经完成了集群的所有搭建工作。至于测试工作，可以留给大家自己试试。一个是往主节点插入数据，能从备节点查到之前插入的数据（查询备节点可能会遇到某个问题，可以自己去网上查查看）。二是停掉主节点，备节点能变成主节点提供服务。三是恢复主节点，备节点也能恢复其备的角色，而不是继续充当主的角色。二和三都可以通过rs.status()命令实时查看集群的变化。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">Sharding</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">和Replica Set类似，都需要一个仲裁节点，但是Sharding还需要配置节点和路由节点。就三种集群搭建方式来说，这种是最复杂的。部署图如下：</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><img src="http://img.my.csdn.net/uploads/201301/13/1358091861_1772.png" alt="" height="369" width="401" style="border: none; max-width: 100%;" /><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">1.启动数据节点</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 4703px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./mongod&nbsp;--fork&nbsp;--dbpath&nbsp;../data/set1/&nbsp;--logpath&nbsp;../log/set1.log&nbsp;--replSet&nbsp;test&nbsp;#192.168.4.43&nbsp;&nbsp;</li><li style="line-height: 18px;">./mongod&nbsp;--fork&nbsp;--dbpath&nbsp;../data/set2/&nbsp;--logpath&nbsp;../log/set2.log&nbsp;--replSet&nbsp;test&nbsp;#192.168.4.44&nbsp;&nbsp;</li><li style="line-height: 18px;">./mongod&nbsp;--fork&nbsp;--dbpath&nbsp;../data/set3/&nbsp;--logpath&nbsp;../log/set3.log&nbsp;--replSet&nbsp;test&nbsp;#192.168.4.45&nbsp;决策&nbsp;不存储数据&nbsp;&nbsp;</li></ol></div><br style="font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">2.启动配置节点</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 4878px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./mongod&nbsp;--configsvr&nbsp;--dbpath&nbsp;../config/set1/&nbsp;--port&nbsp;20001&nbsp;--fork&nbsp;--logpath&nbsp;../log/conf1.log&nbsp;#192.168.4.30&nbsp;&nbsp;</li><li style="line-height: 18px;">./mongod&nbsp;--configsvr&nbsp;--dbpath&nbsp;../config/set2/&nbsp;--port&nbsp;20002&nbsp;--fork&nbsp;--logpath&nbsp;../log/conf2.log&nbsp;#192.168.4.31&nbsp;&nbsp;</li></ol></div><br style="font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">3.启动路由节点</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 5035px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./mongos&nbsp;--configdb&nbsp;192.168.4.30:20001,192.168.4.31:20002&nbsp;--port&nbsp;27017&nbsp;--fork&nbsp;--logpath&nbsp;../log/root.log&nbsp;#192.168.4.29&nbsp;&nbsp;</li></ol></div><br style="font-family: Arial; line-height: 26px; background-color: #ffffff;" /><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里我们没有用配置文件的方式启动，其中的参数意义大家应该都明白。一般来说一个数据节点对应一个配置节点，仲裁节点则不需要对应的配置节点。注意在启动路由节点时，要将配置节点地址写入到启动命令里。</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">4.配置Replica Set</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里可能会有点奇怪为什么Sharding会需要配置Replica Set。其实想想也能明白，多个节点的数据肯定是相关联的，如果不配一个Replica Set，怎么标识是同一个集群的呢。这也是人家mongodb的规定，咱们还是遵守吧。配置方式和之前所说的一样，定一个cfg，然后初始化配置。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 5304px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./mongo&nbsp;192.168.4.43:27017&nbsp;&nbsp;&nbsp;#ip和port是某个节点的地址&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;use&nbsp;admin&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;cfg={&nbsp;_id:"testrs",&nbsp;members:[&nbsp;{_id:0,host:'192.168.4.43:27017',priority:2},&nbsp;{_id:1,host:'192.168.4.44:27017',priority:1},&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;">{_id:2,host:'192.168.4.45:27017',arbiterOnly:true}]&nbsp;};&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;rs.initiate(cfg)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#使配置生效&nbsp;&nbsp;</li></ol></div><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">5.配置Sharding</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 5515px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./mongo&nbsp;192.168.4.29:27017&nbsp;&nbsp;&nbsp;#这里必须连接路由节点&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;sh.addShard("test/192.168.4.43:27017")&nbsp;#test表示replica&nbsp;set的名字&nbsp;当把主节点添加到shard以后，会自动找到set里的主，备，决策节点&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;db.runCommand({enableSharding:"diameter_test"})&nbsp;&nbsp;&nbsp;&nbsp;#diameter_test&nbsp;is&nbsp;database&nbsp;name&nbsp;&nbsp;</li><li style="line-height: 18px;">&gt;db.runCommand(&nbsp;{&nbsp;shardCollection:&nbsp;"diameter_test.dcca_dccr_test",key:{"__avpSessionId":1}})&nbsp;&nbsp;&nbsp;</li></ol></div><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一个命令很容易理解，第二个命令是对需要进行Sharding的数据库进行配置，第三个命令是对需要进行Sharding的Collection进行配置，这里的dcca_dccr_test即为Collection的名字。另外还有个key，这个是比较关键的东西，对于查询效率会有很大的影响，具体可以查看</span><a href="http://docs.mongodb.org/manual/core/sharding/#sharding-shard-key" style="color: #ca0000; text-decoration: none; font-family: Arial; line-height: 26px; background-color: #ffffff;">Shard Key Overview</a><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 到这里Sharding也已经搭建完成了，以上只是最简单的搭建方式，其中某些配置仍然使用的是默认配置。如果设置不当，会导致效率异常低下，所以建议大家多看看官方文档再进行默认配置的修改。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">Master-Slaver</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">这个是最简答的集群搭建，不过准确说也不能算是集群，只能说是主备。并且官方已经不推荐这种方式，所以在这里只是简单的介绍下吧，搭建方式也相对简单。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 936.53125px; line-height: 26px;"><div><div><strong>[plain]</strong>&nbsp;<a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/luonanqin/article/details/8497860#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 561px; top: 5864px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">./mongod&nbsp;--master&nbsp;--dbpath&nbsp;/data/masterdb/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#主节点&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;</li><li style="line-height: 18px;">./mongod&nbsp;--slave&nbsp;--source&nbsp;&lt;masterip:masterport&gt;&nbsp;--dbpath&nbsp;/data/slavedb/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;备节点&nbsp;&nbsp;</li></ol></div><span style="font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基本上只要在主节点和备节点上分别执行这两条命令，Master-Slaver就算搭建完成了。我没有试过主节点挂掉后备节点是否能变成主节点，不过既然已经不推荐了，大家就没必要去使用了。</span><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以上三种集群搭建方式首选Replica Set，只有真的是大数据，Sharding才能显现威力，毕竟备节点同步数据是需要时间的。Sharding可以将多片数据集中到路由节点上进行一些对比，然后将数据返回给客户端，但是效率还是比较低的说。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我自己有测试过，不过具体的机器配置已经不记得了。Replica Set的ips在数据达到1400w条时基本能达到1000左右，而Sharding在300w时已经下降到500ips了，两者的单位数据大小大概是10kb。大家在应用的时候还是多多做下性能测试，毕竟不像Redis有benchmark。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Mongodb现在用的还是比较多的，但是个人觉得配置太多了。。。。我看官网都看了好多天，才把集群搭建的配置和注意要点弄明白。而且用过的人应该知道mongodb吃内存的问题，解决办法只能通过ulimit来控制内存使用量，但是如果控制不好的话，mongodb会挂掉。。。</p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; background-color: #ffffff;">过段时间我会写一篇关于项目里使用mongodb所涉及到的具体业务，各位有兴趣可以关注下。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/428919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-01-04 15:39 <a href="http://www.blogjava.net/xiaomage234/archive/2016/01/04/428919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MongoDB：执行计划 </title><link>http://www.blogjava.net/xiaomage234/archive/2015/12/21/428755.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 21 Dec 2015 02:48:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/12/21/428755.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/428755.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/12/21/428755.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/428755.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/428755.html</trackback:ping><description><![CDATA[<span style="color: #494949; font-family: simsun; background-color: #f4e6db;">来源：http://francs3.blog.163.com/blog/static/40576727201210202322706/</span><br style="color: #494949; font-family: simsun; background-color: #f4e6db;" /><br style="color: #494949; font-family: simsun; background-color: #f4e6db;" /><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">关于索引的创建在之前的&nbsp;</span><a target="_blank" href="http://francs3.blog.163.com/blog/static/405767272012101995338970/" style="text-decoration: none; color: #905e40; font-family: simsun; background-color: #f4e6db;">创建索引</a>&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">blog 中已有描述，</span><br style="color: #494949; font-family: simsun; background-color: #f4e6db;" /><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">接下</span><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">来看看 MongoDB 的执行计划，通过使用&nbsp;</span><a target="_blank" href="http://docs.mongodb.org/manual/reference/javascript/#cursor.explain" style="text-decoration: none; color: #905e40; font-family: simsun; background-color: #f4e6db;">explain()</a><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;&nbsp;</span><wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">方法可以很容易的查看执行计划。</span><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><br /><strong>--1 查看索引</strong></p><table border="1" cellpadding="1" cellspacing="1" width="80%" style="margin: 0px; padding: 0px; color: #494949; font-family: simsun; font-size: 14px; background-color: #f4e6db;"><tbody><tr><td style="margin: 0px; padding: 0px; font-size: 12px; font-family: Verdana, 宋体, sans-serif; line-height: 18px;">&nbsp;<wbr>&gt; db.test_4.getIndexes();<br />[<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"v" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"key" : {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"_id" : 1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"ns" : "skytf.test_4",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"name" : "_id_"<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"v" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"key" : {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"skyid" : 1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"ns" : "skytf.test_4",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"name" : "idx_test_4_skyid",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"background" : true<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;}<br />]</td></tr></tbody></table>&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><br /><strong>--2 查看执行计划</strong></p><table border="1" cellpadding="1" cellspacing="1" width="80%" style="margin: 0px; padding: 0px; color: #494949; font-family: simsun; font-size: 14px; background-color: #f4e6db;"><tbody><tr><td style="margin: 0px; padding: 0px; font-size: 12px; font-family: Verdana, 宋体, sans-serif; line-height: 18px;">&nbsp;<wbr>&gt;&nbsp;<strong>db.test_4.find({skyid:1}).explain();<br /></strong>{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"cursor" : "BtreeCursor idx_test_4_skyid",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"isMultiKey" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"n" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedObjects" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscanned" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedObjectsAllPlans" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedAllPlans" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"scanAndOrder" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"indexOnly" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nYields" : 0,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nChunkSkips" : 0,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"millis" : 9,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"indexBounds" : {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"skyid" : [<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;[<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;]<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;]<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"server" : "redhatB.example.com:27017"<br />}</td></tr></tbody></table>&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr>&nbsp;备注： 上面为 mongodb 的执行计划，部分参数意思为以下：<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;cursor：&nbsp;<wbr>&nbsp;<wbr>&nbsp;值为 BasicCursor&nbsp;<wbr>&nbsp;或 BtreeCursor，后者表示此查询使用了索引<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;nscanned： 扫描的索引项<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;n:&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;返回的文档数，即返回的行<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;millis：&nbsp;<wbr>&nbsp;<wbr>&nbsp;完成此查询所需的时间，单位为毫秒<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;indexBounds: 如果不为空，表示此查询使用的索引项<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;MongoDB 也能强制使用索引，通过使用&nbsp;<a target="_blank" href="http://docs.mongodb.org/manual/reference/javascript/#cursor.hint" style="text-decoration: none; color: #905e40;">hint()</a>&nbsp;，感觉非常强大！</p><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><br /><strong>--3 删除老索引</strong></p><table border="1" cellpadding="1" cellspacing="1" width="80%" style="margin: 0px; padding: 0px; color: #494949; font-family: simsun; font-size: 14px; background-color: #f4e6db;"><tbody><tr><td style="margin: 0px; padding: 0px; font-size: 12px; font-family: Verdana, 宋体, sans-serif; line-height: 18px;">&nbsp;<wbr>&gt; db.test_4.dropIndexes('idx_test_4_skyid');<br />{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nIndexesWas" : 2,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"msg" : "non-_id indexes dropped for collection",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"ok" : 1<br />}</td></tr></tbody></table>&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><br /><strong>--4 新建索引</strong></p><table border="1" cellpadding="1" cellspacing="1" width="705" style="margin: 0px; padding: 0px; color: #494949; font-family: simsun; font-size: 14px; width: 705px; height: 58px; background-color: #f4e6db;"><tbody><tr><td style="margin: 0px; padding: 0px; font-size: 12px; font-family: Verdana, 宋体, sans-serif; line-height: 18px;">&nbsp;<wbr>&gt;&nbsp;<strong>db.test_4.ensureIndex({skyid:1,name:1},{name:"idx_test_4_skyid_name",background:true});&nbsp;<wbr></strong></td></tr></tbody></table>&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><br /><strong>--5 查看索引</strong></p><table border="1" cellpadding="1" cellspacing="1" width="80%" style="margin: 0px; padding: 0px; color: #494949; font-family: simsun; font-size: 14px; background-color: #f4e6db;"><tbody><tr><td style="margin: 0px; padding: 0px; font-size: 12px; font-family: Verdana, 宋体, sans-serif; line-height: 18px;">&nbsp;<wbr>&gt;&nbsp;<strong>db.test_4.getIndexes();</strong><br />[<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"v" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"key" : {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"_id" : 1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"ns" : "skytf.test_4",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"name" : "_id_"<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"v" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"key" : {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"skyid" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"name" : 1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"ns" : "skytf.test_4",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"name" : "idx_test_4_skyid_name",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"background" : true<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;}<br />]</td></tr></tbody></table>&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><br style="color: #494949; font-family: simsun; background-color: #f4e6db;" />&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;备注：索引 "idx_test_4_skyid_name" 已创建。</span><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><br /><strong>--6 没使用索引的查询</strong></p><table border="1" cellpadding="1" cellspacing="1" width="80%" style="margin: 0px; padding: 0px; color: #494949; font-family: simsun; font-size: 14px; background-color: #f4e6db;"><tbody><tr><td style="margin: 0px; padding: 0px; font-size: 12px; font-family: Verdana, 宋体, sans-serif; line-height: 18px;">&nbsp;<wbr>&gt; db.test_4.find({name:'a'}).explain();<br />{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<strong>"cursor" : "BasicCursor",<br /></strong>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"isMultiKey" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"n" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedObjects" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscanned" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedObjectsAllPlans" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedAllPlans" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"scanAndOrder" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"indexOnly" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nYields" : 1,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nChunkSkips" : 0,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"millis" : 156,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"<strong>indexBounds</strong>" : {<p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal;">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"server" : "redhatB.example.com:27017"<br />}</p></td></tr></tbody></table>&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><br style="color: #494949; font-family: simsun; background-color: #f4e6db;" />&nbsp;<wbr style="color: #494949; font-family: simsun; background-color: #f4e6db;"><span style="color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;备注： indexBounds 为空表示没使用索引。</span><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><br /><strong>--7 强制查询使用索引</strong></p><table border="1" cellpadding="1" cellspacing="1" width="80%" style="margin: 0px; padding: 0px; color: #494949; font-family: simsun; font-size: 14px; background-color: #f4e6db;"><tbody><tr><td style="margin: 0px; padding: 0px; font-size: 12px; font-family: Verdana, 宋体, sans-serif; line-height: 18px;">&nbsp;<wbr>&gt;&nbsp;<strong>db.test_4.find({name:'a'}).hint({skyid:1,name:1}).explain();</strong><br />{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"cursor" : "<strong>BtreeCursor idx_test_4_skyid_name",</strong><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"isMultiKey" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"n" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedObjects" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscanned" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedObjectsAllPlans" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nscannedAllPlans" : 100001,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"scanAndOrder" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"indexOnly" : false,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nYields" : 0,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"nChunkSkips" : 0,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"millis" : 263,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"<strong>indexBounds</strong>" : {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"skyid" : [<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;[<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"$minElement" : 1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;{<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"$maxElement" : 1<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;}<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;]<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;],<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"name" : [<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;[<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"a",<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"a"<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;]<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;]<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;},<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;"server" : "redhatB.example.com:27017"<br />}</td></tr></tbody></table><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;">&nbsp;<wbr>&nbsp;<wbr>&nbsp;备注：indexBounds 不为空表示已使用索引，并且 cursor 字段显示了使用的索引名称。<br />&nbsp;<wbr>&nbsp;<wbr></p><p style="margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; color: #494949; font-family: simsun; background-color: #f4e6db;"><strong>--8 参考</strong><br /><a href="http://docs.mongodb.org/manual/reference/javascript/#cursor.explain" style="text-decoration: none; color: #905e40;">http://docs.mongodb.org/manual/reference/javascript/#cursor.explain</a><br /><a href="http://docs.mongodb.org/manual/reference/javascript/#cursor.hint" style="text-decoration: none; color: #905e40;">http://docs.mongodb.org/manual/reference/javascript/#cursor.hint</a>&nbsp;<wbr>&nbsp;<wbr><wbr></p><div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/428755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-12-21 10:48 <a href="http://www.blogjava.net/xiaomage234/archive/2015/12/21/428755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mycat分布式mysql中间件（数据库切分概述）[转]</title><link>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 16 Mar 2015 10:27:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/423493.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/423493.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/423493.html</trackback:ping><description><![CDATA[from:http://songwie.com/articlelist/21<br /><br /><div style="margin: 0px; border: 0px; vertical-align: baseline; line-height: 1.714285714; color: #444444; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; background-color: #ffffff;"><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">mysql数据库切分</span></strong></h2><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">前言</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过MySQLReplication功能所实现的扩展总是会受到数据库大小的限制，一旦数据库过于庞大，尤其是当写入过于频繁，很难由一台主机支撑的时候，我们还是会面临到扩展瓶颈。这时候，我们就必须许找其他技术手段来解决这个瓶颈，那就是我们这一章所要介绍恶的数据切分技术。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">何谓数据切分</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">可能很多读者朋友在网上或者杂志上面都已经多次见到关于数据切分的相关文章了，只不过在有些文章中称之为数据的Sharding。其实不管是称之为数据的Sharding还是数据的切分，其概念都是一样的。简单来说，就是指通过某种特定的条件，将我们存放在同一个数据库中的数据分散存放到多个数据库（主机）上面，以达到分散单台设备负载的效果。数据的切分同时还可以提高系统的总体可用性，因为单台设备Crash之后，只有总体数据的某部分不可用，而不是所有的数据。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">数据的切分（Sharding）根据其切分规则的类型，可以分为两种切分模式。一种是按照不同的表（或者Schema）来切分到不同的数据库（主机）之上，这种切可以称之为数据的垂直（纵向）切分；另外一种则是根据表中的数据的逻辑关系，将同一个表中的数据按照某种条件拆分到多台数据库（主机）上面，这种切分称之为数据的水平（横向）切分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">垂直切分的最大特点就是规则简单，实施也更为方便，尤其适合各业务之间的耦合度非常低，相互影响很小，业务逻辑非常清晰的系统。在这种系统中，可以很容易做到将不同业务模块所使用的表分拆到不同的数据库中。根据不同的表来进行拆分，对应用程序的影响也更小，拆分规则也会比较简单清晰。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">水平切分于垂直切分相比，相对来说稍微复杂一些。因为要将同一个表中的不同数据拆分到不同的数据库中，对于应用程序来说，拆分规则本身就较根据表名来拆分更为复杂，后期的数据维护也会更为复杂一些。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当我们某个（或者某些）表的数据量和访问量特别的大，通过垂直切分将其放在独立的设备上后仍然无法满足性能要求，这时候我们就必须将垂直切分和水平切分相结合，先垂直切分，然后再水平切分，才能解决这种超大型表的性能问题。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">下面我们就针对垂直、水平以及组合切分这三种数据切分方式的架构实现及切分后数据的整合进行相应的分析。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据的垂直切分</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">我们先来看一下，数据的垂直切分到底是如何一个切分法的。数据的垂直切分，也可以称之为纵向切分。将数据库想象成为由很多个一大块一大块的&#8220;数据块&#8221;（表）组成，我们垂直的将这些&#8220;数据块&#8221;切开，然后将他们分散到多台数据库主机上面。这样的切分方法就是一个垂直（纵向）的数据切分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一个架构设计较好的应用系统，其总体功能肯定是由很多个功能模块所组成的，而每一个功能模块所需要的数据对应到数据库中就是一个或者多个表。而在架构设计中，各个功能模块相互之间的交互点越统一越少，系统的耦合度就越低，系统各个模块的维护性以及扩展性也就越好。这样的系统，实现数据的垂直切分也就越容易。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当我们的功能模块越清晰，耦合度越低，数据垂直切分的规则定义也就越容易。完全可以根据功能模块来进行数据的切分，不同功能模块的数据存放于不同的数据库主机中，可以很容易就避免掉跨数据库的Join存在，同时系统架构也非常的清晰。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然，很难有系统能够做到所有功能模块所使用的表完全独立，完全不需要访问对方的表或者需要两个模块的表进行Join操作。这种情况下，我们就必须根据实际的应用场景进行评估权衡。决定是迁就应用程序将需要Join的表的相关某快都存放在同一个数据库中，还是让应用程序做更多的事情，也就是程序完全通过模块接口取得不同数据库中的数据，然后在程序中完成Join操作。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一般来说，如果是一个负载相对不是很大的系统，而且表关联又非常的频繁，那可能数据库让步，将几个相关模块合并在一起减少应用程序的工作的方案可以减少较多的工作量，是一个可行的方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然，通过数据库的让步，让多个模块集中共用数据源，实际上也是简介的默许了各模块架构耦合度增大的发展，可能会让以后的架构越来越恶化。尤其是当发展到一定阶段之后，发现数据库实在无法承担这些表所带来的压力，不得不面临再次切分的时候，所带来的架构改造成本可能会远远大于最初的时候。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，在数据库进行垂直切分的时候，如何切分，切分到什么样的程度，是一个比较考验人的难题。只能在实际的应用场景中通过平衡各方面的成本和收益，才能分析出一个真正适合自己的拆分方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">比如在本书所使用示例系统的example数据库，我们简单的分析一下，然后再设计一个简单的切分规则，进行一次垂直垂直拆分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">系统功能可以基本分为四个功能模块：用户，群组消息，相册以及事件，分别对应为如下这些表：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 用户模块表：user,user_profile,user_group,user_photo_album</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2. 群组讨论表：groups,group_message,group_message_content,top_message</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">3. 相册相关表：photo,photo_album,photo_album_relation,photo_comment</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">4. 事件信息表：event</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">初略一看，没有哪一个模块可以脱离其他模块独立存在，模块与模块之间都存在着关系，莫非无法切分？</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然不是，我们再稍微深入分析一下，可以发现，虽然各个模块所使用的表之间都有关联，但是关联关系还算比较清晰，也比较简单。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;群组讨论模块和用户模块之间主要存在通过用户或者是群组关系来进行关联。一般关联的时候都会是通过用户的id或者nick_name以及group的id来进行关联，通过模块之间的接口实现不会带来太多麻烦；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;相册模块仅仅与用户模块存在通过用户的关联。这两个模块之间的关联基本就有通过用户id关联的内容，简单清晰，接口明确；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 事件模块与各个模块可能都有关联，但是都只关注其各个模块中对象的ID信息，同样可以做到很容易分拆。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，我们第一步可以将数据库按照功能模块相关的表进行一次垂直拆分，每个模块所涉及的表单独到一个数据库中，模块与模块之间的表关联都在应用系统端通过藉口来处理。如下图所示：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194849_11.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194120_831.jpg" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过这样的垂直切分之后，之前只能通过一个数据库来提供的服务，就被分拆成四个数据库来提供服务，服务能力自然是增加几倍了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">垂直切分的优点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 数据库的拆分简单明了，拆分规则明确；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用程序模块清晰明确，整合容易；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 数据维护方便易行，容易定位；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">垂直切分的缺点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 部分表关联无法在数据库级别完成，需要在程序中完成；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 对于访问极其频繁且数据量超大的表仍然存在性能平静，不一定能满足要求；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 事务处理相对更为复杂；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 切分达到一定程度之后，扩展性会遇到限制；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 过读切分可能会带来系统过渡复杂而难以维护。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">针对于垂直切分可能遇到数据切分及事务问题，在数据库层面实在是很难找到一个较好的处理方案。实际应用案例中，数据库的垂直切分大多是与应用系统的模块相对应，同一个模块的数据源存放于同一个数据库中，可以解决模块内部的数据关联问题。而模块与模块之间，则通过应用程序以服务接口方式来相互提供所需要的数据。虽然这样做在数据库的总体操作次数方面确实会有所增加，但是在系统整体扩展性以及架构模块化方面，都是有益的。可能在某些操作的单次响应时间会稍有增加，但是系统的整体性能很可能反而会有一定的提升。而扩展瓶颈问题，就只能依靠下一节将要介绍的数据水平切分架构来解决了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据的水平切分</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">上面一节分析介绍了数据的垂直切分，这一节再分析一下数据的水平切分。数据的垂直切分基本上可以简单的理解为按照表按照模块来切分数据，而水平切分就不再是按照表或者是功能模块来切分了。一般来说，简单的水平切分主要是将某个访问极其平凡的表再按照某个字段的某种规则来分散到多个表之中，每个表中包含一部分数据。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">简单来说，我们可以将数据的水平切分理解为是按照数据行的切分，就是将表中的某些行切分到一个数据库，而另外的某些行又切分到其他的数据库中。当然，为了能够比较容易的判定各行数据被切分到哪个数据库中了，切分总是都需要按照某种特定的规则来进行的。如根据某个数字类型字段基于特定数目取模，某个时间类型字段的范围，或者是某个字符类型字段的hash值。如果整个系统中大部分核心表都可以通过某个字段来进行关联，那这个字段自然是一个进行水平分区的上上之选了，当然，非常特殊无法使用就只能另选其他了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一般来说，像现在互联网非常火爆的Web2.0类型的网站，基本上大部分数据都能够通过会员用户信息关联上，可能很多核心表都非常适合通过会员ID来进行数据的水平切分。而像论坛社区讨论系统，就更容易切分了，非常容易按照论坛编号来进行数据的水平切分。切分之后基本上不会出现各个库之间的交互。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">如我们的示例系统，所有数据都是和用户关联的，那么我们就可以根据用户来进行水平拆分，将不同用户的数据切分到不同的数据库中。当然，唯一有点区别的是用户模块中的groups表和用户没有直接关系，所以groups不能根据用户来进行水平拆分。对于这种特殊情况下的表，我们完全可以独立出来，单独放在一个独立的数据库中。其实这个做法可以说是利用了前面一节所介绍的&#8220;数据的垂直切分&#8221;方法，我将在下一节中更为详细的介绍这种垂直切分与水平切分同时使用的联合切分方法。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，对于我们的示例数据库来说，大部分的表都可以根据用户ID来进行水平的切分。不同用户相关的数据进行切分之后存放在不同的数据库中。如将所有用户ID通过2取模然后分别存放于两个不同的数据库中。每个和用户ID关联上的表都可以这样切分。这样，基本上每个用户相关的数据，都在同一个数据库中，即使是需要关联，也可以非常简单的关联上。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">我们可以通过下图来更为直观的展示水平切分相关信息：水平切分的优点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194915_274.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 表关联基本能够在数据库端全部完成；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 不会存在某些超大型数据量和高负载的表遇到瓶颈的问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用程序端整体架构改动相对较少；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 事务处理相对简单；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 只要切分规则能够定义好，基本上较难遇到扩展性限制；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">水平切分的缺点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 切分规则相对更为复杂，很难抽象出一个能够满足整个数据库的切分规则；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 后期数据的维护难度有所增加，人为手工定位数据更困难；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用系统各模块耦合度较高，可能会对后面数据的迁移拆分造成一定的困难。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">垂直与水平切分的联合使用</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">上面两节内容中，我们分别，了解了&#8220;垂直&#8221;和&#8220;水平&#8221;这两种切分方式的实现以及切分之后的架构信息，同时也分析了两种架构各自的优缺点。但是在实际的应用场景中，除了那些负载并不是太大，业务逻辑也相对较简单的系统可以通过上面两种切分方法之一来解决扩展性问题之外，恐怕其他大部分业务逻辑稍微复杂一点，系统负载大一些的系统，都无法通过上面任何一种数据的切分方法来实现较好的扩展性，而需要将上述两种切分方法结合使用，不同的场景使用不同的切分方法。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在这一节中，我将结合垂直切分和水平切分各自的优缺点，进一步完善我们的整体架构，让系统的扩展性进一步提高。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一般来说，我们数据库中的所有表很难通过某一个（或少数几个）字段全部关联起来，所以很难简单的仅仅通过数据的水平切分来解决所有问题。而垂直切分也只能解决部分问题，对于那些负载非常高的系统，即使仅仅只是单个表都无法通过单台数据库主机来承担其负载。我们必须结合&#8220;垂直&#8221;和&#8220;水平&#8221;两种切分方式同时使用，充分利用两者的优点，避开其缺点。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">每一个应用系统的负载都是一步一步增长上来的，在开始遇到性能瓶颈的时候，大多数架构师和DBA都会选择先进行数据的垂直拆分，因为这样的成本最先，最符合这个时期所追求的最大投入产出比。然而，随着业务的不断扩张，系统负载的持续增长，在系统稳定一段时期之后，经过了垂直拆分之后的数据库集群可能又再一次不堪重负，遇到了性能瓶颈。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">这时候我们该如何抉择？是再次进一步细分模块呢，还是寻求其他的办法来解决？如果我们再一次像最开始那样继续细分模块，进行数据的垂直切分，那我们可能在不久的将来，又会遇到现在所面对的同样的问题。而且随着模块的不断的细化，应用系统的架构也会越来越复杂，整个系统很可能会出现失控的局面。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">这时候我们就必须要通过数据的水平切分的优势，来解决这里所遇到的问题。而且，我们完全不必要在使用数据水平切分的时候，推倒之前进行数据垂直切分的成果，而是在其基础上利用水平切分的优势来避开垂直切分的弊端，解决系统复杂性不断扩大的问题。而水平拆分的弊端（规则难以统一）也已经被之前的垂直切分解决掉了，让水平拆分可以进行的得心应手。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">对于我们的示例数据库，假设在最开始，我们进行了数据的垂直切分，然而随着业务的不断增长，数据库系统遇到了瓶颈，我们选择重构数据库集群的架构。如何重构？考虑到之前已经做好了数据的垂直切分，而且模块结构清晰明确。而业务增长的势头越来越猛，即使现在进一步再次拆分模块，也坚持不了太久。我们选择了在垂直切分的基础上再进行水平拆分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在经历过垂直拆分后的各个数据库集群中的每一个都只有一个功能模块，而每个功能模块中的所有表基本上都会与某个字段进行关联。如用户模块全部都可以通过用户ID进行切分，群组讨论模块则都通过群组ID来切分，相册模块则根据相册ID来进切分，最后的事件通知信息表考虑到数据的时限性（仅仅只会访问最近某个事件段的信息），则考虑按时间来切分。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">下图展示了切分后的整个架构：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194941_67.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">实际上，在很多大型的应用系统中，垂直切分和水平切这两种数据的切分方法基本上都是并存的，而且经常在不断的交替进行，以不断的增加系统的扩展能力。我们在应对不同的应用场景的时候，也需要充分考虑到这两种切分方法各自的局限，以及各自的优势，在不同的时期（负载压力）使用不同的结合方式。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">联合切分的优点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 可以充分利用垂直切分和水平切分各自的优势而避免各自的缺陷；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 让系统扩展性得到最大化提升；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">联合切分的缺点</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 数据库系统架构比较复杂，维护难度更大；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 应用程序架构也相对更复杂；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据切分及整合方案</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过前面的章节，我们已经很清楚了通过数据库的数据切分可以极大的提高系统的扩展性。但是，数据库中的数据在经过垂直和（或）水平切分被存放在不同的数据库主机之后，应用系统面临的最大问题就是如何来让这些数据源得到较好的整合，可能这也是很多读者朋友非常关心的一个问题。这一节我们主要针对的内容就是分析可以使用的各种可以帮助我们实现数据切分以及数据整合的整体解决方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">数据的整合很难依靠数据库本身来达到这个效果，虽然MySQL存在Federated存储引擎，可以解决部分类似的问题，但是在实际应用场景中却很难较好的运用。那我们该如何来整合这些分散在各个MySQL主机上面的数据源呢？</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">总的来说，存在两种解决思路：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 在每个应用程序模块中配置管理自己需要的一个（或者多个）数据源，直接访问各个数据库，在模块内完成数据的整合；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2. 通过中间代理层来统一管理所有的数据源，后端数据库集群对前端应用程序透明；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">可能90%以上的人在面对上面这两种解决思路的时候都会倾向于选择第二种，尤其是系统不断变得庞大复杂的时候。确实，这是一个非常正确的选择，虽然短期内需要付出的成本可能会相对更大一些，但是对整个系统的扩展性来说，是非常有帮助的。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">所以，对于第一种解决思路我这里就不准备过多的分析，下面我重点分析一下在第二种解决思路中的一些解决方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733; 自行开发中间代理层</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在决定选择通过数据库的中间代理层来解决数据源整合的架构方向之后，有不少公司（或者企业）选择了通过自行开发符合自身应用特定场景的代理层应用程序。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过自行开发中间代理层可以最大程度的应对自身应用的特定，最大化的定制很多个性化需求，在面对变化的时候也可以灵活的应对。这应该说是自行开发代理层最大的优势了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当然，选择自行开发，享受让个性化定制最大化的乐趣的同时，自然也需要投入更多的成本来进行前期研发以及后期的持续升级改进工作，而且本身的技术门槛可能也比简单的Web应用要更高一些。所以，在决定选择自行开发之前，还是需要进行比较全面的评估为好。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">由于自行开发更多时候考虑的是如何更好的适应自身应用系统，应对自身的业务场景，所以这里也不好分析太多。后面我们主要分析一下当前比较流行的几种数据源整合解决方案。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733;利用MySQLProxy实现数据切分及整合</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">MySQLProxy是MySQL官方提供的一个数据库代理层产品，和MySQLServer一样，同样是一个基于GPL开源协议的开源产品。可用来监视、分析或者传输他们之间的通讯信息。他的灵活性允许你最大限度的使用它，目前具备的功能主要有连接路由，Query分析，Query过滤和修改，负载均衡，以及基本的HA机制等。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">实际上，MySQLProxy本身并不具有上述所有的这些功能，而是提供了实现上述功能的基础。要实现这些功能，还需要通过我们自行编写LUA脚本来实现。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">MySQLProxy实际上是在客户端请求与MySQLServer之间建立了一个连接池。所有客户端请求都是发向MySQLProxy，然后经由MySQLProxy进行相应的分析，判断出是读操作还是写操作，分发至对应的MySQLServer上。对于多节点Slave集群，也可以起做到负载均衡的效果。以下是MySQLProxy的基本架构图：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228194958_853.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过上面的架构简图，我们可以很清晰的看出MySQLProxy在实际应用中所处的位置，以及能做的基本事情。关于MySQLProxy更为详细的实施细则在MySQL官方文档中有非常详细的介绍和示例，感兴趣的读者朋友可以直接从MySQL官方网站免费下载或者在线阅读，我这里就不累述浪费纸张了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733;利用Amoeba实现数据切分及整合</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">Amoeba是一个基于Java开发的，专注于解决分布式数据库数据源整合Proxy程序的开源框架，基于GPL3开源协议。目前，Amoeba已经具有Query路由，Query过滤，读写分离，负载均衡以及HA机制等相关内容。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">Amoeba 主要解决的以下几个问题：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 数据切分后复杂数据源整合；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2. 提供数据切分规则并降低数据切分规则给数据库带来的影响；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">3. 降低数据库与客户端的连接数；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">4. 读写分离路由；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">我们可以看出，Amoeba所做的事情，正好就是我们通过数据切分来提升数据库的扩展性所需要的。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">Amoeba并不是一个代理层的Proxy程序，而是一个开发数据库代理层Proxy程序的开发框架，目前基于Amoeba所开发的Proxy程序有AmoebaForMySQL和AmoebaForAladin两个。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">AmoebaForMySQL主要是专门针对MySQL数据库的解决方案，前端应用程序请求的协议以及后端连接的数据源数据库都必须是MySQL。对于客户端的任何应用程序来说，AmoebaForMySQL和一个MySQL数据库没有什么区别，任何使用MySQL协议的客户端请求，都可以被AmoebaForMySQL解析并进行相应的处理。下如可以告诉我们AmoebaForMySQL的架构信息（出自Amoeba开发者博客）：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228195022_18.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">AmoebaForAladin则是一个适用更为广泛，功能更为强大的Proxy程序。他可以同时连接不同数据库的数据源为前端应用程序提供服务，但是仅仅接受符合MySQL协议的客户端应用程序请求。也就是说，只要前端应用程序通过MySQL协议连接上来之后，AmoebaForAladin会自动分析Query语句，根据Query语句中所请求的数据来自动识别出该所Query的数据源是在什么类型数据库的哪一个物理主机上面。下图展示了AmoebaForAladin的架构细节（出自Amoeba开发者博客）：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228195037_993.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">咋一看，两者好像完全一样嘛。细看之后，才会发现两者主要的区别仅在于通过MySQLProtocalAdapter处理之后，根据分析结果判断出数据源数据库，然后选择特定的JDBC驱动和相应协议连接后端数据库。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">其实通过上面两个架构图大家可能也已经发现了Amoeba的特点了，他仅仅只是一个开发框架，我们除了选择他已经提供的ForMySQL和ForAladin这两款产品之外，还可以基于自身的需求进行相应的二次开发，得到更适应我们自己应用特点的Proxy程序。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">当对于使用MySQL数据库来说，不论是AmoebaForMySQL还是AmoebaForAladin都可以很好的使用。当然，考虑到任何一个系统越是复杂，其性能肯定就会有一定的损失，维护成本自然也会相对更高一些。所以，对于仅仅需要使用MySQL数据库的时候，我还是建议使用AmoebaForMySQL。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">AmoebaForMySQL的使用非常简单，所有的配置文件都是标准的XML文件，总共有四个配置文件。分别为：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;amoeba.xml：主配置文件，配置所有数据源以及Amoeba自身的参数设置；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;rule.xml：配置所有Query路由规则的信息；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;functionMap.xml：配置用于解析Query中的函数所对应的Java实现类；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; rullFunctionMap.xml：配置路由规则中需要使用到的特定函数的实现类；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">如果您的规则不是太复杂，基本上仅需要使用到上面四个配置文件中的前面两个就可完成所有工作。Proxy程序常用的功能如读写分离，负载均衡等配置都在amoeba.xml中进行。此外，Amoeba已经支持了实现数据的垂直切分和水平切分的自动路由，路由规则可以在rule.xml进行设置。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">目前Amoeba少有欠缺的主要就是其在线管理功能以及对事务的支持了，曾经在与相关开发者的沟通过程中提出过相关的建议，希望能够提供一个可以进行在线维护管理的命令行管理工具，方便在线维护使用，得到的反馈是管理专门的管理模块已经纳入开发日程了。另外在事务支持方面暂时还是Amoeba无法做到的，即使客户端应用在提交给Amoeba的请求是包含事务信息的，Amoeba也会忽略事务相关信息。当然，在经过不断完善之后，我相信事务支持肯定是Amoeba重点考虑增加的feature。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">关于Amoeba更为详细的使用方法读者朋友可以通过Amoeba开发者博客（http://amoeba.sf.net）上面提供的使用手册获取，这里就不再细述了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733;利用HiveDB实现数据切分及整合</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">和前面的MySQLProxy以及Amoeba一样，HiveDB同样是一个基于Java针对MySQL数据库的提供数据切分及整合的开源框架，只是目前的HiveDB仅仅支持数据的水平切分。主要解决大数据量下数据库的扩展性及数据的高性能访问问题，同时支持数据的冗余及基本的HA机制。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">HiveDB的实现机制与MySQLProxy和Amoeba有一定的差异，他并不是借助MySQL的Replication功能来实现数据的冗余，而是自行实现了数据冗余机制，而其底层主要是基于HibernateShards来实现的数据切分工作。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在HiveDB中，通过用户自定义的各种Partitionkeys（其实就是制定数据切分规则），将数据分散到多个MySQLServer中。在访问的时候，在运行Query请求的时候，会自动分析过滤条件，并行从多个MySQLServer中读取数据，并合并结果集返回给客户端应用程序。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">单纯从功能方面来讲，HiveDB可能并不如MySQLProxy和Amoeba那样强大，但是其数据切分的思路与前面二者并无本质差异。此外，HiveDB并不仅仅只是一个开源爱好者所共享的内容，而是存在商业公司支持的开源项目。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">下面是HiveDB官方网站上面一章图片，描述了HiveDB如何来组织数据的基本信息，虽然不能详细的表现出太多架构方面的信息，但是也基本可以展示出其在数据切分方面独特的一面了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><img src="http://songwie.com/attached/image/20150228/20150228195051_109.png" alt="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; max-width: 100%; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 4px;" /></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><span style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; line-height: 19.5px;">&#9733; mycat 数据整合：具体http://www.songwie.com/articlelist/11</span></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9733; 其他实现数据切分及整合的解决方案</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">除了上面介绍的几个数据切分及整合的整体解决方案之外，还存在很多其他同样提供了数据切分与整合的解决方案。如基于MySQLProxy的基础上做了进一步扩展的HSCALE，通过Rails构建的SpockProxy，以及基于Pathon的Pyshards等等。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">不管大家选择使用哪一种解决方案，总体设计思路基本上都不应该会有任何变化，那就是通过数据的垂直和水平切分，增强数据库的整体服务能力，让应用系统的整体扩展能力尽可能的提升，扩展方式尽可能的便捷。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">只要我们通过中间层Proxy应用程序较好的解决了数据切分和数据源整合问题，那么数据库的线性扩展能力将很容易做到像我们的应用程序一样方便，只需要通过添加廉价的PCServer服务器，即可线性增加数据库集群的整体服务能力，让数据库不再轻易成为应用系统的性能瓶颈。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><br /></p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">数据切分与整合可能存在的问题</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">这里，大家应该对数据切分与整合的实施有了一定的认识了，或许很多读者朋友都已经根据各种解决方案各自特性的优劣基本选定了适合于自己应用场景的方案，后面的工作主要就是实施准备了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在实施数据切分方案之前，有些可能存在的问题我们还是需要做一些分析的。一般来说，我们可能遇到的问题主要会有以下几点：</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 引入分布式事务的问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670;跨节点Join的问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&#9670; 跨节点合并排序分页问题；</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">1. 引入分布式事务的问题</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一旦数据进行切分被分别存放在多个MySQLServer中之后，不管我们的切分规则设计的多么的完美（实际上并不存在完美的切分规则），都可能造成之前的某些事务所涉及到的数据已经不在同一个MySQLServer中了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">在这样的场景下，如果我们的应用程序仍然按照老的解决方案，那么势必需要引入分布式事务来解决。而在MySQL各个版本中，只有从MySQL5.0开始以后的各个版本才开始对分布式事务提供支持，而且目前仅有Innodb提供分布式事务支持。不仅如此，即使我们刚好使用了支持分布式事务的MySQL版本，同时也是使用的Innodb存储引擎，分布式事务本身对于系统资源的消耗就是很大的，性能本身也并不是太高。而且引入分布式事务本身在异常处理方面就会带来较多比较难控制的因素。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">怎么办？其实我们可以可以通过一个变通的方法来解决这种问题，首先需要考虑的一件事情就是：是否数据库是唯一一个能够解决事务的地方呢？其实并不是这样的，我们完全可以结合数据库以及应用程序两者来共同解决。各个数据库解决自己身上的事务，然后通过应用程序来控制多个数据库上面的事务。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">也就是说，只要我们愿意，完全可以将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务，并通过应用程序来总控各个小事务。当然，这样作的要求就是我们的俄应用程序必须要有足够的健壮性，当然也会给应用程序带来一些技术难度。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">2.跨节点Join的问题</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">上面介绍了可能引入分布式事务的问题，现在我们再看看需要跨节点Join的问题。数据切分之后，可能会造成有些老的Join语句无法继续使用，因为Join使用的数据源可能被切分到多个MySQLServer中了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">怎么办？这个问题从MySQL数据库角度来看，如果非得在数据库端来直接解决的话，恐怕只能通过MySQL一种特殊的存储引擎Federated来解决了。Federated存储引擎是MySQL解决类似于Oracle的DBLink之类问题的解决方案。和OracleDBLink的主要区别在于Federated会保存一份远端表结构的定义信息在本地。咋一看，Federated确实是解决跨节点Join非常好的解决方案。但是我们还应该清楚一点，那就似乎如果远端的表结构发生了变更，本地的表定义信息是不会跟着发生相应变化的。如果在更新远端表结构的时候并没有更新本地的Federated表定义信息，就很可能造成Query运行出错，无法得到正确的结果。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">对待这类问题，我还是推荐通过应用程序来进行处理，先在驱动表所在的MySQLServer中取出相应的驱动结果集，然后根据驱动结果集再到被驱动表所在的MySQLServer中取出相应的数据。可能很多读者朋友会认为这样做对性能会产生一定的影响，是的，确实是会对性能有一定的负面影响，但是除了此法，基本上没有太多其他更好的解决办法了。而且，由于数据库通过较好的扩展之后，每台MySQLServer的负载就可以得到较好的控制，单纯针对单条Query来说，其响应时间可能比不切分之前要提高一些，所以性能方面所带来的负面影响也并不是太大。更何况，类似于这种需要跨节点Join的需求也并不是太多，相对于总体性能而言，可能也只是很小一部分而已。所以为了整体性能的考虑，偶尔牺牲那么一点点，其实是值得的，毕竟系统优化本身就是存在很多取舍和平衡的过程。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">3. 跨节点合并排序分页问题</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">一旦进行了数据的水平切分之后，可能就并不仅仅只有跨节点Join无法正常运行，有些排序分页的Query语句的数据源可能也会被切分到多个节点，这样造成的直接后果就是这些排序分页Query无法继续正常运行。其实这和跨节点Join是一个道理，数据源存在于多个节点上，要通过一个Query来解决，就和跨节点Join是一样的操作。同样Federated也可以部分解决，当然存在的风险也一样。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">还是同样的问题，怎么办？我同样仍然继续建议通过应用程序来解决。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">如何解决？解决的思路大体上和跨节点Join的解决类似，但是有一点和跨节点Join不太一样，Join很多时候都有一个驱动与被驱动的关系，所以Join本身涉及到的多个表之间的数据读取一般都会存在一个顺序关系。但是排序分页就不太一样了，排序分页的数据源基本上可以说是一个表（或者一个结果集），本身并不存在一个顺序关系，所以在从多个数据源取数据的过程是完全可以并行的。这样，排序分页数据的取数效率我们可以做的比跨库Join更高，所以带来的性能损失相对的要更小，在有些情况下可能比在原来未进行数据切分的数据库中效率更高了。当然，不论是跨节点Join还是跨节点排序分页，都会使我们的应用服务器消耗更多的资源，尤其是内存资源，因为我们在读取访问以及合并结果集的这个过程需要比原来处理更多的数据。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">分析到这里，可能很多读者朋友会发现，上面所有的这些问题，我给出的建议基本上都是通过应用程序来解决。大家可能心里开始犯嘀咕了，是不是因为我是DBA，所以就很多事情都扔给应用架构师和开发人员了？</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">其实完全不是这样，首先应用程序由于其特殊性，可以非常容易做到很好的扩展性，但是数据库就不一样，必须借助很多其他的方式才能做到扩展，而且在这个扩展过程中，很难避免带来有些原来在集中式数据库中可以解决但被切分开成一个数据库集群之后就成为一个难题的情况。要想让系统整体得到最大限度的扩展，我们只能让应用程序做更多的事情，来解决数据库集群无法较好解决的问题。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">&nbsp;</p><h2><strong style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span style="margin: 0px; padding: 0px; border: 0px; font-size: 14pt; vertical-align: baseline; line-height: 1.5;">小结</span></strong></h2><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline; line-height: 1.6; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;">通过数据切分技术将一个大的MySQLServer切分成多个小的MySQLServer，既解决了写入性能瓶颈问题，同时也再一次提升了整个数据库集群的扩展性。不论是通过垂直切分，还是水平切分，都能够让系统遇到瓶颈的可能性更小。尤其是当我们使用垂直和水平相结合的切分方法之后，理论上将不会再遇到扩展瓶颈了。</p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 16px; vertical-align: baseline; line-height: 1.6;"></p><p style="margin: 1.3em 0px 1.5em; padding: 0px; border: 0px; font-size: 16px; vertical-align: baseline; line-height: 1.6;"></p></div><footer style="margin: 1.714285714rem 0px 12px; padding: 0px; border: 0px; font-size: 0.928571429rem; vertical-align: baseline; color: #757575; clear: both; line-height: 1.846153846; font-family: 'Helvetica Neue', Helvetica, 'Hiragino Sans GB', Arial, sans-serif; background-color: #ffffff;">发布在[ 技术 ]&nbsp;<a href="http://songwie.com/articlelist/21#" title="" rel="bookmark" style="margin: 0px; padding: 0px; border-width: 0px 0px 1px; border-bottom-style: dotted; border-bottom-color: #cccccc; font-size: 13px; vertical-align: baseline; outline: none; color: #757575; text-decoration: none;"><time datetime="2014/12/06 21:07:33" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2015-01-05 17:49:30.0</time></a>&nbsp;<span style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; vertical-align: baseline;">by&nbsp;<span vcard"="" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><a fn=""  n"="" href="http://www.songwie.com/blog/author/1" title="" rel="author" style="margin: 0px; padding: 0px; border-width: 0px 0px 1px; border-bottom-style: dotted; border-bottom-color: #cccccc; vertical-align: baseline; outline: none; color: #757575; text-decoration: none;">从零开始</a></span></span></footer><img src ="http://www.blogjava.net/xiaomage234/aggbug/423493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-03-16 18:27 <a href="http://www.blogjava.net/xiaomage234/archive/2015/03/16/423493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Bug #70588	Index merge used on partitionned table can return wrong result set</title><link>http://www.blogjava.net/xiaomage234/archive/2014/12/08/421173.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 08 Dec 2014 09:33:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/12/08/421173.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/421173.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/12/08/421173.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/421173.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/421173.html</trackback:ping><description><![CDATA[<div>Bug #70588<span style="white-space:pre">	</span>Index merge used on partitionned table can return wrong result set</div><div>Submitted:<span style="white-space:pre">	</span>10 Oct 2013 12:09<span style="white-space:pre">	</span>Modified:<span style="white-space:pre">	</span>5 Nov 2013 17:05</div><div>Reporter:<span style="white-space:pre">	</span>Joffrey MICHAIE<span style="white-space:pre">	</span>Email Updates:<span style="white-space:pre">	</span></div><div></div><div>Status:<span style="white-space:pre">	</span>Closed<span style="white-space:pre">	</span>Impact on me:<span style="white-space:pre">	</span></div><div>None&nbsp;</div><div>Category:<span style="white-space:pre">	</span>Server: Partition<span style="white-space:pre">	</span>Severity:<span style="white-space:pre">	</span>S2 (Serious)</div><div>Version:<span style="white-space:pre">	</span>5.6.14,5.5<span style="white-space:pre">	</span>OS:<span style="white-space:pre">	</span>Any</div><div>Assigned to:<span style="white-space:pre">		</span>Target Version:<span style="white-space:pre">	</span></div><div>Tags:<span style="white-space:pre">	</span>index merge, intersect, partition, wrong resultset</div><div>Triage:<span style="white-space:pre">	</span>Needs Triage: D2 (Serious)</div><div>ViewAdd CommentFilesDeveloperEdit SubmissionView Progress LogContributions</div><div>[10 Oct 2013 12:09] Joffrey MICHAIE</div><div>Description:</div><div>Simple query where&nbsp;</div><div></div><div>indexed_col = 'x' and indexed_date_column = 'yyyy-mm-aa'</div><div></div><div>&nbsp;returns wrong resultset, when run on partitionned table, and using index_merge (indexed_col,indexed_date_column)</div><div></div><div>Found on 5.5, repeated on 5.6.14, didn't test on 5.1</div><div></div><div>How to repeat:</div><div>Start MySQL with 100% default settings.</div><div></div><div>CREATE TABLE `poll` (</div><div>&nbsp; `id_key` int(10) unsigned NOT NULL AUTO_INCREMENT,</div><div>&nbsp; `id` int(6) NOT NULL DEFAULT '0',</div><div>&nbsp; `id_poll` int(6) NOT NULL DEFAULT '0',</div><div>&nbsp; `date_long` datetime NOT NULL,</div><div>&nbsp; `date_short` date NOT NULL,</div><div>&nbsp; PRIMARY KEY (`id_key`,`id_poll`),</div><div>&nbsp; KEY `id` (`id`),</div><div>&nbsp; KEY `date_creation` (`date_short`)</div><div>) ENGINE=InnoDB AUTO_INCREMENT=14101389 DEFAULT CHARSET=latin1</div><div>/*!50100 PARTITION BY HASH (id_poll)</div><div>PARTITIONS 20 */;</div><div></div><div>INSERT INTO `poll` VALUES (NULL,1718848,580660,'2013-10-09 18:21:00','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,39369,869049,'2013-10-09 18:21:02','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,1916580,'2013-10-09 18:21:09','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,1333222,'2013-10-09 18:20:31','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,1557405,869555,'2013-10-09 18:20:32','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,1343938,'2013-10-09 18:20:32','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,1157259,'2013-10-09 18:20:40','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,1800441,'2013-10-09 18:20:50','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,60,'2013-10-09 18:20:53','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,1718848,580660,'2013-10-09 18:21:00','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,39369,869049,'2013-10-09 18:21:02','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,1916580,'2013-10-09 18:21:09','2013-10-09');</div><div>INSERT INTO `poll` VALUES (NULL,70,1916580,'2013-10-0Query OK, 1 row affected (0,01 sec)</div><div></div><div>explain SELECT date_short FROM poll WHERE id =70 AND date_short = &nbsp;'2013-10-10'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+----+-------------+-------+-------------+------------------+------------------+---------+------+------+-------------------------------------------------------------+</div><div>| id | select_type | table | type &nbsp; &nbsp; &nbsp; &nbsp;| possible_keys &nbsp; &nbsp;| key &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| key_len | ref &nbsp;| rows | Extra &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</div><div>+----+-------------+-------+-------------+------------------+------------------+---------+------+------+-------------------------------------------------------------+</div><div>| &nbsp;1 | SIMPLE &nbsp; &nbsp; &nbsp;| poll &nbsp;| index_merge | id,date_creation | date_creation,id | 3,4 &nbsp; &nbsp; | NULL | &nbsp; &nbsp;2 | Using intersect(date_creation,id); Using where; Using index |</div><div>+----+-------------+-------+-------------+------------------+------------------+---------+------+------+-------------------------------------------------------------+</div><div>1 row in set (0,00 sec)</div><div></div><div>(data sample is small, you can run ANALYZE TABLE if intersect is not shown)</div><div></div><div>mysql&gt; &nbsp;SELECT date_short FROM poll WHERE id =70 AND date_short = &nbsp;'2013-10-10';</div><div>Empty set (0,01 sec)</div><div></div><div>mysql&gt; &nbsp;SELECT date_short FROM poll WHERE id =70 AND date_short like &nbsp;'2013-10-10';</div><div>+------------+</div><div>| date_short |</div><div>+------------+</div><div>| 2013-10-10 |</div><div>+------------+</div><div>1 row in set (0,00 sec)</div><div></div><div>Other examples:</div><div>mysql&gt; &nbsp;SELECT date_short FROM poll IGNORE INDEX (date_creation) WHERE id =70 AND date_short = &nbsp;'2013-10-10';</div><div>+------------+</div><div>| date_short |</div><div>+------------+</div><div>| 2013-10-10 |</div><div>+------------+</div><div>1 row in set (0,00 sec)</div><div></div><div>mysql&gt; &nbsp;SELECT date_short FROM poll IGNORE INDEX (id) WHERE id =70 AND date_short = &nbsp;'2013-10-10';</div><div>+------------+</div><div>| date_short |</div><div>+------------+</div><div>| 2013-10-10 |</div><div>+------------+</div><div>1 row in set (0,00 sec)</div><div></div><div>mysql&gt; alter table poll remove partitioning;</div><div>Query OK, 13 rows affected (0,08 sec)</div><div>Records: 13 &nbsp;Duplicates: 0 &nbsp;Warnings: 0</div><div></div><div>mysql&gt; &nbsp;SELECT date_short FROM poll WHERE id =70 AND date_short = &nbsp;'2013-10-10';</div><div>+------------+</div><div>| date_short |</div><div>+------------+</div><div>| 2013-10-10 |</div><div>+------------+</div><div>1 row in set (0,00 sec)</div><div></div><div>Suggested fix:</div><div>Return correct resultset, or do not use intersection merge on hash partitionned tables</div><div>[10 Oct 2013 12:30] Miguel Solorzano</div><div>Thank you for the bug report.</div><div></div><div>C:\dbs&gt;c:\dbs\5.6\bin\mysql -uroot --port=3560 --prompt="mysql 5.6 &gt; "</div><div>Welcome to the MySQL monitor. &nbsp;Commands end with ; or \g.</div><div>Your MySQL connection id is 3</div><div>Server version: 5.6.15 Source distribution</div><div></div><div>Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.</div><div></div><div>Oracle is a registered trademark of Oracle Corporation and/or its</div><div>affiliates. Other names may be trademarks of their respective</div><div>owners.</div><div></div><div>Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.</div><div></div><div>mysql 5.6 &gt; use xd</div><div>Database changed</div><div>mysql 5.6 &gt; CREATE TABLE `poll` (</div><div>&nbsp; &nbsp; -&gt; &nbsp; `id_key` int(10) unsigned NOT NULL AUTO_INCREMENT,</div><div>&nbsp; &nbsp; -&gt; &nbsp; `id` int(6) NOT NULL DEFAULT '0',</div><div>&nbsp; &nbsp; -&gt; &nbsp; `id_poll` int(6) NOT NULL DEFAULT '0',</div><div>&nbsp; &nbsp; -&gt; &nbsp; `date_long` datetime NOT NULL,</div><div>&nbsp; &nbsp; -&gt; &nbsp; `date_short` date NOT NULL,</div><div>&nbsp; &nbsp; -&gt; &nbsp; PRIMARY KEY (`id_key`,`id_poll`),</div><div>&nbsp; &nbsp; -&gt; &nbsp; KEY `id` (`id`),</div><div>&nbsp; &nbsp; -&gt; &nbsp; KEY `date_creation` (`date_short`)</div><div>&nbsp; &nbsp; -&gt; ) ENGINE=InnoDB AUTO_INCREMENT=14101389 DEFAULT CHARSET=latin1</div><div>&nbsp; &nbsp; -&gt; /*!50100 PARTITION BY HASH (id_poll)</div><div>&nbsp; &nbsp; -&gt; PARTITIONS 20 */;</div><div>Query OK, 0 rows affected (4.76 sec)</div><div></div><div>mysql 5.6 &gt;</div><div>mysql 5.6 &gt; INSERT INTO `poll` VALUES (NULL,1718848,580660,'2013-10-09 18:21:00','2013-10-09');</div><div>Query OK, 1 row affected (0.20 sec)</div><div></div><div>&lt;CUT&gt;</div><div></div><div>mysql 5.6 &gt; SELECT date_short FROM poll WHERE id =70 AND date_short = &nbsp;'2013-10-10';</div><div>Empty set (0.00 sec)</div><div></div><div>mysql 5.6 &gt; alter table poll remove partitioning;</div><div>Query OK, 13 rows affected (3.76 sec)</div><div>Records: 13 &nbsp;Duplicates: 0 &nbsp;Warnings: 0</div><div></div><div>mysql 5.6 &gt; SELECT date_short FROM poll WHERE id =70 AND date_short = &nbsp;'2013-10-10';</div><div>+------------+</div><div>| date_short |</div><div>+------------+</div><div>| 2013-10-10 |</div><div>+------------+</div><div>1 row in set (0.02 sec)</div><div></div><div>mysql 5.6 &gt;</div><div>[10 Oct 2013 12:55] Joffrey MICHAIE</div><div>From:</div><div>http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-14.html</div><div></div><div>For partitioned tables, queries could return different results depending on whether Index Merge was used. (Bug #16862316)</div><div>[5 Nov 2013 17:05] Jonathan Stephens</div><div>Fixed in 5.5+. Documented in the 5.5.36, 5.6.16, and 5.7.4 changelogs, as follows:</div><div></div><div>&nbsp; &nbsp; &nbsp; Queries using index_merge optimization (see&nbsp;</div><div>&nbsp; &nbsp; &nbsp; http://dev.mysql.com/doc/refman/5.5/en/index-merge-optimization.html)&nbsp;</div><div>&nbsp; &nbsp; &nbsp; could return invalid results when run against tables that were&nbsp;</div><div>&nbsp; &nbsp; &nbsp; partitioned by HASH.&nbsp;</div><div></div><div>Closed.</div><div>[2 Feb 17:20] Laurynas Biveinis</div><div>5.5$ bzr log -r 4538</div><div>------------------------------------------------------------</div><div>revno: 4538</div><div>committer: Aditya A &lt;aditya.a@oracle.com&gt;</div><div>branch nick: mysql-5.5</div><div>timestamp: Tue 2013-11-05 19:25:26 +0530</div><div>message:</div><div>&nbsp; Bug#17588348: INDEX MERGE USED ON PARTITIONED TABLE&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CAN RETURN WRONG RESULT SET</div><div>&nbsp;&nbsp;</div><div>&nbsp; PROBLEM</div><div>&nbsp; -------</div><div>&nbsp; In ha_partition::cmp_ref() we were only calling the&nbsp;</div><div>&nbsp; underlying cmp_ref() of storage engine if the records</div><div>&nbsp; are in the same partiton,else we sort by partition and</div><div>&nbsp; returns the result.But the index merge intersect&nbsp;</div><div>&nbsp; algorithm expects first to sort by row-id first and&nbsp;</div><div>&nbsp; then by partition id.</div><div>&nbsp;&nbsp;</div><div>&nbsp; FIX</div><div>&nbsp; ---</div><div>&nbsp; Compare the refernces first using storage engine cmp_ref</div><div>&nbsp; and then if references are equal(only happens if&nbsp;</div><div>&nbsp; non clustered index is used) then sort it by partition id.</div><div>&nbsp;&nbsp;</div><div>&nbsp; [Approved by Mattiasj #rb3755]</div><div>&nbsp; -</div><img src ="http://www.blogjava.net/xiaomage234/aggbug/421173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-12-08 17:33 <a href="http://www.blogjava.net/xiaomage234/archive/2014/12/08/421173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>pt-table-checksum 和 pt-table-sync 的使用</title><link>http://www.blogjava.net/xiaomage234/archive/2014/11/21/420419.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 21 Nov 2014 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/11/21/420419.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/420419.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/11/21/420419.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/420419.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/420419.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: pt-table-checksum测试库一致的情况下./pt-table-checksum h='127.0.0.1',u='root',p='dh123',P=5331 -d db1 --recursion-method=processlist --no-check-binlog-format --replicate=test.checksumsSELECT db, tbl,lower_boun...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/11/21/420419.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/420419.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-11-21 16:08 <a href="http://www.blogjava.net/xiaomage234/archive/2014/11/21/420419.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL 5.5.12 row格式复制下从库结构变更引发1677错误一则</title><link>http://www.blogjava.net/xiaomage234/archive/2014/11/21/420412.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 21 Nov 2014 06:19:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/11/21/420412.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/420412.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/11/21/420412.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/420412.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/420412.html</trackback:ping><description><![CDATA[<div style="font-family: tahoma, arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><h1><br /></h1></div><div clearfix"="" style="min-width: 0px; font-family: tahoma, arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><p style="margin: 1em 0px; padding: 0px;">以前statement复制下做表结构变更时，一般是一台一台的从库依次去做，最后做主库。</p><p style="margin: 1em 0px; padding: 0px;">今天在一台从库上进行表结构变更时却遇到一个复制报错，<br />Last_Errno: 1677<br />Last_Error: Column 7 of table &#8216;user_0.user_00&#8242; cannot be converted from type &#8216;varchar(10)&#8217; to type &#8216;varbinary(30)&#8217;</p><p style="margin: 1em 0px; padding: 0px;">原变更语句为<br />alter table user_00 modify `column7` varbinary(30) NOT NULL DEFAULT &#8221;;</p><p style="margin: 1em 0px; padding: 0px;">原表中此字段类型为<br />`column7` varbinary(10) NOT NULL DEFAULT &#8221;</p><p style="margin: 1em 0px; padding: 0px;">s 命令显示此从库为5.5格式，并且复制是row格式。</p><p style="margin: 1em 0px; padding: 0px;">官网查询后，发现这并不是一个bug，</p><p style="margin: 1em 0px; padding: 0px;">http://bugs.mysql.com/bug.php?id=59424</p><p style="margin: 1em 0px; padding: 0px;">在5.5的row格式复制中，有参数<br />slave_type_conversions来控制复制中主从结构不一致的处理</p><p style="margin: 1em 0px; padding: 0px;">取值见下表：<br /><a href="http://www.imcjd.com/wp-content/uploads/2012/06/slave_type_conversions.jpg" style="color: #cc0000; font-weight: bold;"><img size-full=""  wp-image-1215"="" title="slave_type_conversions" src="http://www.imcjd.com/wp-content/uploads/2012/06/slave_type_conversions.jpg" alt="" width="761" height="417" style="border: 1px solid #dddddd; display: block; margin: 10px auto; padding: 5px; border-radius: 3px; max-width: 96%; height: auto; background-color: #f3f3f3;" /></a></p><p style="margin: 1em 0px; padding: 0px;">默认为&#8221;，即不支持主从字段类型不一致，<br />其它3种类型为：<br />all_lossy 支持有损转换，如int&#8211;&gt;tinyint<br />all_non_lossy 支持无损转换，如char(20)&#8211;&gt;varchar(25)<br />all_lossy,all_non_lossy 支持所有转换</p><p style="margin: 1em 0px; padding: 0px;">此时手工在从库上执行：<br />stop slave;<br />set global slave_type_conversions=ALL_LOSSY;<br />start slave;</p><p style="margin: 1em 0px; padding: 0px;">复制恢复正常</p></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/420412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-11-21 14:19 <a href="http://www.blogjava.net/xiaomage234/archive/2014/11/21/420412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Galera/mysql 集群 备忘 【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418782.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 16 Oct 2014 06:18:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418782.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418782.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418782.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418782.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418782.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:http://blog.csdn.net/signmem/article/details/17379427特色MySQL/Galera 是一种多主同步集群，但只限于使用 MySQL/InnoDB 引擎，并具有下面特点同步复制多个主服务器的拓扑结构可以在任意节点上进行读写自动控制成员，自动删除故障节点自动加入节点真正给予行级别的并发复制调度客户连接优势参考下面基于 DBMS 集群的解决方法...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/10/16/418782.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/418782.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-16 14:18 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/16/418782.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Percona XtraDB Cluster 搭配 HAProxy</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418781.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 16 Oct 2014 06:17:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418781.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418781.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/16/418781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418781.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418781.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 28.7999992370605px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;">from:<span style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px;">http://www.tuicool.com/articles/2UVBba</span></p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 28.7999992370605px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;">标签：&nbsp;<strong>InnoDB</strong>&nbsp;<strong>MySQL</strong>&nbsp;<strong>Percona</strong>&nbsp;<strong>XtraDB</strong>&nbsp;<strong>Cluster</strong>&nbsp;<strong>Percoba</strong>&nbsp;<strong>XtraDB</strong>&nbsp;<strong>Cluster</strong><strong>Percona</strong>&nbsp;<strong>Software</strong>&nbsp;| 发表时间：2014-01-19 13:02 | 作者：appleboy</p><div style="font-size: 16px; line-height: 28.7999992370605px; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;"><div style="line-height: 1.8;"><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;"><img alt="percona" height="234" src="http://img0.tuicool.com/n6fEbe.jpg" width="240" style="max-width: 550px; height: auto; vertical-align: middle; border: 0px none; text-align: center; margin: 0px auto; display: block;" /></p><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">本篇文章紀錄安裝&nbsp;<a href="http://www.percona.com/software/percona-xtradb-cluster" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Percona XtraDB Cluster</a>&nbsp;(簡稱 PXC) 及搭配&nbsp;<a href="http://haproxy.1wt.eu/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">HAProxy</a>&nbsp;做分散流量系統，其實在業界已經很常看到 HAProxy + MySQL Cluster Database 解決方案，HAProxy 幫您解決負載平衡，並且偵測系統是否存活，管理者也就不用擔心 MySQL 服務是否會掛掉。本篇會著重於 HAProxy 設定部份，並且紀錄每一步安裝步驟。之前本作者寫過一篇&nbsp;<a href="http://blog.wu-boy.com/2013/03/galera-cluster-for-mysql-multi-master-replication/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Galera Cluster for MySQL Multi-master Replication</a>&nbsp;，也可以參考。今天測試系統都會以&nbsp;<a href="http://www.centos.org/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">CentOS</a>&nbsp;為主，各位讀者可以直接開&nbsp;<a href="http://aws.amazon.com/ec2/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Amazone EC2</a>&nbsp;來測試，測試完成再關閉即可。</p><h3>安裝 Percona XtraDB Cluster</h3><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">我們會使用官方&nbsp;<a href="http://www.percona.com/docs/wiki/repositories:yum" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Percona</a>&nbsp;及&nbsp;<a href="http://fedoraproject.org/wiki/EPEL" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">EPEL</a>&nbsp;repositories 進行軟體安裝，底下是 Yum 安裝步驟</p><div style="line-height: 1.8;"><pre ruby"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;"><span style="color: #008080;">$ </span>yum -y install Percona-XtraDB-Cluster-server Percona-XtraDB-Cluster-client Percona-Server-shared-compat percona-xtrabackup</pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">如果系統已經有安裝過&nbsp;<a href="http://codership.com/content/using-galera-cluster" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">MariaDB</a>&nbsp;+&nbsp;<a href="https://mariadb.org/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Galera</a>&nbsp;，請務必先移除套件</p><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">完成安裝 PXC 套件後，接著設定&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">my.cnf</code>&nbsp;設定檔</p><div style="line-height: 1.8;"><pre ruby"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;">[mysqld] server_id=<span style="color: #009999;">1</span> wsrep_provider=<span style="color: #009926;">/usr/lib</span>64/libgalera_smm.so wsrep_cluster_address=<span style="color: #dd1144;">"gcomm://"</span> wsrep_sst_auth=<span style="color: #990073;">username:</span>password wsrep_provider_options=<span style="color: #dd1144;">"gcache.size=4G"</span> wsrep_cluster_name=Percona wsrep_sst_method=xtrabackup wsrep_node_name=db_01 wsrep_slave_threads=<span style="color: #009999;">4</span> log_slave_updates innodb_locks_unsafe_for_binlog=<span style="color: #009999;">1</span> innodb_autoinc_lock_mode=<span style="color: #009999;">2</span></pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">再開啟第 2 台或第 3 台 PXC 服務的時候，務必確認第 1 台已經正確開啟成功。上面設定檔是針對第 1 台做設定，之後新增 Node，請務必修改<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">wsrep_cluster_address</code>&nbsp;填上你想要 Join 的 Cluster Server IP Address，另外每台的&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">server_id</code>&nbsp;及&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">wsrep_node_name</code>&nbsp;也會不同，請務必注意</p><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">第 2 台設定值</p><div style="line-height: 1.8;"><pre ini"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;">server_id=<span style="color: #009999;">2</span> wsrep_cluster_address=gcomm://<span style="color: #009999;">192.168.1.100 # replace this with the IP of your first node</span> wsrep_node_name=db_02</pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">第 3 台設定值</p><div style="line-height: 1.8;"><pre ini"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;">server_id=<span style="color: #009999;">2</span> wsrep_cluster_address=gcomm://<span style="color: #009999;">192.168.1.100 # replace this with the IP of your first node</span> wsrep_node_name=db_03</pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">根據&nbsp;<a href="http://www.percona.com/doc/percona-xtradb-cluster/5.5/manual/state_snapshot_transfer.html" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">State Snapshot Transfer</a>&nbsp;(簡稱 SST)，我們使用&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">Xtrabackup</code>&nbsp;，當新的 Node 連上時，就會開始複製資料到新的 Node 上，成功複製完成，可以看到底下 Log 訊息</p><div style="line-height: 1.8;"><pre perl"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;"><span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">05</span> [Note] WSREP: Flow-control interval: [<span style="color: #009999;">28</span>, <span style="color: #009999;">28</span>] <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">05</span> [Note] WSREP: Shifting OPEN -&gt; PRIMARY (TO: <span style="color: #009999;">678691</span>) <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">05</span> [Note] WSREP: State transfer required:         Group <span style="font-weight: bold;">state</span>: <span style="color: #009999;">28</span>e87291-da41-<span style="color: #009999;">11</span>e2-080<span style="color: #009999;">0</span>-<span style="color: #009999;">34</span>a03cad54a7:<span style="color: #009999;">678691</span>         Local <span style="font-weight: bold;">state</span>: <span style="color: #009999;">28</span>e87291-da41-<span style="color: #009999;">11</span>e2-080<span style="color: #009999;">0</span>-<span style="color: #009999;">34</span>a03cad54a7:<span style="color: #009999;">678684</span> <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">05</span> [Note] WSREP: New cluster view: global <span style="font-weight: bold;">state</span>: <span style="color: #009999;">28</span>e87291-da41-<span style="color: #009999;">11</span>e2-080<span style="color: #009999;">0</span>-<span style="color: #009999;">34</span>a03cad54a7:<span style="color: #009999;">678691</span>, view<span style="color: #999988; font-style: italic;"># 33: Primary, number of nodes: 3, my index: 1, protocol version 2</span> <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">05</span> [Warning] WSREP: Gap in <span style="font-weight: bold;">state</span> sequence. Need <span style="font-weight: bold;">state</span> transfer. <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span> [Note] WSREP: Running: <span style="color: #dd1144;">'wsrep_sst_xtrabackup --role '</span>joiner<span style="color: #dd1144;">' --address '</span><span style="color: #009999;">122.146</span>.<span style="color: #009999;">119.102</span><span style="color: #dd1144;">' --auth '</span>username:password<span style="color: #dd1144;">' --datadir '</span>/var/lib/mysql/<span style="color: #dd1144;">' --defaults-file '</span>/etc/<span style="font-weight: bold;">my</span>.cnf<span style="color: #dd1144;">' --parent '</span><span style="color: #009999;">965</span><span style="color: #dd1144;">''</span> WSREP_SST: [INFO] Streaming with tar (<span style="color: #009999;">20140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span>.<span style="color: #009999;">517</span>) WSREP_SST: [INFO] Using socat as streamer (<span style="color: #009999;">20140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span>.<span style="color: #009999;">519</span>) WSREP_SST: [INFO] Evaluating socat -u TCP-LISTEN:<span style="color: #009999;">4444</span>,reuseaddr stdio | tar xfi - --recursive-<span style="font-weight: bold;">unlink</span> -h; RC=( ${PIPESTATUS[<span style="color: #008080;">@]</span>} ) (<span style="color: #009999;">20140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span>.<span style="color: #009999;">531</span>) <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span> [Note] WSREP: Prepared SST request: xtrabackup|<span style="color: #009999;">122.146</span>.<span style="color: #009999;">119.102</span>:<span style="color: #009999;">4444</span>/xtrabackup_sst <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span> [Note] WSREP: wsrep_notify_cmd is <span style="font-weight: bold;">not</span> <span style="font-weight: bold;">defined</span>, skipping notification. <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span> [Note] WSREP: Assign initial position <span style="font-weight: bold;">for</span> certification: <span style="color: #009999;">678691</span>, protocol version: <span style="color: #009999;">2</span> <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span> [Note] WSREP: Prepared IST receiver, listening at: tcp:<span style="color: #009926;">//</span><span style="color: #009999;">122.146</span>.<span style="color: #009999;">119.102</span>:<span style="color: #009999;">4568</span> <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span> [Note] WSREP: Node <span style="color: #009999;">1</span> (db_01) requested <span style="font-weight: bold;">state</span> transfer from <span style="color: #dd1144;">'*any*'</span>. Selected <span style="color: #009999;">0</span> (db_02)(SYNCED) as donor. <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">56</span>:<span style="color: #009999;">07</span> [Note] WSREP: Shifting PRIMARY -&gt; JOINER (TO: <span style="color: #009999;">678692</span>) <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">57</span>:<span style="color: #009999;">36</span> [Note] WSREP: Synchronized with group, ready <span style="font-weight: bold;">for</span> connections <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">57</span>:<span style="color: #009999;">36</span> [Note] WSREP: wsrep_notify_cmd is <span style="font-weight: bold;">not</span> <span style="font-weight: bold;">defined</span>, skipping notification. <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">57</span>:<span style="color: #009999;">36</span> [Note] WSREP: <span style="color: #009999;">1</span> (db_02): State transfer from <span style="color: #009999;">0</span> (db_01) complete. <span style="color: #009999;">140117</span> <span style="color: #009999;">11</span>:<span style="color: #009999;">57</span>:<span style="color: #009999;">36</span> [Note] WSREP: Member <span style="color: #009999;">1</span> (db_02) synced with group.</pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">最後我們可以透過 MySQL Status 來看看是否有建立成功</p><div style="line-height: 1.8;"><pre sql"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;">mysql&gt; <span style="font-weight: bold;">show global status like <span style="color: #dd1144;">'wsrep_cluster_size'</span>;</span> +<span style="color: #999988; font-style: italic;">--------------------+-------+</span> | Variable_name      | Value | +<span style="color: #999988; font-style: italic;">--------------------+-------+</span> | wsrep_cluster_size | 3     | +<span style="color: #999988; font-style: italic;">--------------------+-------+</span> 1 row in <span style="font-weight: bold;">set (<span style="color: #009999;">0.00</span> sec)</span></pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">看到&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">wsrep_cluster_size</code>&nbsp;出現正確的 Server 數量，就代表設定成功。</p><h3>設定 HAProxy 負載平衡</h3><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">上述完成了 3 台 Cluster 設定，接著所有的 Application 服務都需要直接跟此 Cluster 溝通，為了完成此需求，我們必須將 HAProxy 安裝在其中一台伺服器來做負載平衡，今天會介紹兩種設定方式，第一種是採用&nbsp;<a href="http://en.wikipedia.org/wiki/Round-robin_scheduling" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">round robin</a>&nbsp;方式，意思就是說所有的 Application 都可以連上並且寫入資料到三台機器，這狀況其實沒有錯誤，但是如果同時寫入三台機器，難免會出現&nbsp;<a href="http://en.wikipedia.org/wiki/Optimistic_concurrency_control" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">optimistic locking</a>&nbsp;而產生 rollback，如果可以確定不會產生 conflict，其實這方案是不錯的。第2種設定方式就是只寫入單一 Node，但是可以讀取三台機器，也就是&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">insert</code>&nbsp;,&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">update</code>&nbsp;都是在同一台 Node 完成，所以 Application 不用擔心會產生 rollback 情形。第1種設定在大部份的狀況底下都是可以運作很好的，所以其實也不用擔心。</p><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">底下是&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">/etc/haproxy/haproxy.cfg</code>&nbsp;設定</p><div style="line-height: 1.8;"><pre perl"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;">frontend stats-front <span style="font-weight: bold;">bind</span> <span style="color: #008080;">*:</span><span style="color: #009999;">8080</span> mode http default_backend stats-back  frontend pxc-front <span style="font-weight: bold;">bind</span> <span style="color: #008080;">*:</span><span style="color: #009999;">3307</span> mode tcp default_backend pxc-back  frontend pxc-onenode-front <span style="font-weight: bold;">bind</span> <span style="color: #008080;">*:</span><span style="color: #009999;">3308</span> mode tcp default_backend pxc-onenode-back  backend stats-back mode http balance roundrobin stats uri /haproxy/stats stats auth username:password  backend pxc-back mode tcp balance leastconn option httpchk server c1 <span style="color: #009999;">192.168</span>.<span style="color: #009999;">1.100</span>:<span style="color: #009999;">3306</span> check port <span style="color: #009999;">9200</span> inter <span style="color: #009999;">12000</span> rise <span style="color: #009999;">3</span> fall <span style="color: #009999;">3</span> server c2 <span style="color: #009999;">192.168</span>.<span style="color: #009999;">1.101</span>:<span style="color: #009999;">3306</span> check port <span style="color: #009999;">9200</span> inter <span style="color: #009999;">12000</span> rise <span style="color: #009999;">3</span> fall <span style="color: #009999;">3</span> server c3 <span style="color: #009999;">192.168</span>.<span style="color: #009999;">1.102</span>:<span style="color: #009999;">3306</span> check port <span style="color: #009999;">9200</span> inter <span style="color: #009999;">12000</span> rise <span style="color: #009999;">3</span> fall <span style="color: #009999;">3</span>  backend pxc-onenode-back mode tcp balance leastconn option httpchk server c1 <span style="color: #009999;">192.168</span>.<span style="color: #009999;">1.100</span>:<span style="color: #009999;">3306</span> check port <span style="color: #009999;">9200</span> inter <span style="color: #009999;">12000</span> rise <span style="color: #009999;">3</span> fall <span style="color: #009999;">3</span> server c2 <span style="color: #009999;">192.168</span>.<span style="color: #009999;">1.101</span>:<span style="color: #009999;">3306</span> check port <span style="color: #009999;">9200</span> inter <span style="color: #009999;">12000</span> rise <span style="color: #009999;">3</span> fall <span style="color: #009999;">3</span> backup server c3 <span style="color: #009999;">192.168</span>.<span style="color: #009999;">1.102</span>:<span style="color: #009999;">3306</span> check port <span style="color: #009999;">9200</span> inter <span style="color: #009999;">12000</span> rise <span style="color: #009999;">3</span> fall <span style="color: #009999;">3</span> backup</pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">從上述設定，可以看到我們定義了 3 個&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">frontend-backend</code>&nbsp;，其中<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">stats-front</code>&nbsp;是 HAProxy Status Page，另外兩組則是針對 PXC 設定。看到此設定，可以知道系統會 Listen 3307 及 3308 兩個 port，其中 3308 會讓 App 使用一台 PXC Node 而已，此設定可以避免因為&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">optimistic locking</code>&nbsp;而產生 rollbacks，如果 Node 掛點，則會啟動其他 Node。然而如果是連接 3307 port，系統會直接對3台 node 寫入或讀取，我們使用&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">leastconn</code>&nbsp;取代&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">round robin</code>&nbsp;，這代表著 HAProxy 會偵測所有機器，並且取得現在連線數目最少的 Node 來給下一個連線。最後<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">stats-front</code>&nbsp;是顯示 HAProxy 偵測及連線狀態，請務必設定帳號密碼。</p><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">完成設定，如何偵測 MySQL Server 是否存活，靠著就是 9200 port，透過 Http check 方式，讓 HAProxy 知道 PXC 狀態，安裝完 PXC 後，可以發現多了<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">clustercheck</code>&nbsp;指令，我們必須先給&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">clustercheckuser</code>&nbsp;使用者帳號密碼</p><div style="line-height: 1.8;"><pre sql"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;"># <span style="font-weight: bold;">Grant privileges required: $ GRANT PROCESS ON *.* TO <span style="color: #dd1144;">'clustercheckuser'</span>@<span style="color: #dd1144;">'localhost'</span> IDENTIFIED BY <span style="color: #dd1144;">'clustercheckpassword!'</span>;</span></pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">此&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">clustercheck</code>&nbsp;指令會在 Local 執行<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">SHOW STATUS LIKE 'wsrep_local_state'</code>&nbsp;MySQL 指令，回傳值為&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">200</code>&nbsp;或<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">503</code>&nbsp;，指令確定成功執行，最後步驟就是透過&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">xinetd</code>&nbsp;產生 9200 port 的服務。底下先安裝&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">xinetd</code>&nbsp;服務</p><div style="line-height: 1.8;"><pre ruby"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;"><span style="color: #008080;">$ </span>yum -y install xinetd</pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">產生&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; color: #dd1144; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border: 1px solid #e1e1e8; white-space: nowrap; background-color: #f7f7f9;">mysqlchk</code>&nbsp;設定</p><div style="line-height: 1.8;"><pre perl"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;"><span style="color: #999988; font-style: italic;"># default: on</span> <span style="color: #999988; font-style: italic;"># description: mysqlchk</span> service mysqlchk { <span style="color: #999988; font-style: italic;"># this is a config for xinetd, place it in /etc/xinetd.d/</span>     disable = <span style="font-weight: bold;">no</span>     flags = REUSE     socket_type = stream     port = <span style="color: #009999;">9200</span>     <span style="font-weight: bold;">wait</span> = <span style="font-weight: bold;">no</span>     user = nobody     server = <span style="color: #009926;">/usr/bin</span><span style="color: #009926;">/clustercheck     log_on_failure += USERID     only_from = 0.0.0.0/</span><span style="color: #009999;">0</span>     <span style="color: #999988; font-style: italic;"># recommended to put the IPs that need</span>     <span style="color: #999988; font-style: italic;"># to connect exclusively (security purposes)</span>     per_source = UNLIMITED }</pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">上面步驟全部成功，請打開 URL 輸入 HAProxy Status 頁面，看到底下狀態，就是代表設定成功</p><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;"><img alt="Statistics Report for HAProxy" src="http://img1.tuicool.com/vYVJ7b.jpg" style="max-width: 550px; height: auto; vertical-align: middle; border: 0px none; text-align: center; margin: 0px auto; display: block;" /></p><div style="line-height: 1.8;"><div style="line-height: 1.8;"><h3>Related View</h3><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; line-height: 1.8;"><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2014/01/sysbench-test-percona-xtradb-server-performance/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Sysbench 測試 Percona XtraDB Server 效能</a>&nbsp;<small style="font-size: 14px;">(0)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2013/03/galera-cluster-for-mysql-multi-master-replication/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Galera Cluster for MySQL Multi-master Replication</a>&nbsp;<small style="font-size: 14px;">(2)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2014/01/percona-xtradb-server-read-only-issue/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Percona XtraDB Server 出現 read only issue</a>&nbsp;<small style="font-size: 14px;">(0)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2013/01/percona-xtrabackup-innodb/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">Percona XtraBackup InnoDB 備份工具</a>&nbsp;<small style="font-size: 14px;">(1)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2012/12/mysql-myisam-tables-convert-to-innodb/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">MySQL MyISAM Engine 轉換成 InnoDB</a>&nbsp;<small style="font-size: 14px;">(2)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2012/11/innodb-as-the-default-mysql-storage-engine/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">MySQL 預設儲存引擎: InnoDB 介紹</a>&nbsp;<small style="font-size: 14px;">(11)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2013/04/best-mysqldump-innodb-data/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">MySQL 用 MySQLDump 備份 InnoDB 注意事項</a>&nbsp;<small style="font-size: 14px;">(1)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2008/08/%e8%bd%89%e8%bc%89mysql-%e7%9a%84-set-names-xxx-%e5%ad%97%e5%85%83%e7%b7%a8%e7%a2%bc%e5%95%8f%e9%a1%8c%e5%88%86%e6%9e%90/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">[轉載]MySQL 的 &#8220;SET NAMES xxx&#8221; 字元編碼問題分析</a>&nbsp;<small style="font-size: 14px;">(2)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2008/12/mysql-%e5%af%a6%e5%81%9a-mysql-master-master-replication-%e5%90%8c%e6%ad%a5/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">[MySQL] 實做 MySQL Master-Master Replication 同步</a>&nbsp;<small style="font-size: 14px;">(1)</small>&nbsp;<br /></li><li style="line-height: 1.8; list-style-type: disc;"><a href="http://blog.wu-boy.com/2009/07/sql-mysql-row_number-simulation/" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; -webkit-transition: 0.25s; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #949494; font-style: italic; font-weight: bold;">[SQL] MySQL ROW_NUMBER Simulation</a>&nbsp;<small style="font-size: 14px;">(0)</small>&nbsp;</li></ul></div></div></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/418781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-16 14:17 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/16/418781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mysql高可用方案MHA介绍</title><link>http://www.blogjava.net/xiaomage234/archive/2014/08/05/416586.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 05 Aug 2014 05:45:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/08/05/416586.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/416586.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/08/05/416586.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/416586.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/416586.html</trackback:ping><description><![CDATA[<div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">mysql高可用方案MHA介绍</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">概述</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">MHA是一位日本MySQL大牛用Perl写的一套MySQL故障切换方案，来保证<a href="http://www.2cto.com/database/" target="_blank" style="color: #333333; text-decoration: none;">数据库</a>系统的高可用.在宕机的时间内（通常10&#8212;30秒内），完成故障切换，部署MHA，可避免主从一致性问题，节约购买新服务器的费用，不影响服务器性能，易安装，不改变现有部署。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp;还支持在线切换，从当前运行master切换到一个新的master上面，只需要很短的时间（0.5-2秒内），此时仅仅阻塞写操作，并不影响读操作，便于主机硬件维护。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">在有高可用，数据一致性要求的系统上，MHA 提供了有用的功能，几乎无间断的满足维护需要。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;优点</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">1 &nbsp; &nbsp; &nbsp; &nbsp;master自动监控和故障转移</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; 在当前已存在的主从复制环境中，MHA可以监控master主机故障，并且故障自动转移。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">即使有一些slave没有接受新的relay log events，MHA也会从最新的slave自动识别差异的relay log events，并apply差异的event到其他slaves。因此所有的slave都是一致的。MHA秒级别故障转移（9-12秒监测到主机故障，任选7秒钟关闭电源主机避免脑裂，接下来apply差异relay logs，注册到新的master，通常需要时间10-30秒即total downtime）。另外，在配置文件里可以配置一个slave优先成为master。因为MHA修复了slave之间的一致性，dba就不用去处理一致性问题。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; &nbsp;当迁移新的master之后，并行恢复其他slave。即使有成千上万的slave,也不会影响恢复master时间，slave也很快完成。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; &nbsp; DeNA公司在150+主从环境中用MHA。当其中一个master崩溃，MHA4秒完成故障转移，这是主动/被动集群解决方案无法完成的。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">2 &nbsp; &nbsp; &nbsp; &nbsp;互动(手动)master故障转移</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;MHA可以用来只做故障转移，而不监测master，MHA只作为故障转移的交互。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">3 &nbsp; &nbsp; &nbsp; &nbsp;非交互式故障转移</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;非交互式的故障转移也提供（不监控master，自动故障转移）。这个特性很有用，特别是你已经安装了其他软件监控master。比如，用Pacemaker(Heartbeat)监测master故障和vip接管，用MHA故障转移和slave提升。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">4 &nbsp; &nbsp; &nbsp; &nbsp;在线切换master到不同主机</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;在很多情况下，有必要将master转移到其他主机上（如替换raid控制器，提升master机器硬件等等）。这并不是master崩溃，但是计划维护必须去做。计划维护导致downtime，必须尽可能快的恢复。快速的master切换和优雅的阻塞写操作是必需的，MHA提供了这种方式。优雅的master切换， 0.5-2秒内阻塞写操作。在很多情况下0.5-2秒的downtime是可以接受的，并且即使不在计划维护窗口。这意味着当需要更换更快机器，升级高版本时，dba可以很容易采取动作。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">5 &nbsp; &nbsp; &nbsp; &nbsp;master crash不会导致主从数据不一致性</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; 当master crash后，MHA自动识别slave间relay logevents的不同，然后应用与不同的slave，最终所有slave都同步。结合通过半同步一起使用，几乎没有任何数据丢失。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">其他高可用方案</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">6 &nbsp; &nbsp; &nbsp; &nbsp;MHA部署不影响当前环境设置</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">MHA最重要的一个设计理念就是尽可能使用简单。使用与5.0+以上主从环境，其他HA方案需要改变<a href="http://www.2cto.com/database/MySQL/" target="_blank" style="color: #333333; text-decoration: none;">mysql</a>部署设置，MHA不会让dba做这些部署配置，同步和半同步环境都可以用。启动/停止/升级/降级/安装/卸载 MHA都不用改变mysql主从（如启动/停止）。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">当你需要升级MHA到新版本时，不需要停止mysql，仅仅更新HMA版本，然后重新启动MHAmanger即可。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp;MHA 支持包含5.0/5/1/5.5(应该也支持5.6，翻译文档时MHA开发者没更新对于5.6版本)。有些HA方案要求特定的mysql版本（如mysqlcluster，mysql with global transaction id 等）,而且你可能不想仅仅为了MasterHA而迁移应用。很多情况下，公司已经部署了许多传统的mysql应用，开发或dba不想花太多时间迁移到不同的存储引擎或新的特性（newer bleeding edge distributions 不知道这个是否该这么翻译）。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">7 &nbsp; &nbsp; &nbsp; &nbsp;不增加服务器费用</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">MHA 包含MHA Manager和MHA node。MHA node运行在每台mysql服务器上，Manager可以单独部署一台机器，监控100+以上master，总服务器数量不会有太大增加。需要注意的是Manager也可以运行在slaves中的一台机器上。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">8 &nbsp; &nbsp; &nbsp; &nbsp;性能无影响</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">当监控master，MHA只是几秒钟（默认3秒）发送ping包，不发送大的查询。主从复制性能不受影响</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">9 &nbsp; &nbsp; &nbsp; &nbsp;适用任何存储引擎</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Mysql不仅仅适用于事务安全的innodb引擎，在主从中适用的引擎，MHA都可以适用。即使用遗留环境的mysiam引擎，不进行迁移，也可以用MHA。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;与其他HA方案比较</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Doing everything manually</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Mysql replication 是同步或半同步。当master崩溃时，很有可能一些slave还没有接受最新的relay log events，这意味着每一个slave都相互处在不同的状态。人为修复一致性问题显得不再平凡。没有一致性问题，主从也可能不会启动（如duplicate key error）。花费1个多小时重新启动主从复制显得不同寻常。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Single master and single slave</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">在单一主从情况下，一些slave 落后与其他slave的情况将不会发生。其中一个master崩溃，可以轻松的让应用转移到一个新的master上面，提供对外服务，故障迁移很简单。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Master, one candidate master, and multiple slaves双主多从</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">双主多从的架构也很常见。主master挂掉，备用master将接替主master提供服务。某些情况配置为多主架构。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">M(RW)-----M2(R) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;M(RW), promoted from M2</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; +----+----+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--(master crash)--&gt; &nbsp; +-x--+--x-+</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;S(R) &nbsp; &nbsp; S2(R) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; S(?) &nbsp; &nbsp; &nbsp;S(?)</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (Fromwhich position should S restart replication?)</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">但是这并不作为master故障转移方案。当前master挂掉，剩余slave不一定接受全部relay log events，修复数据一致性还是问题。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">这种架构使用广泛，但是不是所有人都能深刻理解上述问题。当前master挂掉，slave变得不统一或者slave不能从新的master复制数据。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">也许双master，其中一个master只读，每个master都至少有一个slave也许可能解决问题。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;M(RW)--M2(R)</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; &nbsp;|</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp; &nbsp; &nbsp; &nbsp; S(R) &nbsp; S2(R)</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Pacemaker + DRBD</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Pecemaker(Heartbeat)+DRBD+Mysql是一个通用方案。但是这个方案也有以下问题</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">1 费用问题，特别是跑大量主从环境。Pecemaker+DRBD是主动/被动的解决方案，因此需要一台被动服务器对外不提供任何应用服务。基本的需要四台mysql服务器，one active master，one passive master，two slaves。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">2 宕机时间(downtime)。Pacemaker+DRBD是主备集群，主master挂掉，备用master启用。这可能花费长的时间，特别是没有用innodb plugin。即使用innodb plugin，花费几分钟开始在备用master上接受连接也不寻常。另外，因为备用master上数据/文件缓存是空的，恢复时间，热身(填充数据到data buffer pool)花费不可忽视的时间。实践中，需要一台或更多slave提供足够的读服务。在热身时间内，空缓存导致写性能降低</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">3 写问题下降或一致性问题。为了让主动/被动集群真正的工作，每次提交(commit)后，必须刷新事务日志(binary log和innodb log)，也就是必须设置innodb-flush-log-at-trx-commit=1,sync-binlog=1。设置sync-binlog=1会降低写性能，因为fsync()函数被序列化(sync-binlog=1，group commit失效)。大部分案例中，不设置sync-binlog=1.如果没有设置sync-binlog=1，活动master crash，新的master(先前被动服务器)可能会丢失一些已经发送到slave的binary log events。假如 master 挂掉，slave A接受到mysqld-bin.000123,位置1500。binlog data刷新到硬盘的位置在1000，那么新的master数据也只能mysqld-bin.000123的1000处，然后在启动时创建一个新的binary log mysqld-bin.000124。如果发生这种情况，slave A不能继续复制，因为新的master 没有mysqld-bin.000123位置1500.</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;4 复杂。对多数人来说，安装/初始化pacemake和DRBD不是容易的事情。相对于其他案例，初始化DRBD需要重新创建<a href="http://www.2cto.com/os/" target="_blank" style="color: #333333; text-decoration: none;">系统</a>分区也不容易。要求dba在DRBD和linux内核层有足够的技能。如果dba执行了一个错误命令（如执行drbdadm&#8211;overwrite-data-of-peer primary 在被动节点），那么将会损坏活动的数据。重要的是另外一旦硬盘io层出现问题，多数dba处理这种问题不是容易的。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">MySQL Cluster</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Mysql cluster是真正的高可用解决方案，但是必须得用NDB存储引擎。如果你用innodb，将不能发挥mysql cluster集群优势。</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Semi-Synchronous Replication</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">半同步复制大大降低了binlog event仅仅存在于崩溃master上的这种风险。这非常有用的能避免数据丢失。但是半同步不能解决所有一致性问题，只能保证一个（不是所有）slave接受到master端的commit的binlog events，其他slave也许还没有接受全部的binlog events。不能apply不同的binlog events 从新的slave到 其他slave上，也不能保证相互一致性</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">&nbsp;</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">Global Transaction ID</div><div style="border-width: 0px; margin: 0px; list-style: none; color: #333333; font-family: 宋体; line-height: 28px; background-color: #ffffff;">GlobalTransaction ID所要达到的目的跟MHA相同，但它覆盖更多。MHA只是两级复制，但是global transaction id覆盖任何级别的复制环境，即使第两级复制失败，dba也能覆盖第三级。Check Google'sglobal transaction id project for details。</div><img src ="http://www.blogjava.net/xiaomage234/aggbug/416586.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-08-05 13:45 <a href="http://www.blogjava.net/xiaomage234/archive/2014/08/05/416586.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL数据库改名的三种方法</title><link>http://www.blogjava.net/xiaomage234/archive/2014/07/31/416389.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 31 Jul 2014 02:02:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/07/31/416389.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/416389.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/07/31/416389.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/416389.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/416389.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 28.799999237060547px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;"><span style="text-indent: 0px;">第一种方法：</span></p><div style="font-size: 16px; line-height: 28.799999237060547px; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;"><pre sql"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;">RENAME <span style="color: #0000ff;">database olddbname <span style="color: #333333; font-weight: bold;">TO</span> newdbname</span></pre></div><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 28.799999237060547px; text-indent: 1em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;">这个是5.1.7到5.1.23版本可以用的，但是官方不推荐，会有丢失数据的危险</p><div style="font-size: 16px; line-height: 28.799999237060547px; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;">第二种方法：</div><div style="font-size: 16px; line-height: 28.799999237060547px; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif; background-color: #ffffff;"><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">1.创建需要改成新名的数据库。&nbsp;<br />2.mysqldum 导出要改名的数据库&nbsp;<br />3.删除原来的旧库（确定是否真的需要）&nbsp;<br />当然这种方法虽然安全，但是如果数据量大，会比较耗时，哎，当时连这种方法都没有想到，真有想死的冲动。</p><div style="line-height: 1.8;">第三种方法：</div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">我这里就用一个脚本，很简单，相信大家都看的懂</p><div style="line-height: 1.8;"><div style="line-height: 1.8;"><pre bash"="" style="padding: 0.5em; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; font-size: 1em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; white-space: pre-wrap; border: 1px solid rgba(0, 0, 0, 0.14902); overflow-y: auto; background: #f8f8ff;"><span style="color: #999999; font-weight: bold;">#!/bin/<span style="color: #000000;">bash</span></span><span style="color: #000000;"> <span style="color: #999988; font-style: italic;"># 假设将sakila数据库名改为new_sakila</span> <span style="color: #999988; font-style: italic;"># MyISAM直接更改数据库目录下的文件即可</span>  mysql </span>-uroot -p123456 -e <span style="color: #800000;"><span style="color: #dd1144;">'</span></span><span style="color: #dd1144;"><span style="color: #800000;">create database if not exists new_sakila</span><span style="color: #800000;">'</span></span><span style="color: #000000;"> list_table</span>=$(mysql -uroot -p123456 -Nse <span style="color: #800000;"><span style="color: #dd1144;">"</span></span><span style="color: #dd1144;"><span style="color: #800000;">select table_name from information_schema.TABLES where TABLE_SCHEMA='sakila'</span><span style="color: #800000;">"</span></span><span style="color: #000000;">)  </span><span style="color: #0000ff;"><span style="color: #333333; font-weight: bold;">for</span></span> table <span style="color: #0000ff;"><span style="color: #333333; font-weight: bold;">in</span></span><span style="color: #000000;"> <span style="color: #008080;">$list_table</span> </span><span style="color: #0000ff;"><span style="color: #333333; font-weight: bold;">do</span></span><span style="color: #000000;">     mysql </span>-uroot -p123456 -e <span style="color: #800000;"><span style="color: #dd1144;">"</span></span><span style="color: #dd1144;"><span style="color: #800000;">rename table sakila.<span style="color: #008080;">$table</span> to new_sakila.<span style="color: #008080;">$table</span></span><span style="color: #800000;">"</span></span> <span style="color: #0000ff;"><span style="color: #333333; font-weight: bold;">done</span></span></pre></div><p style="margin: 0px 0px 0.75em; line-height: 1.8; text-indent: 1em;">这里用到了rename table,改表名的命令，但是如果新表名后面加数据库名，就会将老数据库的表移动到新的数据库，所以，这种方法即安全，又快速。</p></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/416389.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-07-31 10:02 <a href="http://www.blogjava.net/xiaomage234/archive/2014/07/31/416389.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL小问题解决集锦</title><link>http://www.blogjava.net/xiaomage234/archive/2014/07/25/416200.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 25 Jul 2014 06:56:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/07/25/416200.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/416200.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/07/25/416200.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/416200.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/416200.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1、MySQL错误日志里出现：140331 10:08:18 [ERROR] Error reading master configuration140331 10:08:18 [ERROR] Failed to initialize the master info structure140331 10:08:18 [Note] Event Scheduler: Loaded 0 events&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/07/25/416200.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/416200.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-07-25 14:56 <a href="http://www.blogjava.net/xiaomage234/archive/2014/07/25/416200.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL 5.5 和 5.6 默认参数值的差异</title><link>http://www.blogjava.net/xiaomage234/archive/2014/07/23/416134.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 23 Jul 2014 07:41:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/07/23/416134.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/416134.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/07/23/416134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/416134.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/416134.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://www.oschina.net/question/12_90733作为&nbsp;MySQL 5.5 和 5.6 性能比较的一部分，我研究了下两个版本默认参数的差异，为了了解差异内容，我使用如下的 SQL 语句分别在 MySQL 5.5 和 5.6 版本进行查询，得出下表（点击图片查看大图）：让我们来看看这些差异的配置中最重要的也是影响最大的部分：performance_schema...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/07/23/416134.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/416134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-07-23 15:41 <a href="http://www.blogjava.net/xiaomage234/archive/2014/07/23/416134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对于有大量重复数据的表添加唯一索引</title><link>http://www.blogjava.net/xiaomage234/archive/2014/07/07/415533.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 07 Jul 2014 05:52:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/07/07/415533.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/415533.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/07/07/415533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/415533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/415533.html</trackback:ping><description><![CDATA[<blockquote style="border-width: 0px 0px 0px 18px; border-left-color: #cccccc; margin: 0px; padding: 4px; width: 1000.796875px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #eeeeee;"><p style="margin-top: 10px; margin-bottom: 10px;">遇到如题的这么一个场景：需要在MySQL的一张innodb引擎的表(tableA)上添加一个唯一索引(idx_col1_u)。但是表中已经有大量重复数据，对于每个key(col1)，有的重复2行，有的重复N行。</p><p style="margin-top: 10px; margin-bottom: 10px;">此时，做数据的手工清理，或者SQL处理无疑是非常耗时的。</p></blockquote><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;</p><h2>1. Alter ignore table come to help</h2><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">印象中MySQL有一个独有的 alter ignore add unique index的语法。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">语法如下：</p><blockquote style="border-width: 0px 0px 0px 18px; border-left-color: #cccccc; margin: 0px; padding: 4px; width: 1000.796875px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #eeeeee;"><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">ALTER [ONLINE | OFFLINE] [IGNORE] TABLE <em>tbl_name</em></pre><p style="margin-top: 10px; margin-bottom: 10px;"><em><code>&nbsp;</code></em></p></blockquote><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">行为类似于insert ignore，即遇到冲突的unique数据则直接抛弃而不报错。对于加唯一索引的情况来说就是建一张空表，然后加上唯一索引，将老数据用insert ignore语法插入到新表中，遇到冲突则抛弃数据。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;"><span style="line-height: 1.5;">文档中对于alter ignore的注释：详见：<a href="http://dev.mysql.com/doc/refman/5.1/en/alter-table.html" style="color: #1d58d1; text-decoration: none;">http://dev.mysql.com/doc/refman/5.1/en/alter-table.html</a></span></p><blockquote style="border-width: 0px 0px 0px 18px; border-left-color: #cccccc; margin: 0px; padding: 4px; width: 1000.796875px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #eeeeee;"><p style="margin-top: 10px; margin-bottom: 10px;"><code>IGNORE</code>&nbsp;is a MySQL extension to standard SQL. It controls how&nbsp;<a title="13.1.7.&nbsp;ALTER TABLE Syntax" href="http://dev.mysql.com/doc/refman/5.1/en/alter-table.html" style="color: #1d58d1; text-decoration: none;"><code>ALTER TABLE</code></a>&nbsp;works if there are duplicates on unique keys in the new table or if warnings occur when strict mode is enabled. If&nbsp;<code>IGNORE</code>&nbsp;is not specified, the copy is aborted and rolled back if duplicate-key errors occur. If&nbsp;<code>IGNORE</code>&nbsp;is specified, only the first row is used of rows with duplicates on a unique key. The other conflicting rows are deleted. Incorrect values are truncated to the closest matching acceptable value.</p></blockquote><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;</p><h2>2.&nbsp;&nbsp;<strong>#1062 - Duplicate entry&nbsp;</strong></h2><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;然而在执行了 alter ignore table tableA add unique index idx_col1_u (col1) 后，还是报了以下错误：</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;<span style="color: #3366ff;">#1062 - Duplicate entry '111' for key 'col1'.</span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">不是会自动丢弃重复数据么？世界观被颠覆了。<span style="color: #ff0000;"><strong>查了下资料原来是alter ignore的语法不支持innodb。</strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">得知alter ignore的实现完全取决于存储引擎的内部实现，而不是server端强制的，具体描述如下：</p><blockquote style="border-width: 0px 0px 0px 18px; border-left-color: #cccccc; margin: 0px; padding: 4px; width: 1000.796875px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #eeeeee;"><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">For ALTER TABLE with the IGNORE keyword, IGNORE is now part of the information provided to the storage engine. It is up to the storage engine whether to use this when choosing between the in-place or copy algorithm for altering the table. For InnoDB index operations, IGNORE  is not used if the index is unique, so the copy algorithm is used</pre></blockquote><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;详见：<a href="http://bugs.mysql.com/bug.php?id=40344" style="color: #1d58d1; text-decoration: none;">http://bugs.mysql.com/bug.php?id=40344</a></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;</p><h2>3. 解决方案</h2><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">当然解决这个问题的tricky的方法还是有的，也比较直白粗暴。具体如下：</p><blockquote style="border-width: 0px 0px 0px 18px; border-left-color: #cccccc; margin: 0px; padding: 4px; width: 1000.796875px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #eeeeee;"><p style="margin-top: 10px; margin-bottom: 10px;">ALTER TABLE tableA ENGINE MyISAM;<br />ALTER IGNORE TABLE tableA ADD UNIQUE INDEX idx_col1_u (col1)<br />ALTER TABLE table ENGINE InnoDB;</p></blockquote><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;</p><blockquote style="border-width: 0px 0px 0px 18px; border-left-color: #cccccc; margin: 0px; padding: 4px; width: 1000.796875px; font-family: Verdana, Arial, Helvetica, sans-serif; line-height: 25.200000762939453px; background-color: #eeeeee;"><p style="margin-top: 10px; margin-bottom: 10px;"><strong><span style="color: #ff0000;">updated in 2013-09-26:</span></strong></p><p style="margin-top: 10px; margin-bottom: 10px;">@jyzhou 分享提到，可以不用改成MyISAM，而直接使用set old_alter_table = 1; 的方法。具体做法如下：</p><p style="margin-top: 10px; margin-bottom: 10px;"><em>set old_alter_table = 1;</em></p><p style="margin-top: 10px; margin-bottom: 10px;"><em>ALTER IGNORE TABLE tableA ADD UNIQUE INDEX idx_col1_u (col1)&nbsp;</em></p><p style="margin-top: 10px; margin-bottom: 10px;"><em>具体原理：<a href="http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_old_alter_table" style="color: #1d58d1; text-decoration: none;">http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_old_alter_table</a></em></p></blockquote><img src ="http://www.blogjava.net/xiaomage234/aggbug/415533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-07-07 13:52 <a href="http://www.blogjava.net/xiaomage234/archive/2014/07/07/415533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ylbtech-QQ(腾讯)-群空间-数据库设计</title><link>http://www.blogjava.net/xiaomage234/archive/2014/06/19/414934.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 19 Jun 2014 12:02:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/06/19/414934.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/414934.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/06/19/414934.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/414934.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/414934.html</trackback:ping><description><![CDATA[<table border="0" style="border-style: solid; border-color: silver; border-collapse: collapse; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19.5px; width: 1260px; background-color: #ff9900;"><tbody><tr><td style="font-size: 12px; color: #454545; border-style: solid; border-color: silver; border-collapse: collapse; padding: 3px;"><span style="line-height: 1.5; font-size: 16px;"><strong>ylbtech-DatabaseDesgin:ylbtech-QQ(腾讯)-群空间-数据库设计</strong></span></td></tr></tbody></table><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; widows: 2; orphans: 2; background-color: #ffffff;">DatabaseName:QQ-群空间</p><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; widows: 2; orphans: 2; background-color: #ffffff;">Model:群相册、群共享、群论坛、群成员、留言板、公告。6个模块。</p><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; widows: 2; orphans: 2; background-color: #ffffff;">Type:空间-群空间、论坛</p><p style="line-height: 19px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; widows: 2; orphans: 2; background-color: #ffffff;">Url:<a href="http://qun.qzone.qq.com/" style="color: #1a8bc8; text-decoration: none;">http://qun.qzone.qq.com/</a></p><table border="0" style="border-style: solid; border-color: silver; border-collapse: collapse; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19.5px; width: 1260px; background-color: #e5eef7;"><tbody><tr><td colspan="2" style="font-size: 12px; color: #454545; border-style: solid; border-color: silver; border-collapse: collapse; padding: 3px;"><span style="line-height: 1.5; font-size: 14px;"><strong>1.A，数据库关系图(Database Diagram)</strong></span></td></tr></tbody></table><p style="line-height: 19.5px; margin-top: 10px; margin-bottom: 10px; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff;"><img src="http://images.cnblogs.com/cnblogs_com/ylbtech/452776/o_ylbtech_qq_qun-new.jpg" alt="" width="816" height="1113" style="border: 0px;" /></p><table border="0" style="border-style: solid; border-color: silver; border-collapse: collapse; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19.5px; width: 1260px; background-color: #e5eef7;"><tbody><tr><td colspan="2" style="font-size: 12px; color: #454545; border-style: solid; border-color: silver; border-collapse: collapse; padding: 3px;"><span style="line-height: 1.5; font-size: 14px;"><strong>1.B，数据库设计脚本(Database Design Script)-第一版</strong></span></td></tr></tbody></table><div style="margin: 5px 0px;"><span style="font-size: 12px !important;"><img id="code_img_opened_91631742-4dfc-4176-959b-a4d8d7e9abaa" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="" style="border: 0px;" /></span><div id="cnblogs_code_open_91631742-4dfc-4176-959b-a4d8d7e9abaa"><div style="font-size: 12px !important; margin-top: 5px;"><span style="padding-right: 5px;"><a title="复制代码" style="border: none !important;"></a></span></div><div>use master</div><div>go</div><div>-- =============================================</div><div>-- DatabaseName:QQ-群空间</div><div>-- pubdate:16:50 2013-09-26</div><div>-- author:Yuanbo</div><div>-- http://qun.qzone.qq.com/</div><div>-- =============================================</div><div>IF EXISTS (SELECT *&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp;FROM &nbsp; master..sysdatabases&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp;WHERE &nbsp;name = N'qq_qun')</div><div>&nbsp; &nbsp; DROP DATABASE qq_qun</div><div>GO</div><div></div><div>CREATE DATABASE qq_qun</div><div>GO</div><div>use qq_qun</div><div></div><div>go</div><div>-- =============================================</div><div>-- ylb:1,账户表</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table account</div><div>(</div><div>account_id int identity(100000,1) primary key, &nbsp; &nbsp;--编号【PK】</div><div>nickname varchar(20) not null, &nbsp; &nbsp;--昵称</div><div>pwd varchar(20) not null, &nbsp; &nbsp; &nbsp; &nbsp;--密码</div><div>[type] int, &nbsp; &nbsp; &nbsp; &nbsp;--类型 0：QQ号；1：QQ群号</div><div>[enable] bit --状态 0：正常；1：禁用</div><div>)</div><div></div><div>-- =============================================</div><div>-- ylb: 3.1.1 相册表</div><div>-- =============================================</div><div>create table album</div><div>(</div><div>album_id int primary key identity(1,1), &nbsp; &nbsp;--编号【PK】</div><div>album_name varchar(30) not null, &nbsp; &nbsp; &nbsp; &nbsp;--相册名称</div><div>album_desc varchar(80), &nbsp; &nbsp; &nbsp; &nbsp;--相册描述</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; &nbsp;--创建时间</div><div>album_url varchar(100), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--封面图片</div><div></div><div>account_qq int references account(account_id), &nbsp; &nbsp;--相册创建者的QQ号</div><div>account_qun_id int references account(account_id), &nbsp; &nbsp;--QQ群号</div><div>)</div><div>GO</div><div>-- =============================================</div><div>-- ylb: 3.2.1 相片表</div><div>-- =============================================</div><div>create table photo</div><div>(</div><div>photo_id int primary key identity(100,1), &nbsp; &nbsp;--编号【PK】</div><div>photo_name varchar(30) not null, &nbsp; &nbsp; &nbsp; &nbsp;--相片名称</div><div>--photo_desc varchar(100), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--描述</div><div>photo_url varchar(100), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--保存地址</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; &nbsp;--上传时间</div><div></div><div>album_id int references Album(album_id), &nbsp; &nbsp;--相册编号[FK]</div><div>account_qq int references account(account_id), &nbsp; &nbsp;--相册创建者的QQ号</div><div>account_qun_id int references account(account_id), &nbsp; &nbsp;--QQ群号</div><div>)</div><div></div><div>GO</div><div>-- =============================================</div><div>-- ylb: 3.2.2 相片评论表</div><div>-- =============================================</div><div>create table replyphoto</div><div>(</div><div>replyphoto_id int primary key identity(100,1),--编号</div><div>content varchar(200) not null, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--评论内容</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; &nbsp;--评论时间</div><div>baseId int default(0), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--评论级次 0：发表；其他：回复|跟贴</div><div></div><div>photo_id int references photo(photo_id), &nbsp; &nbsp;--照片编号[FK]</div><div>account_qq int references account(account_id), &nbsp; &nbsp;--相册创建者的QQ号</div><div>account_qun_id int references account(account_id), &nbsp; &nbsp;--QQ群号</div><div>)</div><div></div><div></div><div>-- =============================================</div><div>-- ylb:1,群共享</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table share</div><div>(</div><div>[filename] varchar(20), &nbsp; &nbsp;--文件名</div><div>ttl datetime, &nbsp; &nbsp;--有效期【14天】</div><div>filesize int, &nbsp; &nbsp; &nbsp; &nbsp;--文件大小【8.65KB】</div><div>uploaded_author varchar(20), &nbsp; &nbsp;--上传者</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp;--上传时间</div><div>download_cnt int, &nbsp; &nbsp;--下载次数</div><div></div><div>account_id int references account(account_id), --上传者QQ号</div><div>account_qun_id &nbsp; &nbsp;int references account(account_id) --群编号</div><div>)</div><div>go</div><div>-- =============================================</div><div>-- ylb:1,群论坛</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table bbs</div><div>(</div><div>bbs_id int primary key identity(100,1), &nbsp; &nbsp;--编号【PK】</div><div>[subject] varchar(20), &nbsp; &nbsp;--主题</div><div>content varchar(400), &nbsp; &nbsp;--内容</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; &nbsp;--创建时间</div><div></div><div>lock_enable bit, &nbsp; &nbsp;--锁帖|解锁</div><div>stick_enable bit, &nbsp; &nbsp;--0:不顶置；1：顶置</div><div>tags_enable bit, &nbsp; &nbsp;--0:;1:精华</div><div>lightbox_enable bit, --1:高亮</div><div></div><div>account_qq int references account(account_id), &nbsp; &nbsp;--相册创建者的QQ号</div><div>account_qun_id int references account(account_id) &nbsp; &nbsp;--QQ群号</div><div>)</div><div>go</div><div>-- =============================================</div><div>-- ylb:1,回复主题</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table replaybbs</div><div>(</div><div>replaybbs_id int primary key identity(100,1), &nbsp; &nbsp;--编号【PK】</div><div>content varchar(400), &nbsp; &nbsp;--内容</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; &nbsp;--创建时间</div><div></div><div></div><div>bbs_id int references bbs(bbs_id), &nbsp; &nbsp;--主题编号</div><div>account_qq int references account(account_id), &nbsp; &nbsp;--相册创建者的QQ号</div><div>account_qun_id int references account(account_id) &nbsp; &nbsp;--QQ群号</div><div>)</div><div>go</div><div>-- =============================================</div><div>-- ylb:1,群成员</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table member</div><div>(</div><div>member_id int primary key identity(100,1),--编号</div><div>group_nikename varchar(30), &nbsp; &nbsp;--群昵称</div><div>sex varchar(2), &nbsp; &nbsp; &nbsp; &nbsp;--性别</div><div>phone varchar(13), &nbsp; &nbsp;--电话</div><div>email varchar(60), &nbsp; &nbsp;--邮箱</div><div>remark varchar(200),--备注</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; &nbsp;--创建时间</div><div>alow_admin_edit_enable bit, &nbsp; &nbsp;--允许管理员协助修改我的群名片</div><div>[role] int, &nbsp; &nbsp;--角色：群主|管理员|成员【power】</div><div></div><div>account_id int references account(account_id), --上传者QQ号</div><div>account_qun_id &nbsp; &nbsp;int references account(account_id)--群编号</div><div>)</div><div>go</div><div>-- =============================================</div><div>-- ylb:1,留言板</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table messageboard</div><div>(</div><div>messageboard_id int primary key identity(100,1),--编号</div><div>content varchar(30), &nbsp; &nbsp;--内容</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; --创建时间</div><div></div><div>account_id int references account(account_id), --上传者QQ号</div><div>account_qun_id &nbsp; &nbsp;int references account(account_id)--群编号</div><div>)</div><div>go</div><div>-- =============================================</div><div>-- ylb:1,公告</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table notice</div><div>(</div><div>notice_id int primary key identity(100,1),--编号</div><div>content varchar(30), &nbsp; &nbsp;--内容</div><div>pubdate datetime default(getdate()), &nbsp; &nbsp; &nbsp; --创建时间</div><div></div><div>account_id int references account(account_id), --上传者QQ号</div><div>account_qun_id &nbsp; &nbsp;int references account(account_id)--群编号</div><div>)</div><div>go</div><div>-- =============================================</div><div>-- ylb:1,标签【公共】</div><div>--&nbsp;</div><div>-- =============================================</div><div>create table tag</div><div>(</div><div>tag_id uniqueidentifier, &nbsp; &nbsp;--guid</div><div>tag_name varchar(30), &nbsp; &nbsp;--标签名称</div><div>pubdate datetime default(getdate()) &nbsp; &nbsp; &nbsp; --创建时间</div><div>)</div><div>go</div><div>print 'QQ 群空间数据创建成功！'</div><div style="font-size: 12px !important; margin-top: 5px;"><span style="padding-right: 5px; line-height: 1.5 !important;"><a title="复制代码" style="color: #1a8bc8; border: none !important;"></a></span></div></div></div><table border="0" style="border-style: solid; border-color: silver; border-collapse: collapse; color: #4b4b4b; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19.5px; width: 1260px; background-color: #e5eef7;"><tbody><tr><td style="font-size: 12px; color: #454545; border-style: solid; border-color: silver; border-collapse: collapse; padding: 3px;"><span style="line-height: 1.5; font-size: 14px;"><strong>1.C，数据库设计脚本(Database Design Script)-第二版</strong></span></td></tr></tbody></table><img src ="http://www.blogjava.net/xiaomage234/aggbug/414934.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-06-19 20:02 <a href="http://www.blogjava.net/xiaomage234/archive/2014/06/19/414934.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Redis内存使用优化与存储</title><link>http://www.blogjava.net/xiaomage234/archive/2014/05/09/413469.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 09 May 2014 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/05/09/413469.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/413469.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/05/09/413469.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/413469.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/413469.html</trackback:ping><description><![CDATA[<h2>Redis常用数据类型</h2><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">Redis最为常用的数据类型主要有以下五种：</p><ul style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><li>String</li><li>Hash</li><li>List</li><li>Set</li><li>Sorted set</li></ul><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">在具体描述这几种数据类型之前，我们先通过一张图了解下Redis内部内存管理中是如何描述这些不同数据类型的：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><img border="0" alt="" src="http://www.infoq.com/resource/articles/tq-redis-memory-usage-optimization-storage/zh/resources/image1.jpg" style="border: none; max-width: 100%;" /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">首先Redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示：type代表一个value对象具体是何种数据类型，encoding是不同数据类型在redis内部的存储方式，比如：type=string代表value存储的是一个普通字符串，那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的，当然前提是这个字符串本身可以用数值表示，比如:"123" "456"这样的字符串。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">这里需要特殊说明一下vm字段，只有打开了Redis的虚拟内存功能，此字段才会真正的分配内存，该功能默认是关闭状态的，该功能会在后面具体描述。通过上图我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的，当然这些内存管理成本的付出主要也是为了给Redis不同数据类型提供一个统一的管理接口，实际作者也提供了多种方法帮助我们尽量节省内存使用，我们随后会具体讨论。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">下面我们先来逐一的分析下这五种数据类型的使用和内部实现方式：</p><ul style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><li>String<p><strong>常用命令：</strong></p><p>set,get,decr,incr,mget 等。</p><p><strong>应用场景：</strong></p><p>String是最常用的一种数据类型，普通的key/value存储都可以归为此类，这里就不所做解释了。</p><p><strong>实现方式：</strong></p><p>String在redis内部存储默认就是一个字符串，被redisObject所引用，当遇到incr,decr等操作时会转成数值型进行计算，此时redisObject的encoding字段为int。</p></li><li>Hash<p><strong>常用命令：</strong></p><p>hget,hset,hgetall 等。</p><p><strong>应用场景：</strong></p><p>我们简单举个实例来描述下Hash的应用场景，比如我们要存储一个用户信息对象数据，包含以下信息：</p><p>用户ID为查找的key，存储的value用户对象包含姓名，年龄，生日等信息，如果用普通的key/value结构来存储，主要有以下2种存储方式：</p><p><img border="0" alt="" src="http://www.infoq.com/resource/articles/tq-redis-memory-usage-optimization-storage/zh/resources/image2.jpg" style="border: none; max-width: 100%;" /></p><p>第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储，这种方式的缺点是，增加了序列化/反序列化的开销，并且在需要修改其中一项信息时，需要把整个对象取回，并且修改操作需要对并发进行保护，引入CAS等复杂问题。</p><p><img border="0" alt="" src="http://www.infoq.com/resource/articles/tq-redis-memory-usage-optimization-storage/zh/resources/image3.jpg" style="border: none; max-width: 100%;" /></p><p>第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿，用用户ID+对应属性的名称作为唯一标识来取得对应属性的值，虽然省去了序列化开销和并发问题，但是用户ID为重复存储，如果存在大量这样的数据，内存浪费还是非常可观的。</p><p>那么Redis提供的Hash很好的解决了这个问题，Redis的Hash实际是内部存储的Value为一个HashMap，并提供了直接存取这个Map成员的接口，如下图：</p><p><img border="0" alt="" src="http://www.infoq.com/resource/articles/tq-redis-memory-usage-optimization-storage/zh/resources/image4.jpg" style="border: none; max-width: 100%;" /></p><p>也就是说，Key仍然是用户ID, value是一个Map，这个Map的key是成员的属性名，value是属性值，这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了，既不需要重复存储数据，也不会带来序列化和并发修改控制的问题。很好的解决了问题。</p><p>这里同时需要注意，Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多，那么涉及到遍历整个内部Map的操作，由于Redis单线程模型的缘故，这个遍历操作可能会比较耗时，而另其它客户端的请求完全不响应，这点需要格外注意。</p><p><strong>实现方式：</strong></p><p>上面已经说到Redis Hash对应Value内部实际就是一个HashMap，实际这里会有2种不同实现，这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储，而不会采用真正的HashMap结构，对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。</p></li><li>List<p><strong>常用命令：</strong></p><p>lpush,rpush,lpop,rpop,lrange等。</p><p><strong>应用场景：</strong></p><p>Redis list的应用场景非常多，也是Redis最重要的数据结构之一，比如twitter的关注列表，粉丝列表等都可以用Redis的list结构来实现，比较好理解，这里不再重复。</p><p><strong>实现方式：</strong></p><p>Redis list的实现为一个双向链表，即可以支持反向查找和遍历，更方便操作，不过带来了部分额外的内存开销，Redis内部的很多实现，包括发送缓冲队列等也都是用的这个数据结构。</p></li><li>Set<p><strong>常用命令：</strong></p><p>sadd,spop,smembers,sunion 等。</p><p><strong>应用场景：</strong></p><p>Redis set对外提供的功能与list类似是一个列表的功能，特殊之处在于set是可以自动排重的，当你需要存储一个列表数据，又不希望出现重复数据时，set是一个很好的选择，并且set提供了判断某个成员是否在一个set集合内的重要接口，这个也是list所不能提供的。</p><p><strong>实现方式：</strong></p><p>set 的内部实现是一个 value永远为null的HashMap，实际就是通过计算hash的方式来快速排重的，这也是set能提供判断一个成员是否在集合内的原因。</p></li><li>Sorted set<p><strong>常用命令：</strong></p><p>zadd,zrange,zrem,zcard等</p><p><strong>使用场景：</strong></p><p>Redis sorted set的使用场景与set类似，区别是set不是自动有序的，而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序，并且是插入有序的，即自动排序。当你需要一个有序的并且不重复的集合列表，那么可以选择sorted set数据结构，比如twitter 的public timeline可以以发表时间作为score来存储，这样获取时就是自动按时间排好序的。</p><p><strong>实现方式：</strong></p><p>Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序，HashMap里放的是成员到score的映射，而跳跃表里存放的是所有的成员，排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率，并且在实现上比较简单。</p></li></ul><h2><a name="t1" style="color: rgb(51, 102, 153);"></a>常用内存优化手段与参数</h2><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">通过我们上面的一些实现上的分析可以看出redis实际上的内存管理成本非常高，即占用了过多的内存，作者对这点也非常清楚，所以提供了一系列的参数和手段来控制和节省内存，我们分别来讨论下。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">首先最重要的一点是不要开启Redis的VM选项，即虚拟内存功能，这个本来是作为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略，但是其内存管理成本也非常的高，并且我们后续会分析此种持久化策略并不成熟，所以要关闭VM功能，请检查你的redis.conf文件中 vm-enabled 为 no。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">其次最好设置下redis.conf中的maxmemory选项，该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求，该参数能很好的保护好你的Redis不会因为使用了过多的物理内存而导致swap,最终严重影响性能甚至崩溃。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">另外Redis为不同数据类型分别提供了一组参数来控制内存使用，我们在前面详细分析过Redis Hash是value内部为一个HashMap，如果该Map的成员数比较少，则会采用类似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销，这个参数控制对应在redis.conf配置文件中下面2项：</p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #333333; line-height: 26px; background-color: #ffffff;">hash-max-zipmap-entries 64  hash-max-zipmap-value 512  hash-max-zipmap-entries </pre><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">含义是当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储，默认是64,即value内部有64个以下的成员就是使用线性紧凑存储，超过该值自动转成真正的HashMap。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">hash-max-zipmap-value 含义是当 value这个Map内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">以上2个条件任意一个条件超过设置值都会转换成真正的HashMap，也就不会再节省内存了，那么这个值是不是设置的越大越好呢，答案当然是否定的，HashMap的优势就是查找和操作的时间复杂度都是O(1)的，而放弃Hash采用一维存储则是O(n)的时间复杂度，如果</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">成员数量很少，则影响不大，否则会严重影响性能，所以要权衡好这个值的设置，总体上还是最根本的时间成本和空间成本上的权衡。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">同样类似的参数还有：</p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #333333; line-height: 26px; background-color: #ffffff;">list-max-ziplist-entries 512</pre><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">说明：list数据类型多少节点以下会采用去指针的紧凑存储格式。</p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #333333; line-height: 26px; background-color: #ffffff;">list-max-ziplist-value 64 </pre><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">说明：list数据类型节点值大小小于多少字节会采用紧凑存储格式。</p><pre style="white-space: pre-wrap; word-wrap: break-word; color: #333333; line-height: 26px; background-color: #ffffff;">set-max-intset-entries 512 </pre><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">说明：set数据类型内部数据如果全部是数值型，且包含多少节点以下会采用紧凑格式存储。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">最后想说的是Redis内部实现没有对内存分配方面做过多的优化，在一定程度上会存在内存碎片，不过大多数情况下这个不会成为Redis的性能瓶颈，不过如果在Redis内部存储的大部分数据是数值型的话，Redis内部采用了一个shared integer的方式来省去分配内存的开销，即在系统启动时先分配一个从1~n 那么多个数值对象放在一个池子中，如果存储的数据恰好是这个数值范围内的数据，则直接从池子里取出该对象，并且通过引用计数的方式来共享，这样在系统存储了大量数值下，也能一定程度上节省内存并且提高性能，这个参数值n的设置需要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS，该值默认是10000，可以根据自己的需要进行修改，修改后重新编译就可以了。</p><h2><a name="t2" style="color: rgb(51, 102, 153);"></a>Redis的持久化机制</h2><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">Redis由于支持非常丰富的内存数据结构类型，如何把这些复杂的内存组织方式持久化到磁盘上是一个难题，所以Redis的持久化方式与传统数据库的方式有比较多的差别，Redis一共支持四种持久化方式，分别是：</p><ul style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><li>定时快照方式(snapshot)</li><li>基于语句追加文件的方式(aof)</li><li>虚拟内存(vm)</li><li>Diskstore方式</li></ul><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">在设计思路上，前两种是基于全部数据都在内存中，即小数据量下提供磁盘落地功能，而后两种方式则是作者在尝试存储数据超过物理内存时，即大数据量的数据存储，截止到本文，后两种持久化方式仍然是在实验阶段，并且vm方式基本已经被作者放弃，所以实际能在生产环境用的只有前两种，换句话说Redis目前还只能作为小数据量存储（全部数据能够加载在内存中），海量数据存储方面并不是Redis所擅长的领域。下面分别介绍下这几种持久化方式：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>定时快照方式(snapshot)：</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">该持久化方式实际是在Redis内部一个定时器事件，每隔固定时间去检查当前数据发生的改变次数与时间是否满足配置的持久化触发的条件，如果满足则通过操作系统fork调用来创建出一个子进程，这个子进程默认会与父进程共享相同的地址空间，这时就可以通过子进程来遍历整个内存来进行存储操作，而主进程则仍然可以提供服务，当有写入时由操作系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">该持久化的主要缺点是定时快照只是代表一段时间内的内存映像，所以系统重启会丢失上次快照与重启之间所有的数据。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>基于语句追加方式(aof)：</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">aof方式实际类似mysql的基于语句的binlog方式，即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中，也就是说这个log文件就是Redis的持久化数据。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">aof的方式的主要缺点是追加log文件可能导致体积过大，当系统重启恢复数据时如果是aof的方式则加载数据会非常慢，几十G的数据可能需要几小时才能加载完，当然这个耗时并不是因为磁盘文件读取速度慢，而是由于读取的所有命令都要在内存中执行一遍。另外由于每条命令都要写log,所以使用aof的方式，Redis的读写性能也会有所下降。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>虚拟内存方式：</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">虚拟内存方式是Redis来进行用户空间的数据换入换出的一个策略，此种方式在实现的效果上比较差，主要问题是代码复杂，重启慢，复制慢等等，目前已经被作者放弃。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>diskstore方式：</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">diskstore方式是作者放弃了虚拟内存方式后选择的一种新的实现方式，也就是传统的B-tree的方式，目前仍在实验阶段，后续是否可用我们可以拭目以待。</p><h2><a name="t3" style="color: rgb(51, 102, 153);"></a>Redis持久化磁盘IO方式及其带来的问题</h2><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">有Redis线上运维经验的人会发现Redis在物理内存使用比较多，但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题，有人认为是基于快照方式持久化的fork系统调用造成内存占用加倍而导致的，这种观点是不准确的，因为fork 调用的copy-on-write机制是基于操作系统页这个单位的，也就是只有有写入的脏页会被复制，但是一般你的系统不会在短时间内所有的页都发生了写入而导致复制，那么是什么原因导致Redis崩溃的呢？</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">答案是Redis的持久化使用了Buffer IO造成的，所谓Buffer IO是指Redis对持久化文件的写入和读取操作都会使用物理内存的Page Cache,而大多数数据库系统会使用Direct IO来绕过这层Page Cache并自行维护一个数据的Cache，而当Redis的持久化文件过大(尤其是快照文件)，并对其进行读写时，磁盘文件中的数据都会被加载到物理内存中作为操作系统对该文件的一层Cache,而这层Cache的数据与Redis内存中管理的数据实际是重复存储的，虽然内核在物理内存紧张时会做Page Cache的剔除工作，但内核很可能认为某块Page Cache更重要，而让你的进程开始Swap ,这时你的系统就会开始出现不稳定或者崩溃了。我们的经验是当你的Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">下图是Redis在读取或者写入快照文件dump.rdb后的内存数据图：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><img border="0" alt="" src="http://www.infoq.com/resource/articles/tq-redis-memory-usage-optimization-storage/zh/resources/image5.jpg" style="border: none; max-width: 100%; width: 541px; height: 200px;" /></p><h2><a name="t4" style="color: rgb(51, 102, 153);"></a>总结：</h2><ol style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><li>根据业务需要选择合适的数据类型，并为不同的应用场景设置相应的紧凑存储参数。</li><li>当业务场景不需要数据持久化时，关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量。</li><li>如果需要使用持久化，根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一，不要使用虚拟内存以及diskstore方式。</li><li>不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5。</li></ol><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">转载自：<a href="http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage" style="color: #336699; text-decoration: none;">http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage</a></p><img src ="http://www.blogjava.net/xiaomage234/aggbug/413469.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-05-09 17:00 <a href="http://www.blogjava.net/xiaomage234/archive/2014/05/09/413469.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL中间层 Atlas</title><link>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413318.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 06 May 2014 05:33:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413318.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/413318.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413318.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/413318.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/413318.html</trackback:ping><description><![CDATA[<p style="margin: 0px 0px 10px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; font-size: 13px; line-height: 21.333332061767578px; background-color: #ffffff;">from:<span style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px;">http://www.oschina.net/p/atlas/</span></p><p style="margin: 0px 0px 10px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; font-size: 13px; line-height: 21.333332061767578px; background-color: #ffffff;">Atlas是由 Qihoo 360,&nbsp; Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上，修改了大量bug，添加了很多功能特性。目前该项目在360公司内部得到了广泛应用，很多MySQL业务已经接入了Atlas平台，每天承载的读写请求数达几十亿条。</p><p style="margin: 0px 0px 10px; padding: 0px; font-family: 微软雅黑, Verdana, sans-serif, 宋体; font-size: 13px; line-height: 21.333332061767578px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">主要功能：</strong><br style="margin: 0px; padding: 0px;" />* 读写分离<br style="margin: 0px; padding: 0px;" />* 从库负载均衡<br style="margin: 0px; padding: 0px;" />* IP过滤<br style="margin: 0px; padding: 0px;" />* SQL语句黑白名单<br style="margin: 0px; padding: 0px;" />* 自动分表<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" /><strong style="margin: 0px; padding: 0px;">Q &amp; A</strong><br style="margin: 0px; padding: 0px;" />-------------------<br style="margin: 0px; padding: 0px;" />Q: 是否支持多字符集？<br style="margin: 0px; padding: 0px;" />A: 这是我们对原版MySQL-Proxy的第一项改进，符合国情是必须的<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />Q: 自动读写分离挺好，但有时候我写完马上就想读，万一主从同步延迟怎么办?<br style="margin: 0px; padding: 0px;" />A: SQL语句前增加 /*master*/ 就可以将读请求强制发往主库<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />Q: 主库宕机，读操作受影响么？<br style="margin: 0px; padding: 0px;" />A: 在atlas中是不会的! 能问这样的问题, 说明你用过官方的mysql-proxy, 很遗憾官方版本并未解决这个问题<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />Q: 检测后端DB状态会阻塞正常请求么？<br style="margin: 0px; padding: 0px;" />A: 不会, atlas中检测线程是异步进行检测的，即使有db宕机，也不会阻塞主流程。在atlas中没有什么异常会让主流程阻塞! 同上，官方版本也会让你失望<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />Q: 想下线一台DB, 又不想停掉mysql server, 怎么办？<br style="margin: 0px; padding: 0px;" />A: 可以通过管理接口手动上下线后端db, atlas会优先考虑管理员的意愿<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />Q: 想给集群中增加一台DB, 不想影响线上正常访问可以吗？<br style="margin: 0px; padding: 0px;" />A: 通过管理接口可以轻松实现<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />Q: 相比官方mysql-proxy, atlas还有哪些改进？<br style="margin: 0px; padding: 0px;" />A: 这实在是个难以回答的问题，性能，稳定性，可靠性，易维护性，我们做过几十项的改进，下面会尽量列一些较大的改动<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />VS 官方MySQL-Proxy<br style="margin: 0px; padding: 0px;" />-------------------<br style="margin: 0px; padding: 0px;" />1. 将主流程中所有Lua代码改为纯C实现，Lua仅用在管理接口<br style="margin: 0px; padding: 0px;" />2. 重写网络模型、线程模型<br style="margin: 0px; padding: 0px;" />3. 实现了真正意义的连接池<br style="margin: 0px; padding: 0px;" />4. 优化了锁机制，性能提高数十倍<br style="margin: 0px; padding: 0px;" />......<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />附名字来源：<br style="margin: 0px; padding: 0px;" />&nbsp;&nbsp;&nbsp; Atlas，希腊神话中双肩撑天的巨人，普罗米修斯的兄弟，最高大强壮的神之一，因反抗宙斯失败而被罚顶天。我们期望这个系统能够脚踏后端DB，为前端应用撑起一片天。<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />二、配置文件示例<br style="margin: 0px; padding: 0px;" />-------------------<br style="margin: 0px; padding: 0px;" />[mysql-proxy]&nbsp;&nbsp;&nbsp; #不需要改<br style="margin: 0px; padding: 0px;" />plugins = admin, proxy&nbsp;&nbsp;&nbsp; #Atlas加载的模块名称，不需要改<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />admin-username = user&nbsp;&nbsp;&nbsp; #管理接口的用户名<br style="margin: 0px; padding: 0px;" />admin-password = pwd&nbsp;&nbsp;&nbsp; #管理接口的密码<br style="margin: 0px; padding: 0px;" />admin-lua-script = /usr/local/mysql-proxy/lib/mysql-proxy/lua/admin.lua&nbsp;&nbsp;&nbsp; #实现管理接口的Lua脚本所在路径<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />proxy-backend-addresses = 127.0.0.1:3306&nbsp;&nbsp;&nbsp; #Atlas后端连接的MySQL主库的IP和端口，可设置多项，用逗号分隔<br style="margin: 0px; padding: 0px;" />proxy-read-only-backend-addresses = 127.0.0.1:3305@2&nbsp;&nbsp;&nbsp; #Atlas后端连接的MySQL从库的IP和端口，2代表权重，用来作负载均衡，若省略则默认为1，可设置多项，用逗号分隔<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />daemon = false&nbsp;&nbsp;&nbsp; #设置Atlas的运行方式，设为true时为守护进程方式，设为false时为前台方式，一般开发调试时设为false，线上运行时设为true<br style="margin: 0px; padding: 0px;" />keepalive = false&nbsp;&nbsp;&nbsp; #设置Atlas的运行方式，设为true时Atlas会启动两个进程，一个为monitor，一个为worker，monitor在worker意外退出后会自动将其重启，设为false时只有worker，没有monitor，一般开发调试时设为false，线上运行时设为true<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />event-threads = 4&nbsp;&nbsp;&nbsp; #工作线程数，推荐设置与系统的CPU核数相等<br style="margin: 0px; padding: 0px;" />log-level = message&nbsp;&nbsp;&nbsp; #日志级别，分为message、warning、critical、error、debug五个级别<br style="margin: 0px; padding: 0px;" />log-path = /usr/local/mysql-proxy/log&nbsp;&nbsp;&nbsp; #日志存放的路径<br style="margin: 0px; padding: 0px;" />instance = test&nbsp;&nbsp;&nbsp; #实例名称，用于同一台机器上多个Atlas实例间的区分<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />proxy-address = 0.0.0.0:1234&nbsp;&nbsp;&nbsp; #Atlas监听的工作接口IP和端口<br style="margin: 0px; padding: 0px;" />admin-address = 0.0.0.0:2345&nbsp;&nbsp;&nbsp; #Atlas监听的管理接口IP和端口<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />min-idle-connections = 128&nbsp;&nbsp;&nbsp; #连接池的最小空闲连接数，可根据业务请求量大小适当调大或调小<br style="margin: 0px; padding: 0px;" />tables = person.mt.id.3&nbsp;&nbsp;&nbsp; #分表设置，此例中person为库名，mt为表名，id为分表字段，3为子表数量，可设置多项，以逗号分隔<br style="margin: 0px; padding: 0px;" />pwds = user1:+jKsgB3YAG8=, user2:GS+tr4TPgqc=&nbsp;&nbsp;&nbsp; #用户名与其对应的加密过的密码，密码使用加密程序encrypt加密，此设置项用于多个用户名同时访问同一个Atlas实例的情况，若只有一个用户名则不需要设置该项<br style="margin: 0px; padding: 0px;" />charset = utf8&nbsp;&nbsp;&nbsp; #默认字符集，若不设置该项，则默认字符集为latin1<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />三、编译安装<br style="margin: 0px; padding: 0px;" />-------------------<br style="margin: 0px; padding: 0px;" />依赖：glib(2.32.0以上)、libevent(1.4以上)、Lua(5.1以上)、OpenSSL(0.9.8以上)<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />./bootstrap.sh&nbsp;&nbsp;&nbsp; #可能需要修改其中的路径<br style="margin: 0px; padding: 0px;" />make<br style="margin: 0px; padding: 0px;" />sudo make install<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />四、启动与停止<br style="margin: 0px; padding: 0px;" />-------------------<br style="margin: 0px; padding: 0px;" />进入PREFIX/conf目录，编辑instance.conf，此处instance的实际名称应与其中instance设置项相同，其他设置项含义见第二节。<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />启动：<br style="margin: 0px; padding: 0px;" />PREFIX/bin/mysql-proxyd instance start<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />停止：<br style="margin: 0px; padding: 0px;" />PREFIX/bin/mysql-proxyd instance stop<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />重启：<br style="margin: 0px; padding: 0px;" />PREFIX/bin/mysql-proxyd instance restart<br style="margin: 0px; padding: 0px;" /><br style="margin: 0px; padding: 0px;" />查看运行状态：<br style="margin: 0px; padding: 0px;" />PREFIX/bin/mysql-proxyd instance status</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/413318.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-05-06 13:33 <a href="http://www.blogjava.net/xiaomage234/archive/2014/05/06/413318.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mysql 5.5中的半同步复制</title><link>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413317.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 06 May 2014 05:21:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413317.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/413317.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/05/06/413317.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/413317.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/413317.html</trackback:ping><description><![CDATA[<span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">先来看下MYSQL异步复制的概念：&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp; 异步复制：MySQL本身支持单向的、异步的复制。异步复制意味着在把数据从一台机器拷贝到另一台机器时有一个延时 &#8211; 最重要的是这意味着当应用系统的事务提交已经确认时数据并不能在同一时刻拷贝/应用到从机。通常这个延时是由网络带宽、资源可用性和系统负载决定的。然而，使用正确的组件并且调优，复制能做到接近瞬时完成。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp; 当主库有更新的时候，主库会把更新操作的SQL写入二进制日志(Bin log)，并维护一个二进制日志文件的索引，以便于日志文件轮回（Rotate）。在从库启动异步复制的时候，从库会开启两个I/O线程，其中一个线程连接主库，要求主库把二进制日志的变化部分传给从库，并把传回的日志写入本地磁盘。另一个线程则负责读取本地写入的二进制日志，并在本地执行，以反映出这种变化。较老的版本在复制的时候只启用一个I/O线程，实现这两部分的功能。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">同步复制：同步复制可以定义为数据在同一时刻被提交到一台或多台机器，通常这是通过众所周知的&#8220;两阶段提交&#8221;做到的。虽然这确实给你在多系统中保持一致性，但也由于增加了额外的消息交换而造成性能下降。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">使用MyISAM或者InnoDB存储引擎的MySQL本身并不支持同步复制，然而有些技术，例如分布式复制块设备（简称DRBD），可以在下层的文件系统提供同步复制，允许第二个MySQL服务器在主服务器丢失的情况下接管（使用第二服务器的复本）。要了解更多信息，&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp; MYSQL 5。5开始，支持半自动复制。之前版本的MySQL Replication都是异步（asynchronous）的，主库在执行完一些事务后，是不会管备库的进度的。如果备库不幸落后，而更不幸的是主库此时又出现Crash（例如宕机），这时备库中的数据就是不完整的。简而言之，在主库发生故障的时候，我们无法使用备库来继续提供数据一致的服务了。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">Semisynchronous Replication则一定程度上保证提交的事务已经传给了至少一个备库。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">Semi synchronous中，仅仅保证事务的已经传递到备库上，但是并不确保已经在备库上执行完成了。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">此外，还有一种情况会导致主备数据不一致。在某个session中，主库上提交一个事务后，会等待事务传递给至少一个备库，如果在这个等待过程中主库Crash，那么也可能备库和主库不一致，这是很致命的。（在主库恢复后，可以通过参数Rpl_semi_sync_master_no_tx观察）&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp; 如果主备网络故障或者备库挂了，主库在事务提交后等待10秒（rpl_semi_sync_master_timeout的默认值）后，就会继续。这时，主库就会变回原来的异步状态。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; MySQL在加载并开启Semi-sync插件后，每一个事务需等待备库接收日志后才返回给客户端。如果做的是小事务，两台主机的延迟又较小，则Semi-sync可以实现在性能很小损失的情况下的零数据丢失。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp; 主机Crash时的处理&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">备库Crash时，主库会在某次等待超时后，关闭Semi-sync的特性，降级为普通的异步复制，这种情况比较简单。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">主库Crash后，那么可能存在一些事务已经在主库Commit，但是还没有传给任何备库，我们姑且称这类事务为"墙头事务"。"墙头事务"都是没有返回给客户端的，所以发起事务的客户端并不知道这个事务是否已经完成。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">这时，如果客户端不做切换，只是等Crash的主库恢复后，继续在主库进行操作，客户端会发现前面的"墙头事务"都已经完成，可以继续进行后续的业务处理；另一种情况，如果客户端Failover到备库上，客户端会发现前面的&#8220;墙头事务&#8221;都没有成功，则需要重新做这些事务，然后继续进行后续的业务处理。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp; 可以做多个备库，任何一个备库接收完成日志后，主库就可以返回给客户端了。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">网络传输在并发线程较多时，一次可能传输很多日志，事务的平均延迟会降低。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">"墙头事务"在墙头上的时候，是可以被读取的，但是这些事务在上面Failover的场景下，是被认为没有完成的。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp; 默认情况下MySQL的复制是异步的，Master上所有的更新操作写入Binlog之后并不确保所有的更新都被复制到Slave之上。异步操作虽然效率高，但是在Master/Slave出现问题的时候，存在很高数据不同步的风险，甚至可能丢失数据。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">MySQL5.5引入半同步复制功能的目的是为了保证在master出问题的时候，至少有一台Slave的数据是完整的。在超时的情况下也可以临时转入异步复制，保障业务的正常使用，直到一台salve追赶上之后，继续切换到半同步模式。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">Master:&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">INSTALL PLUGIN rpl_semi_sync_master SONAME &#8216;semisync_master.so&#8217;;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">SET GLOBAL rpl_semi_sync_master_enabled=1;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">SET GLOBAL rpl_semi_sync_master_timeout=1000; (1s, default 10s)&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">Slave:&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">INSTALL PLUGIN rpl_semi_sync_slave SONAME &#8216;semisync_slave.so&#8217;;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">SET GLOBAL rpl_semi_sync_slave_enabled=1;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">复制心跳（用户检测复制是否中断）&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">MySQL5.5提供的新的配置master_heartbeat_period，能够在复制停止工作和出现网络中断的时候帮助我们迅速发现问题。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">启用方法：&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">STOP SLAVE;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">CHANGE MASTER TO master_heartbeat_period= milliseconds;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">START SLAVE;&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">Slave自动恢复同步&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">在MySQL5.5版本之前，MySQL Slave实例在异常终止服务之后，可能导致复制中断，并且relay binlog可能损坏，在MySQL再次启动之后并不能正常恢复复制。在MySQL5.5中这一问题得到了解决，MySQL可以自行丢弃顺坏的而未处理的数据，重新从master上获取源数据，进而回复复制。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">跳过指定复制事件&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">在多Master或环形复制的情况下，处于复制链条中间的服务器异常，可以通过&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">CHANGE MASTER TO MASTER_HOST=xxx IGNORE_SERVER_IDS=y&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">跳过出问题的MySQL实例。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">自动转换字段类型&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;" /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25.200000762939453px; background-color: #ffffff;">MySQL5.1在基于语句的复制下，支持部分的字段转换，但是行级的会报错。MySQL5.5语句和行级复制都已支持。还可以通过 SLAVE_TYPE_CONVERSIONS 控制转换的方向。&nbsp;</span><img src ="http://www.blogjava.net/xiaomage234/aggbug/413317.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-05-06 13:21 <a href="http://www.blogjava.net/xiaomage234/archive/2014/05/06/413317.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>faisunSQL自导入数据库备份程序</title><link>http://www.blogjava.net/xiaomage234/archive/2014/04/01/411803.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 01 Apr 2014 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/04/01/411803.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/411803.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/04/01/411803.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/411803.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/411803.html</trackback:ping><description><![CDATA[<span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">功能特点：</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">可以导出导入任意大小的数据库。FaisunSQL 采用分卷导出的方式，将数据库分为多个部份多次导出，因此理论上无论多大的数据库，它都可以胜任。&nbsp;</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">导出的文件本身可以在PHP环境下执行，因此不需要借助其他工具（也不再需要 FaisunSQL程序）。导出的文件为完整的 PHP 文件，直接在服务器中执行即可，使用方便。&nbsp;</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">虽然为多页导出和导入，但其过程会自动运行，且执行速度较快，成功率高。&nbsp;</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">程序编写时考虑了程序的可整合性，因此只要略加修改即可整合到其他程序的后台。&nbsp;</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">导出方式、每个数据文件的大小和数据表等都可以进行设置，个性化强。&nbsp;</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">程序对数据进行了一定的压缩，减少了备份文件的空间占用。&nbsp;</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">对导出的程序进行了加密，安全性高。&nbsp;</span><br style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;" /><span style="font-family: 'Lucida Grande', Helvetica, Arial; font-size: 12px; line-height: 22px; background-color: #ffffff;">导出和导入时基本上按照默认的配置即可，使用方便快捷。&nbsp;</span><img src ="http://www.blogjava.net/xiaomage234/aggbug/411803.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-04-01 15:50 <a href="http://www.blogjava.net/xiaomage234/archive/2014/04/01/411803.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>互联网公司linux运维生产场景常用软件工具一览【转自老男孩】</title><link>http://www.blogjava.net/xiaomage234/archive/2013/11/07/406109.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 07 Nov 2013 08:12:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2013/11/07/406109.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/406109.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2013/11/07/406109.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/406109.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/406109.html</trackback:ping><description><![CDATA[<p style="padding: 0px; margin: 0px; clear: both; height: auto; overflow: hidden; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><span style="padding: 0px; margin: 0px; font-size: 16px;"><strong style="padding: 0px; margin: 0px;">互联网公司linux运维生产场景常用软件工具一览，同时补充了个别常用但不是开源的软件。</strong><br style="padding: 0px; margin: 0px;" /><br style="padding: 0px; margin: 0px;" />下午受邀请参加了一个BBS活动，于是有了下面的内容。<br style="padding: 0px; margin: 0px;" />下面是在linux网站运维方向老男孩最近几年常用的免费的开源软件，临时即兴想起来的，在这里和大家分享，希望给初学者指引一点路。<br style="padding: 0px; margin: 0px;" />linux的世界真的很精彩，还没入门的朋友赶紧进来吧！</span></p><p style="padding: 0px; margin: 0px; clear: both; height: auto; overflow: hidden; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;"><span style="padding: 0px; margin: 0px; font-size: 16px;">操作系统：Centos<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>Freebsd,Ubuntu,Redhatlinux,suselinux<br style="padding: 0px; margin: 0px;" />网站服务：apache<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>nginx<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,lighttpd,php<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>tomcat<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>resin<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>数据库：Mysql<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>PostgreSQL,Mysql-proxy,<span style="padding: 0px; margin: 0px; background-color: #f8f8f8; text-indent: 28px; font-size: 14px; line-height: 25px; font-family: 宋体; color: #333333;">MariaDB</span><br style="padding: 0px; margin: 0px;" />代理相关：lvs,keepalived,haproxy,nginx,apache,heartbeat（此行都是<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;）<br style="padding: 0px; margin: 0px;" /></span>网站缓存：squid<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>nginx<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>varnish<br style="padding: 0px; margin: 0px;" />内存缓存：memcached<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>memcachedb,TokyoTyrant<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>MongoDB,Cassandra<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>redis&#8251;,tair,CouchDB<br style="padding: 0px; margin: 0px;" />存储相关：Nfs<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>Moosefs<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>Hadoop<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>gfs<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>lustre,FastDFS<br style="padding: 0px; margin: 0px;" />版本管理：cvs,svn<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>git<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>监控报警：mboy,mrtg,nagios<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,cacti<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,zabbix,munin<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,hyperic<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>域名解析：bind<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,powerdns,dnsmq<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>同步软件：rsync,inotify,sersync,drbd,csync2,union,lsyncd,scp（此行都是&#8251;）<br style="padding: 0px; margin: 0px;" />分发工具：Secboy<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,expect<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>puppet<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>cfengine<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>ssh+rsync+sersync<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>虚拟软件：xen<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,kvm<br style="padding: 0px; margin: 0px;" />内网软件：iptables<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,zebra<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,iftraf,ntop<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,tc<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,iftop<br style="padding: 0px; margin: 0px;" />邮件软件：qmail<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>posfix<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>sendmail<br style="padding: 0px; margin: 0px;" />远程拨号：openvpn<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,pptp,openswan<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,ipip<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>统一认证：ldap(可结合微软活动目录)<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>队列工具：ActiveMQ<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;,</span>RabbitMQ,MemcacheQ<br style="padding: 0px; margin: 0px;" />打包发布：mvn<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,ants<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>,jenkins<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;<br style="padding: 0px; margin: 0px;" /></span>测试软件：apacheab,smokeping,siege,JMeter,Webbench,LoadRunner（此行都是<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>）<br style="padding: 0px; margin: 0px;" />日志相关：syslog,rsyslog,Awstats<br style="padding: 0px; margin: 0px;" />DB代理：mysql-proxy,amoeba（更多还是程序实现读写分离）<br style="padding: 0px; margin: 0px;" />搜索软件：Sphinx,Xapian（大公司会自己开发类似百度的小规模内部搜索引擎）<br style="padding: 0px; margin: 0px;" /></span><span style="padding: 0px; margin: 0px; font-size: 16px;"><br style="padding: 0px; margin: 0px;" />提示：<br style="padding: 0px; margin: 0px;" />1）以上所有软件都是老男孩用过或测试过的。<br style="padding: 0px; margin: 0px;" />2）带<strong style="padding: 0px; margin: 0px;"><span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span></strong>的为老男孩最近几年用的比较多，可信任使用的。也是近年来linux运维的大众。<br style="padding: 0px; margin: 0px;" />3）有了功能分类和软件名，大家有需求，可以按功能找软件直接G就知道了。</span><br style="padding: 0px; margin: 0px;" /><span style="padding: 0px; margin: 0px; font-size: 16px;">4）学习要有舍有得，什么都抓必然短时间都不会精，希望大家能抓重点，抓精髓，大众软件（带<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>）先熟练了，这是基础加提高，在研究小众软件（不带<span style="padding: 0px; margin: 0px; color: #ff0000;">&#8251;</span>），这是高手之路，最后在研究偏门的，世外高手之路，当然前提是先掌握前面的大众和小众。<br style="padding: 0px; margin: 0px;" />5）当然还有一些没有大众开源的有一些也很棒，如审计堡垒机程序。<br style="padding: 0px; margin: 0px;" /><br style="padding: 0px; margin: 0px;" />还有用的多的，老男孩落下的，大家补充啊。</span></p><p style="padding: 0px; margin: 0px; clear: both; height: auto; overflow: hidden; color: #555555; font-family: 宋体, 'Arial Narrow', arial, serif; line-height: 28px; background-color: #ffffff;">本文出自 &#8220;<a href="http://oldboy.blog.51cto.com/" style="padding: 0px; margin: 0px; color: #015f91; text-decoration: none;">老男孩linux运维</a>&#8221; 博客，请务必保留此出处<a href="http://oldboy.blog.51cto.com/2561410/775056" style="padding: 0px; margin: 0px; color: #015f91; text-decoration: none;">http://oldboy.blog.51cto.com/2561410/775056</a></p><img src ="http://www.blogjava.net/xiaomage234/aggbug/406109.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2013-11-07 16:12 <a href="http://www.blogjava.net/xiaomage234/archive/2013/11/07/406109.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tair资料</title><link>http://www.blogjava.net/xiaomage234/archive/2013/06/25/400934.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 25 Jun 2013 03:58:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2013/06/25/400934.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/400934.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2013/06/25/400934.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/400934.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/400934.html</trackback:ping><description><![CDATA[<h1>1. Tair总述</h1><h2>1.1 系统架构</h2><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">一个Tair集群主要包括3个必选模块：configserver、dataserver和client，一个可选模块：invalidserver。通常情况下，一个集群中包含2台configserver及多台dataServer。两台configserver互为主备并通过维护和dataserver之间的心跳获知集群中存活可用的dataserver，构建数据在集群中的分布信息（对照表）。dataserver负责数据的存储，并按照configserver的指示完成数据的复制和迁移工作。client在启动的时候，从configserver获取数据分布信息，根据数据分布信息和相应的dataserver交互完成用户的请求。invalidserver主要负责对等集群的删除和隐藏操作，保证对等集群的数据一致。</p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">从架构上看，configserver的角色类似于传统应用系统的中心节点，整个集群服务依赖于configserver的正常工作。但实际上相对来说，tair的configserver是非常轻量级的，当正在工作的服务器宕机的时候另外一台会在秒级别时间内自动接管。而且，如果出现两台服务器同时宕机的最恶劣情况，只要应用服务器没有新的变化， tair依然服务正常。而有了configserver这个中心节点，带来的好处就是应用在使用的时候只需要配置configserver的地址（现在可以直接配置Diamond key），而不需要知道内部节点的情况。</p><blockquote style="margin: 0px; padding: 0px; color: #000000; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><p style="margin: 0px; padding: 0px;"><img src="http://code.taobao.org/p/tair/file/2427/structure.jpg" style="border: 0px;"  alt="" /></p></blockquote><h3>1.1.1 ConfigServer的功能</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">1) 通过维护和dataserver心跳来获知集群中存活节点的信息<br />2) 根据存活节点的信息来构建数据在集群中的分布表。<br />3) 提供数据分布表的查询服务。<br />4) 调度dataserver之间的数据迁移、复制。<br /></p><h3>1.1.2 DataServer的功能</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">1) 提供存储引擎<br />2) 接受client的put/get/remove等操作<br />3) 执行数据迁移，复制等<br />4) 插件：在接受请求的时候处理一些自定义功能<br />5) 访问统计<br /></p><h3>1.1.3 InvalidServer的功能</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">1) 接收来自client的invalid/hide等请求后，对属于同一组的集群（双机房独立集群部署方式）做delete/hide操作，保证同一组集群的一致。<br />2) 集群断网之后的，脏数据清理。<br />3) 访问统计。<br /></p><h3>1.1.4 client的功能</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">1) 在应用端提供访问Tair集群的接口。<br />2) 更新并缓存数据分布表和invalidserver地址等。<br />3) LocalCache，避免过热数据访问影响tair集群服务。<br />4) 流控<br /></p><h2>1.2 存储引擎与应用场景</h2><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Tair经过这两年的发展演进，除了应用于cache缓存外，在存储（持久化）上支持的应用需求也越来越广泛。现在主要有mdb，rdb，ldb三种存储引擎。</p><h3>1.2.1 mdb</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">定位于cache缓存，类似于memcache。<br />支持k/v存取和prefix操作<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.2.1.1 mdb的应用场景</strong><br />在实际业务中，大部分当缓存用（后端有DB之类的数据源）。<br />也可用做大访问少量临时数据的存储（例如session登录，防攻击统计等）。<br />集团内绝对多数cache服务都是采用的tair mdb。<br /></p><h3>1.2.2 rdb</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">定位于cache缓存，采用了redis的内存存储结构。<br />支持k/v，list，hash，set，sortedset等数据结构。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.2.2.1 rdb的应用场景</strong><br />适用于需要高速访问某些数据结构的应用，例如SNS中常见的的粉丝存储就可以采用set等结构；或者存储一个商品的多个属性（hashmap）；高效的消息队列（list）等。现在有30个左右的应用在使用rdb服务。</p><h3>1.2.3 ldb</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">定位于高性能存储，并可选择内嵌mdb cache加速，这种情况下cache与持久化存储的数据一致性由tair进行维护。 支持k/v，prefix等数据结构。今后将支持list，hash，set，sortedset等redis支持的数据结构。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.2.3.1 ldb的应用场景</strong><br />存储，里面可以细分如下场景：<br />1) 持续大数据量的存入读取，类似淘宝交易快照。<br />2) 高频度的更新读取，例如计数器，库存等。<br />3) 离线大批量数据导入后做查询。参见fastdump<br />也可以用作cache：<br />数据量大，响应时间敏感度不高的cache需求可以采用。例如天猫实时推荐。<br /></p><h2>1.3 基本概念</h2><h3>1.3.1 configID</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">唯一标识一个tair集群，每个集群都有一个对应的configID，在当前的大部分应用情况下configID是存放在diamond中的，对应了该集群的configserver地址和groupname。业务在初始化tairclient的时候需要配置此ConfigID。</p><h3>1.3.2 namespace</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">又称area， 是tair中分配给应用的一个内存或者持久化存储区域， 可以认为应用的数据存在自己的namespace中。&nbsp;<br />同一集群（同一个configID）中namespace是唯一的。<br />通过引入namespace，我们可以支持不同的应用在同集群中使用相同的key来存放数据，也就是key相同，但内容不会冲突。一个namespace下是如果存放相同的key，那么内容会受到影响，在简单K/V形式下会被覆盖，rdb等带有数据结构的存储引擎内容会根据不同的接口发生不同的变化。<br /></p><h3>1.3.3 quota配额</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">对应了每个namespace储存区的大小限制，超过配额后数据将面临最近最少使用（LRU）的淘汰。<br />持久化引擎（ldb）本身没有配额，ldb由于自带了mdb cache，所以也可以设置cache的配额。超过配额后，在内置的mdb内部进行淘汰。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.3.1 配额是怎样计算的</strong><br />配额大小直接影响数据的命中率和资源利用效率，业务方需要给出一个合适的值，通常的计算方法是评估在保证一定命中率情况下所需要的记录条数，这样配额大小即为： 记录条数 * 平均单条记录大小。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.3.2 管理员如何配置配额</strong><br />单份数据情况下，业务提供的配额就是需要配置在Tair系统中的配额。但对于多备份，在系统中实际计算的配额为： 业务配额 *　备份数<br /></p><h3>1.3.4 expireTime:过期时间</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">expiredTime 是指数据的过期时间，当超过过期时间之后，数据将对应用不可见，这个设置同样影响到应用的命中率和资源利用率。不同的存储引擎有不同的策略清理掉过期的数据。调用接口时，expiredTime单位是秒，可以是相对时间（比如：30s），也可以是绝对时间（比如：当天23时,转换成距1970-1-1 00:00:00的秒数）。 小于0，不更改之前的过期时间<br />如果不传或者传入0，则表示数据永不过期；<br />大于0小于当前时间戳是相对时间过期；<br />大于当前时间戳是绝对时间过期；<br /></p><h3>1.3.5 version</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Tair中存储的每个数据都有版本号，版本号在每次更新后都会递增，相应的，在Tair put接口中也有此version参数，这个参数是为了解决并发更新同一个数据而设置的，类似于乐观锁。<br />很多情况下，更新数据是先get，修改get回来的数据，然后put回系统。如果有多个客户端get到同一份数据，都对其修改并保存，那么先保存的修改就会被后到达的修改覆盖，从而导致数据一致性问题,在大部分情况下应用能够接受，但在少量特殊情况下，这个是我们不希望发生的。<br />比如系统中有一个值&#8221;1&#8221;, 现在A和B客户端同时都取到了这个值。之后A和B客户端都想改动这个值，假设A要改成12，B要改成13，如果不加控制的话，无论A和B谁先更新成功，它的更新都会被后到的更新覆盖。Tair引入的version机制避免了这样的问题。刚刚的例子中，假设A和B同时取到数据，当时版本号是10，A先更新，更新成功后，值为12，版本为11。当B更新的时候，由于其基于的版本号是10，此时服务器会拒绝更新，返回version error，从而避免A的更新被覆盖。B可以选择get新版本的value，然后在其基础上修改，也可以选择强行更新。</p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.5.1 如何获取到当前key的version</strong><br />get接口返回的是DataEntry对象，该对象中包含get到的数据的版本号，可以通过getVersion()接口获得该版本号。在put时，将该版本号作为put的参数即可。 如果不考虑版本问题，则可设置version参数为0，系统将强行覆盖数据，即使版本不一致。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.5.2 version是如何改变的</strong><br />Version改变的逻辑如下：<br />1) 如果put新数据且没有设置版本号，会自动将版本设置成1。<br />2) 如果put是更新老数据且没有版本号，或者put传来的参数版本与当前版本一致，版本号自增1。<br />3) 如果put是更新老数据且传来的参数版本与当前版本不一致，更新失败，返回VersionError。<br />4) put时传入的version参数为0，则强制更新成功，版本号自增1。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.5.3 version返回不一致的时候，该如何处理</strong><br />如果更新所基于的version和系统中当前的版本不一致，则服务器会返回ResultCode.VERERROR。 这时你可以重新get数据，然后在新版本的数据上修改；或者设置version为0重新请求，以达到强制更新的效果，应用可以根据自身对数据一致性的要求在这两种策略间进行选择。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.5.4 version具体使用案例</strong><br />如果应用有10个client会对key进行并发put，那么操作过程如下：&nbsp;<br />1) get key。如果get key成功，则进入步骤2；如果数据不存在，则进入步骤3.&nbsp;<br />2) 在调用put的时候将get key返回的verison重新传入put接口。服务端根据version是否匹配来返回client是否put成功。&nbsp;<br />3) get key数据不存在，则新put数据。此时传入的version必须不是0和1，其他的值都可以（例如1000，要保证所有client是一套逻辑）。因为传入0，tair会认为强制覆盖；而传入1，第一个client写入会成功，但是新写入时服务端的version以0开始计数啊，所以此时version也是1，所以下一个到来的client写入也会成功，这样造成了冲突<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.5.5 version分布式锁</strong><br />Tair中存在该key，则认为该key所代表的锁已被lock；不存在该key，在未加锁。操作过程和上面相似。业务方可以在put的时候增加expire，已避免该锁被长期锁住。<br />当然业务方在选择这种策略的情况下需要考虑并处理Tair宕机带来的锁丢失的情况。<br /></p><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><strong>1.3.5.6 什么情况下需要使用version</strong><br />业务对数据一致性有较高的要求，并且访问并发高，那么通过version可以避免数据的意外结果。<br />如果不关心并发，那么建议不传入version或者直接传0。<br /></p><h2>1.4 集群部署方式</h2><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">Tair通过多种集群部署方式，来满足各类应用的容灾需求。<br />下面所述的双机房可以扩展到多机房，现阶段基本还是采用的双机房。<br />现总共有4种方式：<br />mdb存储引擎适用于双机房单集群单份，双机房独立集群，双机房单集群双份。<br />rdb存储引擎适用于双机房单集群单份。<br />ldb存储引擎适用于双机房主备集群，双机房单集群单份。<br /></p><h3>1.4.1 双机房单集群单份</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">双机房单集群单备份数是指，该Tair集群部署在两个机房中（也就是该Tair集群的机器分别在两个机房）， 数据存储份数为1， 该类型集群部署示意图如下所示。数据服务器（Dataserver）分布在两个机房中，他们都属于同一集群。<br /></p><blockquote style="margin: 0px; padding: 0px; color: #000000; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><p style="margin: 0px; padding: 0px;"><img src="http://code.taobao.org/p/tair/file/2423/1.jpg" style="border: 0px;"  alt="" /></p></blockquote><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">使用场景：<br />1) 后端有无数据源都可。<br />2) 后端有数据源，且更新比例很高的场景。<br />优点：<br />1) 服务器存在于双机房，任一机房宕机保持可用。<br />2) 单份数据，无论应用在哪个机房，看到的都是同一个数据。<br />缺点：<br />1) 应用服务器会跨机房访问。如上图，并假设应用服务器在cm3和cm4，那么cm3的应用服务器也可能调用到cm4的tair机器，cm4的亦然。<br />2) 当一边机房出现故障时，tair中的数据会失效一半（一半这个数值是按两边机房tair机器数相同估计的，如果不相同，则按对应比例估算）<br />该部署方式，应用在删除数据时，只需要调用delete即可，无需调用invalid。当然，调用invalid也可，这种方式下会直接退化到delete。<br /></p><h3>1.4.2 双机房独立集群</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">双机房独立集群是指，在两个机房中同时部署2个独立的Tair集群，这两个集群没有直接关系。下图是一个典型的双机房独立集部署示意图，可以看到，cm3和cm4各有一个完整的tair集群（2个configserver+多个dataserver）。图中还多了一个invalidserver的角色， invalidserver接收客户端的invalid或者hide请求后，会对各机房内的集群进行delete或者hide操作，以此保障Tair中的数据和后端数据源保持一致的。<br /></p><blockquote style="margin: 0px; padding: 0px; color: #000000; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><p style="margin: 0px; padding: 0px;"><img src="http://code.taobao.org/p/tair/file/2424/2.jpg" style="border: 0px;"  alt="" /></p></blockquote><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">适用场景：<br />1) 后端必须要有数据源，否则则退化成单机房集群，Tair集群本身不做同步。<br />2) 读写比不能过小，不然可能会带来Tair命中率降低。例如某个key，在数据库中被频繁更新，那么此时应用必须调用invalid来确保Tair和DB的一致性。此时应用读Tair一直会不命中，导致整体命中率低，可能造成DB压力比较大。 如果依然有疑问的话，请联系 tair答疑。<br />优点：<br />1) 每个机房拥有独立Tair集群，应用在哪个机房就访问相同机房的Tair集群，不会出现跨机房调用和流量。<br />2) 单边机房故障，不会影响业务访问tair命中率。<br />缺点：<br />1) 后端必须要有数据源，也就是这种部署方式下，Tair必然是当作传统意义上的cache存在的。因为Tair mdb集群之间本身不会做数据同步，多集群间一致性保证依赖于后端数据源，如DB。<br />2) 当后端数据源数据发生更新后，业务不能直接把数据put到Tair，而是先需要调用invalid接口来失效这些对等集群中的数据（来保持各Tair集群的数据和后端数据源的一致性）。之后业务可以把数据put到当前Tair集群（注意：只会put到本机房的Tair集群，不会put到对端集群）或者在读Tair时发生not exist的时候从后端数据源取来放入Tair。<br /></p><h3>1.4.3 双机房单集群双份</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">双机房单集群双份，是指一个Tair集群部署在2个机房中，数据保存2份，并且同一数据的2个备份不会放在同一个数据服务器上。根据数据分布策略的不同，还可以将同一份数据的不同备份分布到不同的机房上。该类型的集群部署方式与双机房单集群单份数据的部署方式一样。其不同之处，数据保存份数不一样。该类型集群部署方式示意图如下图所示，数据服务器分别部署在两个不同的机房里，所有的数据服务器都被相同的配置服务器管理，在逻辑上，他们构成一个独立的集群。<br /></p><blockquote style="margin: 0px; padding: 0px; color: #000000; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><p style="margin: 0px; padding: 0px;"><img src="http://code.taobao.org/p/tair/file/2425/3.jpg" style="border: 0px;"  alt="" /></p></blockquote><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">现只有tbsession集群使用了这种部署方式。<br />适用场景：<br />后端无数据源，临时数据的存放，非cache。<br />cache类应用推荐使用双机房独立集群和双机房单集群单份部署方式。<br />优点：<br />1) 数据存放两份，数据安全性有一定保障。但由于存储引擎是mdb，数据存放在内存中，无法绝对保证数据不丢失。<br />2) 当一边机房故障时，另外一边机房依然可以服务，并且数据不丢失。<br />缺点：<br />1) 如果机房间网络出现异常情况，依然有较小几率丢失数据。<br /></p><h3>1.4.4 双机房主备集群</h3><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">这种部署方式中，存在一个主集群和一个备份集群，分别在两个机房中。如下图所示，不妨假设CM3中部署的是主集群，CM4中部署的是备份集群。那么，在正常情况下，用户只使用主集群，读写数据都与主集群交互。主备集群会自动同步数据（不需要业务去更新两边），保证两个机房数据的最终一致性。当一个机房发生故障后，备集群会自动切换成主集群，提供服务，保证系统可用性。<br /></p><blockquote style="margin: 0px; padding: 0px; color: #000000; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;"><p style="margin: 0px; padding: 0px;"><img src="http://code.taobao.org/p/tair/file/2426/4.jpg" style="border: 0px;"  alt="" /></p></blockquote><p style="margin: 0px; padding: 0px; font-family: tahoma, arial, 宋体; font-size: 12px; line-height: 18px; background-color: #ffffff;">适用场景：<br />该方式只在ldb存储引擎中存在，也就是业务将Tair当作最终存储使用。我们会在当前主集群存两份数据，并由Tair异步将数据更新到备集群，确保数据安全和服务可用。<br />优点：<br />1) 数据安全和服务可用性高。<br />2) 用户调用方便，无需考虑多集群间数据一致性的问题。</p><img src ="http://www.blogjava.net/xiaomage234/aggbug/400934.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2013-06-25 11:58 <a href="http://www.blogjava.net/xiaomage234/archive/2013/06/25/400934.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>