<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Tyoung&#39;s Blog</title>
  
  <subtitle>DBA之路</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://db.tyoung.me/"/>
  <updated>2020-04-21T15:15:49.000Z</updated>
  <id>https://db.tyoung.me/</id>
  
  <author>
    <name>Tyoung</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>使用event为Zabbix定期新增与删除分区</title>
    <link href="https://db.tyoung.me/2016/12/create_and_drop_partitions_for_zabbix_tables_on_schedule_by_mysql_event/"/>
    <id>https://db.tyoung.me/2016/12/create_and_drop_partitions_for_zabbix_tables_on_schedule_by_mysql_event/</id>
    <published>2016-12-09T07:08:51.000Z</published>
    <updated>2020-04-21T15:15:49.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h1><p>上一篇文章介绍的<a href="/2016/12/using_tokudb_and_partition_for_zabbix_tables/">Zabbix数据表使用TokuDB引擎及分区表</a>，同时需要每个月为这些表新建一个分区，及删除历史分区。由于MySQL不会自动新建及删除分区，所以需要额外创建一个定时任务，来进行表分区的管理。这里采用MySQL的event来做。</p><p>实现的思路是：定时任务每个月执行一次，在执行的时候，创建下个月的分区，及删除大于保留时长的历史分区，并将操作记录到log表里，便于查询历史操作记录。</p><a id="more"></a><h1 id="实现方式"><a href="#实现方式" class="headerlink" title="实现方式"></a>实现方式</h1><h2 id="相关表结构"><a href="#相关表结构" class="headerlink" title="相关表结构"></a>相关表结构</h2><p>总共创建两个表：</p><ul><li>partition_management：将需要进行分区管理的表信息、历史数据保留时长存储在该表</li><li>partition_logs：记录表分区操作记录</li></ul><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">USE</span> <span class="string">`zabbix`</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- Table: partition_management</span></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> <span class="string">`partition_management`</span>;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`partition_management`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">INT</span>(<span class="number">10</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT <span class="keyword">COMMENT</span> <span class="string">'主键ID'</span>,</span><br><span class="line">  <span class="string">`schema_name`</span> <span class="built_in">VARCHAR</span>(<span class="number">64</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'库名'</span>,</span><br><span class="line">  <span class="string">`table_name`</span> <span class="built_in">VARCHAR</span>(<span class="number">64</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'表名'</span>,</span><br><span class="line">  <span class="string">`keep_period`</span> <span class="built_in">INT</span>(<span class="number">10</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'历史数据保留时长(单位:月)'</span>,</span><br><span class="line">  <span class="string">`is_del_partition`</span> <span class="built_in">TINYINT</span>(<span class="number">4</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span> <span class="keyword">COMMENT</span> <span class="string">'是否删除历史分区(0:不删除, 1:删除)'</span>,</span><br><span class="line">  <span class="string">`create_time`</span> DATETIME <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="keyword">CURRENT_TIMESTAMP</span> <span class="keyword">COMMENT</span> <span class="string">'创建时间'</span>,</span><br><span class="line">  <span class="string">`update_time`</span> DATETIME <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">ON</span> <span class="keyword">UPDATE</span> <span class="keyword">CURRENT_TIMESTAMP</span> <span class="keyword">COMMENT</span> <span class="string">'更新时间'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">UNIQUE</span> <span class="keyword">KEY</span> <span class="string">`un_partition_management_1`</span> (<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">INNODB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8 <span class="keyword">COMMENT</span>=<span class="string">'分区管理表'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- Table: partition_logs</span></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> <span class="string">`partition_logs`</span>;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`partition_logs`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">INT</span>(<span class="number">10</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT <span class="keyword">COMMENT</span> <span class="string">'主键ID'</span>,</span><br><span class="line">  <span class="string">`schema_name`</span> <span class="built_in">VARCHAR</span>(<span class="number">64</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'库名'</span>,</span><br><span class="line">  <span class="string">`table_name`</span> <span class="built_in">VARCHAR</span>(<span class="number">64</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'表名'</span>,</span><br><span class="line">  <span class="string">`maintenance_type`</span> ENUM(<span class="string">'ADD'</span>,<span class="string">'DROP'</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'分区维护类型'</span>,</span><br><span class="line">  <span class="string">`partition_name`</span> <span class="built_in">VARCHAR</span>(<span class="number">200</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'分区名称'</span>,</span><br><span class="line">  <span class="string">`execute_sql`</span> <span class="built_in">VARCHAR</span>(<span class="number">200</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'执行的SQL'</span>,</span><br><span class="line">  <span class="string">`message`</span> <span class="built_in">VARCHAR</span>(<span class="number">100</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">COMMENT</span> <span class="string">'备注信息'</span>,</span><br><span class="line">  <span class="string">`create_time`</span> DATETIME <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="keyword">CURRENT_TIMESTAMP</span> <span class="keyword">COMMENT</span> <span class="string">'创建时间'</span>,</span><br><span class="line">  <span class="string">`update_time`</span> DATETIME <span class="keyword">DEFAULT</span> <span class="literal">NULL</span> <span class="keyword">ON</span> <span class="keyword">UPDATE</span> <span class="keyword">CURRENT_TIMESTAMP</span> <span class="keyword">COMMENT</span> <span class="string">'更新时间'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`ix_partition_logs_1`</span> (<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`partition_name`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`ix_partition_logs_2`</span> (<span class="string">`create_time`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">INNODB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8 <span class="keyword">COMMENT</span>=<span class="string">'表分区定时任务执行记录'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- Initialization data</span></span><br><span class="line"><span class="keyword">INSERT</span>  <span class="keyword">INTO</span> <span class="string">`partition_management`</span>(<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`keep_period`</span>,<span class="string">`is_del_partition`</span>) <span class="keyword">VALUES</span> (<span class="string">'zabbix'</span>,<span class="string">'history'</span>,<span class="number">6</span>,<span class="number">1</span>);</span><br><span class="line"><span class="keyword">INSERT</span>  <span class="keyword">INTO</span> <span class="string">`partition_management`</span>(<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`keep_period`</span>,<span class="string">`is_del_partition`</span>) <span class="keyword">VALUES</span> (<span class="string">'zabbix'</span>,<span class="string">'history_log'</span>,<span class="number">6</span>,<span class="number">1</span>);</span><br><span class="line"><span class="keyword">INSERT</span>  <span class="keyword">INTO</span> <span class="string">`partition_management`</span>(<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`keep_period`</span>,<span class="string">`is_del_partition`</span>) <span class="keyword">VALUES</span> (<span class="string">'zabbix'</span>,<span class="string">'history_str'</span>,<span class="number">6</span>,<span class="number">1</span>);</span><br><span class="line"><span class="keyword">INSERT</span>  <span class="keyword">INTO</span> <span class="string">`partition_management`</span>(<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`keep_period`</span>,<span class="string">`is_del_partition`</span>) <span class="keyword">VALUES</span> (<span class="string">'zabbix'</span>,<span class="string">'history_text'</span>,<span class="number">6</span>,<span class="number">1</span>);</span><br><span class="line"><span class="keyword">INSERT</span>  <span class="keyword">INTO</span> <span class="string">`partition_management`</span>(<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`keep_period`</span>,<span class="string">`is_del_partition`</span>) <span class="keyword">VALUES</span> (<span class="string">'zabbix'</span>,<span class="string">'history_uint'</span>,<span class="number">6</span>,<span class="number">1</span>);</span><br><span class="line"><span class="keyword">INSERT</span>  <span class="keyword">INTO</span> <span class="string">`partition_management`</span>(<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`keep_period`</span>,<span class="string">`is_del_partition`</span>) <span class="keyword">VALUES</span> (<span class="string">'zabbix'</span>,<span class="string">'trends'</span>,<span class="number">24</span>,<span class="number">1</span>);</span><br><span class="line"><span class="keyword">INSERT</span>  <span class="keyword">INTO</span> <span class="string">`partition_management`</span>(<span class="string">`schema_name`</span>,<span class="string">`table_name`</span>,<span class="string">`keep_period`</span>,<span class="string">`is_del_partition`</span>) <span class="keyword">VALUES</span> (<span class="string">'zabbix'</span>,<span class="string">'trends_uint'</span>,<span class="number">24</span>,<span class="number">1</span>);</span><br></pre></td></tr></table></figure><h2 id="相关存储过程"><a href="#相关存储过程" class="headerlink" title="相关存储过程"></a>相关存储过程</h2><p>总共创建以下3个存储过程：</p><ul><li>prc_partition_create：新建表分区</li><li>prc_partition_drop：删除表分区</li><li>prc_partition_maintenance：调用以上两个存储过程，进行表分区的新建与删除</li></ul><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- Procedure: prc_partition_create</span></span><br><span class="line">DELIMITER $$</span><br><span class="line"></span><br><span class="line"><span class="keyword">USE</span> zabbix$$</span><br><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">PROCEDURE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> prc_partition_create$$</span><br><span class="line"><span class="keyword">CREATE</span> DEFINER = <span class="string">'root'</span>@<span class="string">'localhost'</span> <span class="keyword">PROCEDURE</span> prc_partition_create(</span><br><span class="line">    <span class="keyword">IN</span> i_schema_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>)    <span class="comment">-- 分区表所在的库名</span></span><br><span class="line">    ,<span class="keyword">IN</span> i_table_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>)    <span class="comment">-- 分区表名</span></span><br><span class="line">    ,<span class="keyword">IN</span> i_partition_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>)    <span class="comment">-- 当前分区名称</span></span><br><span class="line">    ,<span class="keyword">IN</span> i_partition_value <span class="built_in">VARCHAR</span>(<span class="number">50</span>)    <span class="comment">-- 当前分区值范围</span></span><br><span class="line">)</span><br><span class="line">    <span class="keyword">COMMENT</span> <span class="string">'新建表分区'</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_partition_count <span class="built_in">INT</span> <span class="keyword">DEFAULT</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">DECLARE</span> v_is_maxvalue <span class="built_in">INT</span> <span class="keyword">DEFAULT</span> <span class="number">0</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">SET</span> @maintenance_type = <span class="string">'ADD'</span>;    <span class="comment">-- 进行表分区操作的类型</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">      校验是否存在大于当前分区范围值的分区，</span></span><br><span class="line"><span class="comment">      如果存在，则不创建该分区。</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">    <span class="keyword">SELECT</span> <span class="keyword">COUNT</span>(<span class="number">1</span>) <span class="keyword">INTO</span> v_partition_count</span><br><span class="line">    <span class="keyword">FROM</span> information_schema.partitions</span><br><span class="line">    <span class="keyword">WHERE</span> table_schema = i_schema_name</span><br><span class="line">    <span class="keyword">AND</span> table_name = i_table_name</span><br><span class="line">    <span class="keyword">AND</span> partition_description &lt;&gt; <span class="string">'MAXVALUE'</span></span><br><span class="line">    <span class="keyword">AND</span> partition_description &gt;= i_partition_value;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 创建分区，并将相关信息记录到日志表</span></span><br><span class="line">    IF v_partition_count = 0 THEN</span><br><span class="line">        <span class="keyword">SET</span> @message = <span class="string">''</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="comment">-- 判断是否存在MAXVALUE分区，并使用相应的SQL添加分区</span></span><br><span class="line">        <span class="keyword">SELECT</span> <span class="keyword">COUNT</span>(<span class="number">1</span>) <span class="keyword">INTO</span> v_is_maxvalue</span><br><span class="line">        <span class="keyword">FROM</span> information_schema.partitions</span><br><span class="line">        <span class="keyword">WHERE</span> table_schema = i_schema_name</span><br><span class="line">        <span class="keyword">AND</span> table_name = i_table_name</span><br><span class="line">        <span class="keyword">AND</span> partition_description = <span class="string">'MAXVALUE'</span>;</span><br><span class="line">        </span><br><span class="line">        IF v_is_maxvalue = 1 THEN</span><br><span class="line">            <span class="keyword">SET</span> @execute_sql = <span class="keyword">CONCAT</span>(<span class="string">'ALTER TABLE '</span>, i_schema_name, <span class="string">'.'</span>, i_table_name</span><br><span class="line">                ,<span class="string">' REORGANIZE PARTITION pmore INTO (PARTITION '</span>, i_partition_name, <span class="string">' VALUES LESS THAN ('</span>, i_partition_value, <span class="string">')'</span></span><br><span class="line">                ,<span class="string">', PARTITION pmore VALUES LESS THAN MAXVALUE);'</span>);</span><br><span class="line">        ELSE</span><br><span class="line">            <span class="keyword">SET</span> @execute_sql = <span class="keyword">CONCAT</span>(<span class="string">'ALTER TABLE '</span>, i_schema_name, <span class="string">'.'</span>, i_table_name</span><br><span class="line">                ,<span class="string">' ADD PARTITION (PARTITION '</span>, i_partition_name, <span class="string">' VALUES LESS THAN ('</span>, i_partition_value, <span class="string">'));'</span>);</span><br><span class="line">        <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">INSERT</span> <span class="keyword">INTO</span> partition_logs(schema_name, table_name, partition_name, maintenance_type, execute_sql, message)</span><br><span class="line">            <span class="keyword">VALUES</span>(i_schema_name, i_table_name, i_partition_name, @maintenance_type, @execute_sql, @message);</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">PREPARE</span> execute_sql <span class="keyword">FROM</span> @execute_sql;</span><br><span class="line">        <span class="keyword">EXECUTE</span> execute_sql;</span><br><span class="line">        <span class="keyword">DEALLOCATE</span> <span class="keyword">PREPARE</span> execute_sql;</span><br><span class="line">        </span><br><span class="line">    ELSE</span><br><span class="line">        <span class="keyword">SET</span> @message = <span class="keyword">CONCAT</span>(<span class="string">'Partition value greater than or equal to the given value('</span>, <span class="keyword">IFNULL</span>(i_partition_value, <span class="string">'NULL'</span>), <span class="string">') already exists.'</span>);</span><br><span class="line">        <span class="keyword">SET</span> @execute_sql = <span class="string">''</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">INSERT</span> <span class="keyword">INTO</span> partition_logs(schema_name, table_name, partition_name, maintenance_type, execute_sql, message)</span><br><span class="line">            <span class="keyword">VALUES</span>(i_schema_name, i_table_name, i_partition_name, @maintenance_type, @execute_sql, @message);</span><br><span class="line">    <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">    </span><br><span class="line"><span class="keyword">END</span>$$</span><br><span class="line"></span><br><span class="line">DELIMITER ;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Procedure: prc_partition_drop</span></span><br><span class="line">DELIMITER $$</span><br><span class="line"></span><br><span class="line"><span class="keyword">USE</span> zabbix$$</span><br><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">PROCEDURE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> prc_partition_drop$$</span><br><span class="line"><span class="keyword">CREATE</span> DEFINER = <span class="string">'root'</span>@<span class="string">'localhost'</span> <span class="keyword">PROCEDURE</span> prc_partition_drop(</span><br><span class="line">    <span class="keyword">IN</span> i_schema_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>)    <span class="comment">-- 分区表所在的库名</span></span><br><span class="line">    ,<span class="keyword">IN</span> i_table_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>)    <span class="comment">-- 分区表名</span></span><br><span class="line">    ,<span class="keyword">IN</span> i_del_below_part_value <span class="built_in">VARCHAR</span>(<span class="number">50</span>)    <span class="comment">-- 删除小于此分区值的分区(不包含此分区值)</span></span><br><span class="line">)</span><br><span class="line">    <span class="keyword">COMMENT</span> <span class="string">'删除历史表分区'</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_drop_part_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>);</span><br><span class="line">    <span class="keyword">DECLARE</span> v_done <span class="built_in">INT</span> <span class="keyword">DEFAULT</span> <span class="literal">FALSE</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 获取小于给定分区值的所有分区名称</span></span><br><span class="line">    <span class="keyword">DECLARE</span> cur_get_partition_names <span class="keyword">CURSOR</span> <span class="keyword">FOR</span></span><br><span class="line">        <span class="keyword">SELECT</span> partition_name</span><br><span class="line">        <span class="keyword">FROM</span> information_schema.partitions</span><br><span class="line">        <span class="keyword">WHERE</span> table_schema = i_schema_name</span><br><span class="line">        <span class="keyword">AND</span> table_name = i_table_name</span><br><span class="line">        <span class="keyword">AND</span> partition_description &lt;&gt; <span class="string">'MAXVALUE'</span></span><br><span class="line">        <span class="keyword">AND</span> partition_description &lt; i_del_below_part_value;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">DECLARE</span> CONTINUE <span class="keyword">HANDLER</span> <span class="keyword">FOR</span> <span class="keyword">NOT</span> <span class="keyword">FOUND</span> <span class="keyword">SET</span> v_done = <span class="literal">TRUE</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">SET</span> @maintenance_type = <span class="string">'DROP'</span>;    <span class="comment">-- 进行表分区操作的类型</span></span><br><span class="line">    <span class="keyword">SET</span> @alter_header = <span class="keyword">CONCAT</span>(<span class="string">'ALTER TABLE '</span>, i_schema_name, <span class="string">'.'</span>, i_table_name, <span class="string">' DROP PARTITION '</span>);</span><br><span class="line">    <span class="keyword">SET</span> @drop_partitions = <span class="string">''</span>;</span><br><span class="line">    <span class="keyword">SET</span> @message = <span class="string">''</span>;</span><br><span class="line">    <span class="keyword">SET</span> @execute_sql = <span class="string">''</span>;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 将所有需要删除的分区拼接起来</span></span><br><span class="line">    OPEN cur_get_partition_names;</span><br><span class="line">    loop_1: LOOP</span><br><span class="line">        FETCH cur_get_partition_names INTO v_drop_part_name;</span><br><span class="line">        </span><br><span class="line">        IF v_done THEN</span><br><span class="line">            LEAVE loop_1;</span><br><span class="line">        <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">SET</span> @drop_partitions = <span class="keyword">IF</span>(@drop_partitions = <span class="string">''</span>, v_drop_part_name, <span class="keyword">CONCAT</span>(@drop_partitions, <span class="string">','</span>, v_drop_part_name));</span><br><span class="line">    <span class="keyword">END</span> <span class="keyword">LOOP</span> loop_1;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 删除小于给定分区值的所有分区，并将相关信息记录到日志表</span></span><br><span class="line">    IF @drop_partitions != '' THEN</span><br><span class="line">        <span class="keyword">SET</span> @execute_sql = <span class="keyword">CONCAT</span>(@alter_header, @drop_partitions, <span class="string">';'</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">INSERT</span> <span class="keyword">INTO</span> partition_logs(schema_name, table_name, partition_name, maintenance_type, execute_sql, message)</span><br><span class="line">            <span class="keyword">VALUES</span>(i_schema_name, i_table_name, @drop_partitions, @maintenance_type, @execute_sql, @message);</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">PREPARE</span> execute_sql <span class="keyword">FROM</span> @execute_sql;</span><br><span class="line">        <span class="keyword">EXECUTE</span> execute_sql;</span><br><span class="line">        <span class="keyword">DEALLOCATE</span> <span class="keyword">PREPARE</span> execute_sql;</span><br><span class="line">        </span><br><span class="line">    ELSE</span><br><span class="line">        <span class="keyword">SET</span> @message = <span class="keyword">CONCAT</span>(<span class="string">'No partition less than the given value('</span>, <span class="keyword">IFNULL</span>(i_del_below_part_value, <span class="string">'NULL'</span>), <span class="string">') exists.'</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">INSERT</span> <span class="keyword">INTO</span> partition_logs(schema_name, table_name, partition_name, maintenance_type, execute_sql, message)</span><br><span class="line">            <span class="keyword">VALUES</span>(i_schema_name, i_table_name, @drop_partitions, @maintenance_type, @execute_sql, @message);</span><br><span class="line">    <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">    </span><br><span class="line"><span class="keyword">END</span>$$</span><br><span class="line"></span><br><span class="line">DELIMITER ;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Procedure: prc_partition_maintenance</span></span><br><span class="line">DELIMITER $$</span><br><span class="line"></span><br><span class="line"><span class="keyword">USE</span> zabbix$$</span><br><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">PROCEDURE</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> prc_partition_maintenance$$</span><br><span class="line"><span class="keyword">CREATE</span> DEFINER = <span class="string">'root'</span>@<span class="string">'localhost'</span> <span class="keyword">PROCEDURE</span> prc_partition_maintenance(</span><br><span class="line">    <span class="keyword">IN</span> i_current_year_month <span class="built_in">VARCHAR</span>(<span class="number">10</span>)    <span class="comment">-- 执行添加、删除分区的年月，如：'201611'</span></span><br><span class="line">)</span><br><span class="line">  <span class="comment">-- DETERMINISTIC</span></span><br><span class="line">  <span class="keyword">COMMENT</span> <span class="string">'管理表分区（新建分区及删除历史分区）'</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_schema_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>);    <span class="comment">-- 分区表所在的库名</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_table_name <span class="built_in">VARCHAR</span>(<span class="number">64</span>);    <span class="comment">-- 分区表名</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_partition_type <span class="built_in">VARCHAR</span>(<span class="number">18</span>);    <span class="comment">-- 分区类型</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_keep_period <span class="built_in">INT</span>;    <span class="comment">-- 分区表需要保留的历史数据时长（月）</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_del_partition <span class="built_in">TINYINT</span>;    <span class="comment">-- 是否删除历史分区</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_done <span class="built_in">INT</span> <span class="keyword">DEFAULT</span> <span class="literal">FALSE</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 获取所有的表名，对应的库名，及相应的分区详情</span></span><br><span class="line">    <span class="keyword">DECLARE</span> cur_get_partition_details <span class="keyword">CURSOR</span> <span class="keyword">FOR</span></span><br><span class="line">        <span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> schema_name</span><br><span class="line">            ,table_name</span><br><span class="line">            ,keep_period</span><br><span class="line">            ,is_del_partition</span><br><span class="line">        <span class="keyword">FROM</span> partition_management</span><br><span class="line">        <span class="keyword">ORDER</span> <span class="keyword">BY</span> schema_name, table_name;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">DECLARE</span> CONTINUE <span class="keyword">HANDLER</span> <span class="keyword">FOR</span> <span class="keyword">NOT</span> <span class="keyword">FOUND</span> <span class="keyword">SET</span> v_done = <span class="literal">TRUE</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 如果没有指定执行添加、删除分区的年月，则默认为当前年月</span></span><br><span class="line">    IF i_current_year_month IS NULL OR i_current_year_month = '' THEN</span><br><span class="line">        <span class="keyword">SET</span> i_current_year_month = <span class="keyword">DATE_FORMAT</span>(<span class="keyword">CURRENT_DATE</span>(), <span class="string">'%Y%m'</span>);</span><br><span class="line">    <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">SET</span> @current_part_name = <span class="keyword">CONCAT</span>(<span class="string">'p'</span>, i_current_year_month);</span><br><span class="line">    <span class="keyword">SET</span> @less_than_date = <span class="keyword">CONCAT</span>(<span class="keyword">PERIOD_ADD</span>(i_current_year_month, <span class="number">1</span>), <span class="string">'01'</span>);    <span class="comment">-- 当前分区的值范围对应的日期（1号）</span></span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 读取分区管理表数据，并进行新分区创建和历史分区删除</span></span><br><span class="line">    OPEN cur_get_partition_details;</span><br><span class="line">    </span><br><span class="line">    loop_1: LOOP</span><br><span class="line">        FETCH cur_get_partition_details INTO v_schema_name, v_table_name, v_keep_period, v_del_partition;</span><br><span class="line">        </span><br><span class="line">        IF v_done THEN</span><br><span class="line">            LEAVE loop_1;</span><br><span class="line">        <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">        <span class="comment">-- 获取当前表的分区类型，如果为RANGE，则需要将日期转换为整数（UNIX_TIMESTAMP）。Zabbix表使用的此种分区类型。</span></span><br><span class="line">        <span class="comment">-- 如果分区类型为RANGE COLUMNS，则不需要转换日期格式。日志库的表使用的此种分区类型。</span></span><br><span class="line">        <span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> partition_method <span class="keyword">INTO</span> v_partition_type</span><br><span class="line">        <span class="keyword">FROM</span> information_schema.partitions</span><br><span class="line">        <span class="keyword">WHERE</span> table_schema = v_schema_name</span><br><span class="line">        <span class="keyword">AND</span> table_name = v_table_name;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">SET</span> @del_below_part_date = <span class="keyword">DATE_ADD</span>(@less_than_date, <span class="built_in">INTERVAL</span> -v_keep_period <span class="keyword">MONTH</span>);    <span class="comment">-- 需要删除的分区的值对应的日期（删除小于此值的分区）</span></span><br><span class="line">        </span><br><span class="line">        IF v_partition_type = 'RANGE' THEN</span><br><span class="line">            <span class="keyword">SET</span> @less_than_value = <span class="keyword">UNIX_TIMESTAMP</span>(@less_than_date);    <span class="comment">-- 当前分区的值范围</span></span><br><span class="line">            <span class="keyword">SET</span> @del_below_part_value = <span class="keyword">UNIX_TIMESTAMP</span>(@del_below_part_date);    <span class="comment">-- 删除小于此分区值的分区</span></span><br><span class="line">        ELSEIF v_partition_type = 'RANGE COLUMNS' THEN</span><br><span class="line">            <span class="keyword">SET</span> @less_than_value = <span class="keyword">CONCAT</span>(<span class="string">"'"</span>, <span class="keyword">DATE_FORMAT</span>(@less_than_date, <span class="string">'%Y-%m-%d %H:%i:%s'</span>), <span class="string">"'"</span>);</span><br><span class="line">            <span class="keyword">SET</span> @del_below_part_value = <span class="keyword">CONCAT</span>(<span class="string">"'"</span>, <span class="keyword">DATE_FORMAT</span>(@del_below_part_date, <span class="string">'%Y-%m-%d %H:%i:%s'</span>), <span class="string">"'"</span>);</span><br><span class="line">        <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">        </span><br><span class="line">        </span><br><span class="line">        <span class="comment">-- 新建分区。如果需要删除历史分区，则进行删除</span></span><br><span class="line">        <span class="keyword">CALL</span> prc_partition_create(v_schema_name, v_table_name, @current_part_name, @less_than_value);</span><br><span class="line">        </span><br><span class="line">        IF v_del_partition = 1 THEN</span><br><span class="line">            <span class="keyword">CALL</span> prc_partition_drop(v_schema_name, v_table_name, @del_below_part_value);</span><br><span class="line">        <span class="keyword">END</span> <span class="keyword">IF</span>;</span><br><span class="line">        </span><br><span class="line">    <span class="keyword">END</span> <span class="keyword">LOOP</span> loop_1;</span><br><span class="line">    CLOSE cur_get_partition_details;</span><br><span class="line"><span class="keyword">END</span>$$</span><br><span class="line"></span><br><span class="line">DELIMITER ;</span><br></pre></td></tr></table></figure><h2 id="相关定时任务"><a href="#相关定时任务" class="headerlink" title="相关定时任务"></a>相关定时任务</h2><p>创建一个event(<code>event_partition_maintenance</code>)，每月执行一次，通过调用存储过程<code>prc_partition_maintenance</code>，来达到管理分区的目的。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- Event: event_partition_maintenance</span></span><br><span class="line">DELIMITER $$</span><br><span class="line"></span><br><span class="line"><span class="keyword">USE</span> zabbix$$</span><br><span class="line"></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">EVENT</span> <span class="keyword">IF</span> <span class="keyword">EXISTS</span> event_partition_maintenance$$</span><br><span class="line"><span class="keyword">CREATE</span> DEFINER=<span class="string">'root'</span>@<span class="string">'localhost'</span> <span class="keyword">EVENT</span> event_partition_maintenance</span><br><span class="line">    <span class="keyword">ON</span> SCHEDULE EVERY <span class="number">1</span> <span class="keyword">MONTH</span> STARTS <span class="string">'2016-12-28 20:00:00'</span></span><br><span class="line">    <span class="keyword">ON</span> COMPLETION <span class="keyword">PRESERVE</span></span><br><span class="line">    <span class="keyword">ENABLE</span></span><br><span class="line">    <span class="keyword">COMMENT</span> <span class="string">'定期执行Procedure(prc_partition_maintenance)，管理表分区'</span></span><br><span class="line"><span class="keyword">DO</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line">    <span class="comment">-- 每月执行该任务，创建下一个月的分区表</span></span><br><span class="line">    <span class="keyword">DECLARE</span> v_current_year_month <span class="built_in">VARCHAR</span>(<span class="number">10</span>);</span><br><span class="line">    <span class="keyword">DECLARE</span> v_next_year_month <span class="built_in">VARCHAR</span>(<span class="number">10</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">SET</span> v_current_year_month = <span class="keyword">DATE_FORMAT</span>(<span class="keyword">CURRENT_DATE</span>(), <span class="string">'%Y%m'</span>);</span><br><span class="line">    <span class="keyword">SET</span> v_next_year_month = <span class="keyword">PERIOD_ADD</span>(v_current_year_month, <span class="number">1</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">CALL</span> prc_partition_maintenance(v_next_year_month);</span><br><span class="line"><span class="keyword">END</span>$$</span><br><span class="line"></span><br><span class="line">DELIMITER ;</span><br></pre></td></tr></table></figure><h1 id="脚本共享"><a href="#脚本共享" class="headerlink" title="脚本共享"></a>脚本共享</h1><p>以上所有脚本的完整文件，可以从以下GitHub源获取：<br><a href="https://github.com/tyoungcn/mysql_operations/tree/master/zabbix_auto_partition" target="_blank" rel="noopener">https://github.com/tyoungcn/mysql_operations/tree/master/zabbix_auto_partition</a></p><h1 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h1><ul><li>处理Zabbix历史数据库办法二——使用MySQL表分区：<br><a href="http://john88wang.blog.51cto.com/2165294/1771557" target="_blank" rel="noopener">http://john88wang.blog.51cto.com/2165294/1771557</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;应用场景&quot;&gt;&lt;a href=&quot;#应用场景&quot; class=&quot;headerlink&quot; title=&quot;应用场景&quot;&gt;&lt;/a&gt;应用场景&lt;/h1&gt;&lt;p&gt;上一篇文章介绍的&lt;a href=&quot;/2016/12/using_tokudb_and_partition_for_zabbix_tables/&quot;&gt;Zabbix数据表使用TokuDB引擎及分区表&lt;/a&gt;，同时需要每个月为这些表新建一个分区，及删除历史分区。由于MySQL不会自动新建及删除分区，所以需要额外创建一个定时任务，来进行表分区的管理。这里采用MySQL的event来做。&lt;/p&gt;
&lt;p&gt;实现的思路是：定时任务每个月执行一次，在执行的时候，创建下个月的分区，及删除大于保留时长的历史分区，并将操作记录到log表里，便于查询历史操作记录。&lt;/p&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="MariaDB" scheme="https://db.tyoung.me/tags/MariaDB/"/>
    
      <category term="Zabbix" scheme="https://db.tyoung.me/tags/Zabbix/"/>
    
      <category term="分区表" scheme="https://db.tyoung.me/tags/%E5%88%86%E5%8C%BA%E8%A1%A8/"/>
    
      <category term="event" scheme="https://db.tyoung.me/tags/event/"/>
    
  </entry>
  
  <entry>
    <title>Zabbix数据表使用TokuDB引擎及分区表</title>
    <link href="https://db.tyoung.me/2016/12/using_tokudb_and_partition_for_zabbix_tables/"/>
    <id>https://db.tyoung.me/2016/12/using_tokudb_and_partition_for_zabbix_tables/</id>
    <published>2016-12-09T07:05:44.000Z</published>
    <updated>2020-04-21T15:15:49.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h1><p>线上的Zabbix库的数据表默认使用的是InnoDB存储引擎，随着时间的增长，数据量和占用的存储空间越来越多，单表数据达到了3亿之多。同时，Zabbix的Housekeeping每次在定期清理历史数据时，执行时间都超过了1分多钟，严重影响数据库的性能。</p><p>TokuDB引擎的高压缩比、高INSERT性能，正好适用于Zabbix这种INSERT多、UPDATE少，而且数据量大的环境。所以准备把相关的数据表修改为TokuDB引擎。<br>对Zabbix数据表根据时间字段进行分区后，可以通过删除旧的分区，来达到快速清除历史数据的目的。而且，查询Zabbix最近的数据时，只需要查询单个或几个分区即可，而不需要访问整张表，这样查询性能也得到了提升。</p><a id="more"></a><p>通过查看Zabbix数据库各表数据的存储大小，可以发现，主要是<code>history</code>和<code>trends</code>相关的表所占的存储空间比较大。因此，只对这些表使用TokuDB引擎及分区表。<br>以下是需要分区的表：</p><ul><li><code>history</code></li><li><code>history_log</code></li><li><code>history_str</code></li><li><code>history_text</code></li><li><code>history_uint</code></li><li><code>trends</code></li><li><code>trends_uint</code></li></ul><p>将这些表按照<code>clock</code>时间字段进行分区，每个分区包含一个月的数据。</p><h1 id="系统环境"><a href="#系统环境" class="headerlink" title="系统环境"></a>系统环境</h1><ul><li>OS: CentOS 7</li><li>DB: MariaDB Enterprise 10.0.23</li><li>Zabbix Version: 3.0.1</li></ul><h1 id="开启TokuDB引擎"><a href="#开启TokuDB引擎" class="headerlink" title="开启TokuDB引擎"></a>开启TokuDB引擎</h1><p>关于MariaDB如何开启TokuDB引擎，可参考之前的文章<a href="/2016/11/enable_tokudb_for_mariadb/">《MariaDB开启TokuDB存储引擎》</a>。</p><h1 id="修改存储引擎及开启分区表"><a href="#修改存储引擎及开启分区表" class="headerlink" title="修改存储引擎及开启分区表"></a>修改存储引擎及开启分区表</h1><h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><ol><li>由于TokuDB不支持外键，且InnoDB分区表也不支持外键，所以只要有使用TokuDB引擎或分区表，肯定不支持相关的表的外键。<br>以上7个<code>history</code>和<code>trends</code>相关的表，都没有外键，因此可以使用TokuDB引擎和分区表。</li><li>由于分区表的限制，分区表所使用的列必须是主键和唯一键的一部分或全部。存在以下四种情况：<ol><li>分区表只有主键，没有唯一键。则分区表所使用的列必须是主键的一部分或全部。</li><li>分区表没有主键，只有唯一键。则分区表所使用的列必须是唯一键的一部分或全部。</li><li>分区表既有主键也有唯一键。则分区表所使用的列必须是主键和唯一键的共同部分，如果主键和唯一键没有共同部分，则表无法进行分区。</li><li>分区表既没有主键也没有唯一键。则分区表所使用的列不受上述条件限制。</li></ol></li></ol><p>由于<code>history_log</code>、<code>history_text</code>表结构具有主键和唯一键，且主键和唯一键都不包含分区使用的<code>clock</code>字段，所以需要调整这两个表，以进行表分区。</p><p>表<code>history_log</code>、<code>history_text</code>的原始结构如下：<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SHOW CREATE TABLE history_log\G</span><br><span class="line">*************************** 1. row ***************************</span><br><span class="line">       Table: history_log</span><br><span class="line"><span class="keyword">Create</span> <span class="keyword">Table</span>: <span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`history_log`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">bigint</span>(<span class="number">20</span>) <span class="keyword">unsigned</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">bigint</span>(<span class="number">20</span>) <span class="keyword">unsigned</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`timestamp`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`source`</span> <span class="built_in">varchar</span>(<span class="number">64</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">''</span>,</span><br><span class="line">  <span class="string">`severity`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value`</span> <span class="built_in">text</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`logeventid`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`ns`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">UNIQUE</span> <span class="keyword">KEY</span> <span class="string">`history_log_2`</span> (<span class="string">`itemid`</span>,<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_log_1`</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="number">1</span> <span class="keyword">row</span> <span class="keyword">in</span> <span class="keyword">set</span> (<span class="number">0.00</span> sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; <span class="keyword">SHOW</span> <span class="keyword">CREATE</span> <span class="keyword">TABLE</span> history_text\G</span><br><span class="line">*************************** <span class="number">1.</span> <span class="keyword">row</span> ***************************</span><br><span class="line">       <span class="keyword">Table</span>: history_text</span><br><span class="line"><span class="keyword">Create</span> <span class="keyword">Table</span>: <span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`history_text`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">bigint</span>(<span class="number">20</span>) <span class="keyword">unsigned</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">bigint</span>(<span class="number">20</span>) <span class="keyword">unsigned</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value`</span> <span class="built_in">text</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`ns`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">UNIQUE</span> <span class="keyword">KEY</span> <span class="string">`history_text_2`</span> (<span class="string">`itemid`</span>,<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_text_1`</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="number">1</span> <span class="keyword">row</span> <span class="keyword">in</span> <span class="keyword">set</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure></p><p>表<code>history_log</code>、<code>history_text</code>的主键和索引调整如下：<br><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE history_text DROP PRIMARY KEY, ADD INDEX (id), DROP INDEX history_text_2, ADD INDEX history_text_2 (itemid, id);</span><br><span class="line">mysql&gt; ALTER TABLE history_log DROP PRIMARY KEY, ADD INDEX (id), DROP INDEX history_log_2, ADD INDEX history_log_2 (itemid, id);</span><br></pre></td></tr></table></figure></p><p>由于表的数据量比较多，如果直接在原表上执行以上调整主键和索引的SQL、修改存储引擎、及开启分区表的话，耗时会比较长。这里采取的是先将各表数据分月份导出，然后重建已经修改的分区表结构，再将数据导入到修改后的表里，这样稍微会快些。</p><h2 id="重建表结构"><a href="#重建表结构" class="headerlink" title="重建表结构"></a>重建表结构</h2><p>将原表进行重命名，并使用新的已分区的表结构创建新表。这样可以保证在数据导入导出，修改表结构的时候，不会导致Zabbix丢失这段时间的监控数据。</p><p>重建表结构脚本：<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">USE</span> zabbix;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history</span></span><br><span class="line"><span class="keyword">RENAME</span> <span class="keyword">TABLE</span> history <span class="keyword">TO</span> history_old;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`history`</span> (</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value`</span> <span class="keyword">DOUBLE</span>(<span class="number">16</span>,<span class="number">4</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0.0000'</span>,</span><br><span class="line">  <span class="string">`ns`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_1`</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=TokuDB <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="keyword">PARTITION</span> <span class="keyword">BY</span> <span class="keyword">RANGE</span>(clock)</span><br><span class="line">(<span class="keyword">PARTITION</span> p201609 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201610 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201611 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> pmore <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (MAXVALUE) <span class="keyword">ENGINE</span> = TokuDB</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_log</span></span><br><span class="line"><span class="keyword">RENAME</span> <span class="keyword">TABLE</span> history_log <span class="keyword">TO</span> history_log_old;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`history_log`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`timestamp`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`source`</span> <span class="built_in">VARCHAR</span>(<span class="number">64</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">''</span>,</span><br><span class="line">  <span class="string">`severity`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value`</span> <span class="built_in">TEXT</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`logeventid`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`ns`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_log_2`</span> (<span class="string">`itemid`</span>,<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_log_1`</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=TokuDB <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="keyword">PARTITION</span> <span class="keyword">BY</span> <span class="keyword">RANGE</span>(clock)</span><br><span class="line">(<span class="keyword">PARTITION</span> p201609 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201610 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201611 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> pmore <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (MAXVALUE) <span class="keyword">ENGINE</span> = TokuDB</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_str</span></span><br><span class="line"><span class="keyword">RENAME</span> <span class="keyword">TABLE</span> history_str <span class="keyword">TO</span> history_str_old;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`history_str`</span> (</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value`</span> <span class="built_in">VARCHAR</span>(<span class="number">255</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">''</span>,</span><br><span class="line">  <span class="string">`ns`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_str_1`</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=TokuDB <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="keyword">PARTITION</span> <span class="keyword">BY</span> <span class="keyword">RANGE</span>(clock)</span><br><span class="line">(<span class="keyword">PARTITION</span> p201609 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201610 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201611 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> pmore <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (MAXVALUE) <span class="keyword">ENGINE</span> = TokuDB</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_text</span></span><br><span class="line"><span class="keyword">RENAME</span> <span class="keyword">TABLE</span> history_text <span class="keyword">TO</span> history_text_old;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`history_text`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value`</span> <span class="built_in">TEXT</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`ns`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="keyword">KEY</span> (<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_text_2`</span> (<span class="string">`itemid`</span>,<span class="string">`id`</span>),</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_text_1`</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=TokuDB <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="keyword">PARTITION</span> <span class="keyword">BY</span> <span class="keyword">RANGE</span>(clock)</span><br><span class="line">(<span class="keyword">PARTITION</span> p201609 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201610 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201611 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> pmore <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (MAXVALUE) <span class="keyword">ENGINE</span> = TokuDB</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_uint</span></span><br><span class="line"><span class="keyword">RENAME</span> <span class="keyword">TABLE</span> history_uint <span class="keyword">TO</span> history_uint_old;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`history_uint`</span> (</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`ns`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="keyword">KEY</span> <span class="string">`history_uint_1`</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=TokuDB <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="keyword">PARTITION</span> <span class="keyword">BY</span> <span class="keyword">RANGE</span>(clock)</span><br><span class="line">(<span class="keyword">PARTITION</span> p201609 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201610 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201611 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> pmore <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (MAXVALUE) <span class="keyword">ENGINE</span> = TokuDB</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- trends</span></span><br><span class="line"><span class="keyword">RENAME</span> <span class="keyword">TABLE</span> trends <span class="keyword">TO</span> trends_old;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`trends`</span> (</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`num`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value_min`</span> <span class="keyword">DOUBLE</span>(<span class="number">16</span>,<span class="number">4</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0.0000'</span>,</span><br><span class="line">  <span class="string">`value_avg`</span> <span class="keyword">DOUBLE</span>(<span class="number">16</span>,<span class="number">4</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0.0000'</span>,</span><br><span class="line">  <span class="string">`value_max`</span> <span class="keyword">DOUBLE</span>(<span class="number">16</span>,<span class="number">4</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0.0000'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=TokuDB <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="keyword">PARTITION</span> <span class="keyword">BY</span> <span class="keyword">RANGE</span>(clock)</span><br><span class="line">(<span class="keyword">PARTITION</span> p201609 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201610 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201611 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> pmore <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (MAXVALUE) <span class="keyword">ENGINE</span> = TokuDB</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- trends_uint</span></span><br><span class="line"><span class="keyword">RENAME</span> <span class="keyword">TABLE</span> trends_uint <span class="keyword">TO</span> trends_uint_old;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`trends_uint`</span> (</span><br><span class="line">  <span class="string">`itemid`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`clock`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`num`</span> <span class="built_in">INT</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value_min`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value_avg`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  <span class="string">`value_max`</span> <span class="built_in">BIGINT</span>(<span class="number">20</span>) <span class="keyword">UNSIGNED</span> <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="string">'0'</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`itemid`</span>,<span class="string">`clock`</span>)</span><br><span class="line">) <span class="keyword">ENGINE</span>=TokuDB <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8</span><br><span class="line"><span class="keyword">PARTITION</span> <span class="keyword">BY</span> <span class="keyword">RANGE</span>(clock)</span><br><span class="line">(<span class="keyword">PARTITION</span> p201609 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201610 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> p201611 <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (<span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>)) <span class="keyword">ENGINE</span> = TokuDB,</span><br><span class="line"> <span class="keyword">PARTITION</span> pmore <span class="keyword">VALUES</span> <span class="keyword">LESS</span> <span class="keyword">THAN</span> (MAXVALUE) <span class="keyword">ENGINE</span> = TokuDB</span><br><span class="line">);</span><br></pre></td></tr></table></figure></p><h2 id="导出表数据"><a href="#导出表数据" class="headerlink" title="导出表数据"></a>导出表数据</h2><p>使用<code>SELECT ... INTO OUTFILE ...</code>命令将旧表数据分月份导出到文件。</p><p>数据导出脚本：<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- history</span></span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_old_201609'</span> <span class="keyword">FROM</span> zabbix.history_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-09-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_old_201610'</span> <span class="keyword">FROM</span> zabbix.history_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_old_201611'</span> <span class="keyword">FROM</span> zabbix.history_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_log</span></span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_log_old_201609'</span> <span class="keyword">FROM</span> zabbix.history_log_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-09-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_log_old_201610'</span> <span class="keyword">FROM</span> zabbix.history_log_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_log_old_201611'</span> <span class="keyword">FROM</span> zabbix.history_log_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_str</span></span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_str_old_201609'</span> <span class="keyword">FROM</span> zabbix.history_str_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-09-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_str_old_201610'</span> <span class="keyword">FROM</span> zabbix.history_str_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_str_old_201611'</span> <span class="keyword">FROM</span> zabbix.history_str_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_text</span></span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_text_old_201609'</span> <span class="keyword">FROM</span> zabbix.history_text_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-09-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_text_old_201610'</span> <span class="keyword">FROM</span> zabbix.history_text_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_text_old_201611'</span> <span class="keyword">FROM</span> zabbix.history_text_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_uint</span></span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_uint_old_201609'</span> <span class="keyword">FROM</span> zabbix.history_uint_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-09-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_uint_old_201610'</span> <span class="keyword">FROM</span> zabbix.history_uint_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/history_uint_old_201611'</span> <span class="keyword">FROM</span> zabbix.history_uint_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- trends</span></span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/trends_old_201609'</span> <span class="keyword">FROM</span> zabbix.trends_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-09-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/trends_old_201610'</span> <span class="keyword">FROM</span> zabbix.trends_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/trends_old_201611'</span> <span class="keyword">FROM</span> zabbix.trends_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- trends_uint</span></span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/trends_uint_old_201609'</span> <span class="keyword">FROM</span> zabbix.trends_uint_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-09-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/trends_uint_old_201610'</span> <span class="keyword">FROM</span> zabbix.trends_uint_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-10-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>);</span><br><span class="line"><span class="keyword">SELECT</span> * <span class="keyword">INTO</span> <span class="keyword">OUTFILE</span> <span class="string">'/opt/tmp_zabbix/trends_uint_old_201611'</span> <span class="keyword">FROM</span> zabbix.trends_uint_old <span class="keyword">WHERE</span> clock &gt;= <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-11-01'</span>) <span class="keyword">AND</span> clock &lt; <span class="keyword">UNIX_TIMESTAMP</span>(<span class="string">'2016-12-01'</span>);</span><br></pre></td></tr></table></figure></p><h2 id="导入表数据"><a href="#导入表数据" class="headerlink" title="导入表数据"></a>导入表数据</h2><p>使用<code>LOAD DATA INFILE</code>命令将各表数据分月份导入到新表。<br>由于在导出时，已按照月份将每月数据分别导出到对应的单独文件，所以在导入时可以指定每个数据文件对应的分区，以加快导入速度。</p><p>在导入时，可以临时禁用当前session的binlog，设置<code>sync_binlog = 0</code>，<code>tokudb_commit_sync = 0</code>，以加快导入速度。同时，也可以增大<code>tokudb_lock_timeout</code>的值，以避免在导入本月分区的数据时，Zabbix写入数据等待超时而导致的这段时间的监控数据丢失。具体操作如下：</p><ol><li><p>首先设置以下GLOBAL变量：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SET</span> <span class="keyword">GLOBAL</span> sync_binlog = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">SET</span> <span class="keyword">GLOBAL</span> tokudb_commit_sync = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">SET</span> <span class="keyword">GLOBAL</span> tokudb_lock_timeout = <span class="number">3600000</span>;  <span class="comment">-- 这里设置为1小时</span></span><br></pre></td></tr></table></figure></li><li><p>Kill掉Zabbix的数据库连接，以使刚才设置的全局变量生效；</p></li><li><p>退出当前登录的MySQL会话，重新登录以使刚才设置的全局变量生效。并设置以下SESSION变量，临时禁用binlog：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SET</span> <span class="keyword">SESSION</span> sql_log_bin = <span class="number">0</span>;</span><br></pre></td></tr></table></figure></li><li><p>执行以下数据导入脚本；</p></li><li>导入数据完成后，再恢复设置以上更改的变量值；</li></ol><p>数据导入脚本：<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- history</span></span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_old_201609'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history <span class="keyword">PARTITION</span> (p201609);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_old_201610'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history <span class="keyword">PARTITION</span> (p201610);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_old_201611'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history <span class="keyword">PARTITION</span> (p201611);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_log</span></span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_log_old_201609'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_log <span class="keyword">PARTITION</span> (p201609);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_log_old_201610'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_log <span class="keyword">PARTITION</span> (p201610);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_log_old_201611'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_log <span class="keyword">PARTITION</span> (p201611);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_str</span></span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_str_old_201609'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_str <span class="keyword">PARTITION</span> (p201609);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_str_old_201610'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_str <span class="keyword">PARTITION</span> (p201610);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_str_old_201611'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_str <span class="keyword">PARTITION</span> (p201611);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_text</span></span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_text_old_201609'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_text <span class="keyword">PARTITION</span> (p201609);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_text_old_201610'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_text <span class="keyword">PARTITION</span> (p201610);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_text_old_201611'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_text <span class="keyword">PARTITION</span> (p201611);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- history_uint</span></span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_uint_old_201609'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_uint <span class="keyword">PARTITION</span> (p201609);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_uint_old_201610'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_uint <span class="keyword">PARTITION</span> (p201610);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/history_uint_old_201611'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.history_uint <span class="keyword">PARTITION</span> (p201611);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- trends</span></span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/trends_old_201609'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.trends <span class="keyword">PARTITION</span> (p201609);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/trends_old_201610'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.trends <span class="keyword">PARTITION</span> (p201610);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/trends_old_201611'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.trends <span class="keyword">PARTITION</span> (p201611);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- trends_uint</span></span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/trends_uint_old_201609'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.trends_uint <span class="keyword">PARTITION</span> (p201609);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/trends_uint_old_201610'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.trends_uint <span class="keyword">PARTITION</span> (p201610);</span><br><span class="line"><span class="keyword">LOAD</span> <span class="keyword">DATA</span> <span class="keyword">INFILE</span> <span class="string">'/opt/tmp_zabbix/trends_uint_old_201611'</span> <span class="keyword">INTO</span> <span class="keyword">TABLE</span> zabbix.trends_uint <span class="keyword">PARTITION</span> (p201611);</span><br></pre></td></tr></table></figure></p><h2 id="删除旧表"><a href="#删除旧表" class="headerlink" title="删除旧表"></a>删除旧表</h2><p>将表数据导入到新表后，查看Zabbix数据、图表展示是否正常。如果正常，即可删除旧表。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- truncate table</span></span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> zabbix.history_old;</span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> zabbix.history_log_old;</span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> zabbix.history_str_old;</span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> zabbix.history_text_old;</span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> zabbix.history_uint_old;</span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> zabbix.trends_old;</span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> zabbix.trends_uint_old;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- drop table</span></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> zabbix.history_old;</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> zabbix.history_log_old;</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> zabbix.history_str_old;</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> zabbix.history_text_old;</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> zabbix.history_uint_old;</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> zabbix.trends_old;</span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> zabbix.trends_uint_old;</span><br></pre></td></tr></table></figure><h1 id="禁用Zabbix的Housekeeping"><a href="#禁用Zabbix的Housekeeping" class="headerlink" title="禁用Zabbix的Housekeeping"></a>禁用Zabbix的Housekeeping</h1><p>进行表分区后，通过删除表的历史分区即可清除历史数据，而Zabbix的Housekeeping默认会每隔一小时执行清除历史数据操作，所以需要关闭Housekeeping的定时清理任务。</p><p>进入Zabbix菜单：Administration -&gt; General，选择右上角下拉菜单的“Housekeeping”，取消勾选“History”和“Trends”栏目下的“Enable internal housekeeping”，保存既可。</p><h1 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h1><ul><li>Zabbix官方文档：<br><a href="http://zabbix.org/wiki/Docs/howto/mysql_partition" target="_blank" rel="noopener">http://zabbix.org/wiki/Docs/howto/mysql_partition</a></li><li>处理Zabbix历史数据库办法二——使用MySQL表分区：<br><a href="http://john88wang.blog.51cto.com/2165294/1771557" target="_blank" rel="noopener">http://john88wang.blog.51cto.com/2165294/1771557</a></li><li>迁移Zabbix数据库到TokuDB：<br><a href="http://imysql.com/2014/06/24/migrate-zabbix-db-to-tokudb.shtml" target="_blank" rel="noopener">http://imysql.com/2014/06/24/migrate-zabbix-db-to-tokudb.shtml</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;应用场景&quot;&gt;&lt;a href=&quot;#应用场景&quot; class=&quot;headerlink&quot; title=&quot;应用场景&quot;&gt;&lt;/a&gt;应用场景&lt;/h1&gt;&lt;p&gt;线上的Zabbix库的数据表默认使用的是InnoDB存储引擎，随着时间的增长，数据量和占用的存储空间越来越多，单表数据达到了3亿之多。同时，Zabbix的Housekeeping每次在定期清理历史数据时，执行时间都超过了1分多钟，严重影响数据库的性能。&lt;/p&gt;
&lt;p&gt;TokuDB引擎的高压缩比、高INSERT性能，正好适用于Zabbix这种INSERT多、UPDATE少，而且数据量大的环境。所以准备把相关的数据表修改为TokuDB引擎。&lt;br&gt;对Zabbix数据表根据时间字段进行分区后，可以通过删除旧的分区，来达到快速清除历史数据的目的。而且，查询Zabbix最近的数据时，只需要查询单个或几个分区即可，而不需要访问整张表，这样查询性能也得到了提升。&lt;/p&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="MariaDB" scheme="https://db.tyoung.me/tags/MariaDB/"/>
    
      <category term="TokuDB" scheme="https://db.tyoung.me/tags/TokuDB/"/>
    
      <category term="Zabbix" scheme="https://db.tyoung.me/tags/Zabbix/"/>
    
      <category term="分区表" scheme="https://db.tyoung.me/tags/%E5%88%86%E5%8C%BA%E8%A1%A8/"/>
    
  </entry>
  
  <entry>
    <title>MariaDB开启TokuDB存储引擎</title>
    <link href="https://db.tyoung.me/2016/11/enable_tokudb_for_mariadb/"/>
    <id>https://db.tyoung.me/2016/11/enable_tokudb_for_mariadb/</id>
    <published>2016-11-09T14:26:19.000Z</published>
    <updated>2020-04-21T15:15:49.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h1><p>由于运维及存档分析需要，需要将某些程序、文件调用日志导入到本地MariaDB数据库存储。同时为了节省磁盘空间，决定使用TokuDB存储引擎。</p><p>在MariaDB<code>5.5.34</code>及<code>10.0.6</code>之后的版本已经包含了TokuDB存储引擎，只是默认没有开启，可以根据需要手动进行开启。开启方式也很简单，方法如下文介绍。</p><blockquote><p>MariaDB的二进制包版本中，只有名称中带有<code>glibc_214</code>的压缩包版本，才包含TokuDB引擎。</p></blockquote><a id="more"></a><h1 id="系统环境"><a href="#系统环境" class="headerlink" title="系统环境"></a>系统环境</h1><ul><li>OS: CentOS 7</li><li>DB Version: MariaDB Enterprise 10.0.23</li></ul><h1 id="禁用Transparent-Huge-Pages-THP"><a href="#禁用Transparent-Huge-Pages-THP" class="headerlink" title="禁用Transparent Huge Pages(THP)"></a>禁用Transparent Huge Pages(THP)</h1><p>检查Linux是否开启Transparent Huge Pages。如果有开启，则需要关闭，否则MariaDB无法开启TokuDB引擎。</p><p>原因：</p><blockquote><p>Transparent Huge Pages is a feature in newer linux kernel versions that causes problems for the memory usage tracking calculations in TokuKV and can lead to memory overcommit. If you have this feature enabled, TokuKV will not start, and you should turn it off.</p></blockquote><p>如果没有禁用Transparent Huge Pages，则开启TokuDB后启动MariaDB时，错误日志记录如下，不过mysqld服务仍是可以正常启动的。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">Transparent huge pages are enabled, according to /sys/kernel/mm/transparent_hugepage/enabled</span><br><span class="line">160517 11:40:22 [ERROR] TokuDB: Huge pages are enabled, <span class="built_in">disable</span> them before continuing</span><br><span class="line"></span><br><span class="line">160517 11:40:22 [ERROR] ************************************************************</span><br><span class="line">160517 11:40:22 [ERROR]</span><br><span class="line">160517 11:40:22 [ERROR]                         @@@@@@@@@@@</span><br><span class="line">160517 11:40:22 [ERROR]                       @@<span class="string">'         '</span>@@</span><br><span class="line">160517 11:40:22 [ERROR]                      @@    _     _  @@</span><br><span class="line">160517 11:40:22 [ERROR]                      |    (.)   (.)  |</span><br><span class="line">160517 11:40:22 [ERROR]                      |             ` |</span><br><span class="line">160517 11:40:22 [ERROR]                      |        &gt;    <span class="string">' |</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR]                      |     .----.    |</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR]                      ..   |.----.|  ..</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR]                       ..  '</span>      <span class="string">' ..</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR]                         .._______,.</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR]</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR] TokuDB will not run with transparent huge pages enabled.</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR] Please disable them to continue.</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR] (echo never &gt; /sys/kernel/mm/transparent_hugepage/enabled)</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR]</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR] ************************************************************</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR] Plugin '</span>TokuDB<span class="string">' init function returned error.</span></span><br><span class="line"><span class="string">160517 11:40:22 [ERROR] Plugin '</span>TokuDB<span class="string">' registration as a STORAGE ENGINE failed.</span></span><br></pre></td></tr></table></figure></p><p>未禁用Transparent Huge Pages时，在MySQL命令行，开启TokuDB时，报错信息如下：<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; INSTALL SONAME 'ha_tokudb';</span><br><span class="line">ERROR 1123 (HY000): Can't initialize function 'TokuDB'; Plugin initialization function failed.</span><br></pre></td></tr></table></figure></p><h2 id="检查是否开启Transparent-Huge-Pages"><a href="#检查是否开启Transparent-Huge-Pages" class="headerlink" title="检查是否开启Transparent Huge Pages"></a>检查是否开启Transparent Huge Pages</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; cat /sys/kernel/mm/transparent_hugepage/enabled</span><br></pre></td></tr></table></figure><p>执行以上命令，如果提示路径不存在，或返回以下信息，则表示没有开启Transparent Huge Pages。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">always madvise [never]</span><br></pre></td></tr></table></figure></p><p>如果返回以下信息，则表示已开启Transparent Huge Pages，需要将其禁用。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[always] madvise never</span><br></pre></td></tr></table></figure></p><h2 id="禁用Transparent-Huge-Pages"><a href="#禁用Transparent-Huge-Pages" class="headerlink" title="禁用Transparent Huge Pages"></a>禁用Transparent Huge Pages</h2><h3 id="临时禁用"><a href="#临时禁用" class="headerlink" title="临时禁用"></a>临时禁用</h3><p>以下更改立即生效，在重启后失效：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; <span class="built_in">echo</span> never &gt; /sys/kernel/mm/transparent_hugepage/enabled</span><br></pre></td></tr></table></figure></p><h3 id="永久禁用"><a href="#永久禁用" class="headerlink" title="永久禁用"></a>永久禁用</h3><p>以下更改在重启后生效，且仅限CentOS或RedHat系统。</p><p>在文件<code>/etc/default/grub</code>添加以下内容：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">GRUB_CMDLINE_LINUX_DEFAULT=<span class="string">"transparent_hugepage=never"</span></span><br></pre></td></tr></table></figure></p><p>更新grub (boot loader)：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; grub2-mkconfig -o /boot/grub2/grub.cfg <span class="string">"<span class="variable">$@</span>"</span></span><br></pre></td></tr></table></figure><p>以上是<a href="https://mariadb.com/kb/en/mariadb/enabling-tokudb/#check-for-transparent-hugepage-support-on-linux" target="_blank" rel="noopener">MariaDB官方文档</a>介绍的方法。<br>在公司的测试机上按照以上修改，重启电脑后，Transparent Huge Pages和预料中的一样，被禁用掉了。可是，当我在自己的虚拟机和本地开发机器上，按照以上修改重启系统后，Transparent Huge Pages并没有被禁用掉。如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; cat /sys/kernel/mm/transparent_hugepage/enabled</span><br><span class="line">[always] madvise never</span><br></pre></td></tr></table></figure></p><p>参考<a href="https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/#configure-thp-tuned" target="_blank" rel="noopener">MongoDB官方文档</a>，在禁用Transparent Huge Pages时提到，<strong>如果有在Red Hat或者CentOS(6+)系统使用tuned或ktune，还需要添加额外的配置，以防止THP被重新启用。</strong></p><blockquote><p>tuned和ktune是Red Hat和CentOS系统上的动态调优工具，通过其能够禁用transparent huge pages。如果要通过tuned和ktune来禁用transparent huge pages，需要创建一个配置文件设置THP的值为<code>never</code>。</p></blockquote><p>以下是CentOS 7系统通过添加tuned配置文件来禁用transparent huge pages的方法，CentOS 6系统的配置方法与此有些不同，可以参考<a href="https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/#configure-thp-tuned" target="_blank" rel="noopener">MongoDB官方文档</a>。</p><ol><li><p>新建tuned配置文件夹</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">  shell&gt; mkdir /etc/tuned/no-thp</span><br></pre></td></tr></table></figure></li><li><p>添加配置文件<code>tuned.conf</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">  shell&gt; vim /etc/tuned/no-thp/tuned.conf</span><br></pre></td></tr></table></figure><p>并添加以下配置内容：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">  [main]</span><br><span class="line">  include=virtual-guest</span><br><span class="line">  [vm]</span><br><span class="line">  transparent_hugepages=never</span><br></pre></td></tr></table></figure></li><li><p>使新的配置文件生效</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">  shell&gt; tuned-adm profile no-thp</span><br></pre></td></tr></table></figure></li></ol><p>以上配置添加完成后，再次重启系统，查看及确认Transparent Huge Pages已经被禁用，如下。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; cat /sys/kernel/mm/transparent_hugepage/enabled</span><br><span class="line">always madvise [never]</span><br></pre></td></tr></table></figure></p><h1 id="修改MariaDB配置文件，启用TokuDB"><a href="#修改MariaDB配置文件，启用TokuDB" class="headerlink" title="修改MariaDB配置文件，启用TokuDB"></a>修改MariaDB配置文件，启用TokuDB</h1><p>在配置文件<code>my.cnf</code>中添加以下配置，在每次启动时都启用TokuDB存储引擎，重启生效。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">plugin-load = ha_tokudb</span><br></pre></td></tr></table></figure></p><p>当然，也可以在不重启MariaDB的情况下，执行以下MySQL命令，启用TokuDB存储引擎。<br><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; INSTALL SONAME 'ha_tokudb';</span><br></pre></td></tr></table></figure></p><p>使用<code>SHOW ENGINES</code>命令查看已开启的存储引擎，可以看到TokuDB已启用。<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; show engines;</span><br><span class="line">+<span class="comment">--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+</span></span><br><span class="line">| Engine             | Support | <span class="keyword">Comment</span>                                                                    | Transactions | XA   | Savepoints |</span><br><span class="line">+<span class="comment">--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+</span></span><br><span class="line">| CSV                | YES     | CSV <span class="keyword">storage</span> <span class="keyword">engine</span>                                                         | <span class="keyword">NO</span>           | <span class="keyword">NO</span>   | <span class="keyword">NO</span>         |</span><br><span class="line">| MRG_MyISAM         | YES     | Collection <span class="keyword">of</span> identical MyISAM <span class="keyword">tables</span>                                      | <span class="keyword">NO</span>           | <span class="keyword">NO</span>   | <span class="keyword">NO</span>         |</span><br><span class="line">| <span class="keyword">MEMORY</span>             | YES     | <span class="keyword">Hash</span> based, <span class="keyword">stored</span> <span class="keyword">in</span> <span class="keyword">memory</span>, useful <span class="keyword">for</span> <span class="keyword">temporary</span> <span class="keyword">tables</span>                  | <span class="keyword">NO</span>           | <span class="keyword">NO</span>   | <span class="keyword">NO</span>         |</span><br><span class="line">| BLACKHOLE          | <span class="keyword">NO</span>      | /dev/<span class="literal">null</span> <span class="keyword">storage</span> <span class="keyword">engine</span> (anything you write <span class="keyword">to</span> it disappears)             | <span class="literal">NULL</span>         | <span class="literal">NULL</span> | <span class="literal">NULL</span>       |</span><br><span class="line">| MyISAM             | YES     | MyISAM <span class="keyword">storage</span> <span class="keyword">engine</span>                                                      | <span class="keyword">NO</span>           | <span class="keyword">NO</span>   | <span class="keyword">NO</span>         |</span><br><span class="line">| TokuDB             | YES     | Percona TokuDB <span class="keyword">Storage</span> <span class="keyword">Engine</span> <span class="keyword">with</span> Fractal Tree(tm) Technology             | YES          | YES  | YES        |</span><br><span class="line">| <span class="keyword">InnoDB</span>             | <span class="keyword">DEFAULT</span> | Percona-XtraDB, Supports transactions, <span class="keyword">row</span>-<span class="keyword">level</span> locking, <span class="keyword">and</span> <span class="keyword">foreign</span> <span class="keyword">keys</span> | YES          | YES  | YES        |</span><br><span class="line">| <span class="keyword">ARCHIVE</span>            | <span class="keyword">NO</span>      | <span class="keyword">Archive</span> <span class="keyword">storage</span> <span class="keyword">engine</span>                                                     | <span class="literal">NULL</span>         | <span class="literal">NULL</span> | <span class="literal">NULL</span>       |</span><br><span class="line">| FEDERATED          | YES     | FederatedX <span class="keyword">pluggable</span> <span class="keyword">storage</span> <span class="keyword">engine</span>                                        | YES          | <span class="keyword">NO</span>   | YES        |</span><br><span class="line">| PERFORMANCE_SCHEMA | YES     | <span class="keyword">Performance</span> <span class="keyword">Schema</span>                                                         | <span class="keyword">NO</span>           | <span class="keyword">NO</span>   | <span class="keyword">NO</span>         |</span><br><span class="line">| Aria               | YES     | Crash-<span class="keyword">safe</span> <span class="keyword">tables</span> <span class="keyword">with</span> MyISAM heritage                                     | <span class="keyword">NO</span>           | <span class="keyword">NO</span>   | <span class="keyword">NO</span>         |</span><br><span class="line">+<span class="comment">--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+</span></span><br><span class="line"><span class="number">11</span> <span class="keyword">rows</span> <span class="keyword">in</span> <span class="keyword">set</span> (<span class="number">0.02</span> sec)</span><br></pre></td></tr></table></figure></p><h1 id="相关参数配置"><a href="#相关参数配置" class="headerlink" title="相关参数配置"></a>相关参数配置</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[mysqld]</span><br><span class="line"><span class="comment"># TokuDB</span></span><br><span class="line">plugin-load = ha_tokudb</span><br><span class="line">tokudb_cache_size = 4G</span><br><span class="line">tokudb_data_dir = /data/mysql/mysql3306/tokudb_data</span><br><span class="line">tokudb_log_dir = /data/mysql/mysql3306/logs</span><br><span class="line">tokudb_tmp_dir = /data/mysql/mysql3306/tmp</span><br><span class="line">tokudb_pk_insert_mode = 2</span><br></pre></td></tr></table></figure><p>各参数说明：</p><ul><li>tokudb_cache_size<br>默认情况下，TokuDB分配50%的系统内存。</li><li>tokudb_data_dir<br>指定TokuDB数据的存储位置。默认为空，使用<code>datadir</code>定义的路径。</li><li>tokudb_log_dir<br>指定TokuDB日志的存储位置。默认为空，使用<code>datadir</code>定义的路径。</li><li>tokudb_tmp_dir<br>TokuDB批量导入数据时，临时文件的存储位置。TokuDB在使用LOAD DATA导入数据的时候会通过临时表(可能会很大)来完成。<br>默认为空，使用<code>datadir</code>定义的路径。</li><li>tokudb_pk_insert_mode<br>主键写入的模式，只有值为<code>2</code>时，才支持RBR。</li></ul><h1 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h1><h2 id="变量toukudb-cache-size的值大小设置"><a href="#变量toukudb-cache-size的值大小设置" class="headerlink" title="变量toukudb_cache_size的值大小设置"></a>变量<code>toukudb_cache_size</code>的值大小设置</h2><p>TokuDB默认分配50%的系统内存，该值由变量<code>toukudb_cache_size</code>控制，类似于InnoDB的<code>innodb_buffer_pool_size</code>。<br>如果同时使用InnoDB和TokuDB存储引擎，需适当调整这两个变量的值，以免超过系统内存，造成swap交换。</p><p><code>toukudb_cache_size</code>为只读变量，修改后重启生效。</p><h2 id="变量tokudb-pk-insert-mode对复制的影响"><a href="#变量tokudb-pk-insert-mode对复制的影响" class="headerlink" title="变量tokudb_pk_insert_mode对复制的影响"></a>变量<code>tokudb_pk_insert_mode</code>对复制的影响</h2><p>当变量<code>tokudb_pk_insert_mode</code>为默认值（<code>1</code>）或<code>0</code>时，基于ROW格式的复制（RBR）将无法运行，需要将该变量的值修改为<code>2</code>，RBR才能正常运行。</p><p>变量<code>tokudb_pk_insert_mode</code>的说明如下：</p><blockquote><ul><li><strong>Description:</strong> Mode for primary key inserts using either <code>REPLACE INTO</code> or <code>INSERT IGNORE</code> on tables with no secondary index, or where all columns in the secondary index are in the primary key. For example <code>PRIMARY KEY (a,b,c), key (b,c)</code><ul><li><code>0</code>: Fast inserts. Triggers may not work, and row-based replication will not work.</li><li><code>1</code>: Fast inserts if no triggers are defined, otherwise inserts may be slow. Row-based replication will not work.</li><li><code>2</code>: Slow inserts. Triggers and row-based replication work normally.</li></ul></li><li><strong>Scope:</strong> Global, Session</li><li><strong>Dynamic:</strong> Yes</li><li><strong>Data Type:</strong> enumerated</li><li><strong>Default Value:</strong> <code>1</code></li><li><strong>Valid Values:</strong> <code>0</code>, <code>1</code>, <code>2</code></li></ul></blockquote><h1 id="数据占用存储空间对比"><a href="#数据占用存储空间对比" class="headerlink" title="数据占用存储空间对比"></a>数据占用存储空间对比</h1><p>使用MyISAM引擎存储日志数据时，表数据大小是<code>13G</code>；更改为TokuDB引擎后，使用默认的压缩方式（tokudb_zlib），表数据大小是<code>1.6G</code>。可以看出，TokuDB相对于MyISAM，数据压缩比达到8倍之多。</p><h1 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h1><ol><li>MariaDB官方文档-Enabling TokuDB：<br><a href="https://mariadb.com/kb/en/mariadb/enabling-tokudb" target="_blank" rel="noopener">https://mariadb.com/kb/en/mariadb/enabling-tokudb</a></li><li>MongoDB官方文档-Disable Transparent Huge Pages(THP)：<br><a href="https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/" target="_blank" rel="noopener">https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/</a></li><li>TokuDB使用简单说明：<br><a href="http://highdb.com/tokudb-特性概览/" target="_blank" rel="noopener">http://highdb.com/tokudb-特性概览/</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;应用场景&quot;&gt;&lt;a href=&quot;#应用场景&quot; class=&quot;headerlink&quot; title=&quot;应用场景&quot;&gt;&lt;/a&gt;应用场景&lt;/h1&gt;&lt;p&gt;由于运维及存档分析需要，需要将某些程序、文件调用日志导入到本地MariaDB数据库存储。同时为了节省磁盘空间，决定使用TokuDB存储引擎。&lt;/p&gt;
&lt;p&gt;在MariaDB&lt;code&gt;5.5.34&lt;/code&gt;及&lt;code&gt;10.0.6&lt;/code&gt;之后的版本已经包含了TokuDB存储引擎，只是默认没有开启，可以根据需要手动进行开启。开启方式也很简单，方法如下文介绍。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;MariaDB的二进制包版本中，只有名称中带有&lt;code&gt;glibc_214&lt;/code&gt;的压缩包版本，才包含TokuDB引擎。&lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MariaDB" scheme="https://db.tyoung.me/tags/MariaDB/"/>
    
      <category term="TokuDB" scheme="https://db.tyoung.me/tags/TokuDB/"/>
    
  </entry>
  
  <entry>
    <title>pt-table-checksum使用dsn方式连接检测从库</title>
    <link href="https://db.tyoung.me/2016/09/use_dsn_method_to_connect_and_check_replicas_when_using_pt-table-checksum/"/>
    <id>https://db.tyoung.me/2016/09/use_dsn_method_to_connect_and_check_replicas_when_using_pt-table-checksum/</id>
    <published>2016-09-21T17:44:22.000Z</published>
    <updated>2020-04-21T15:15:49.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="问题场景"><a href="#问题场景" class="headerlink" title="问题场景"></a>问题场景</h1><h2 id="系统环境"><a href="#系统环境" class="headerlink" title="系统环境"></a>系统环境</h2><p>测试环境：</p><ul><li>OS: CentOS 7</li><li>DB Version: MariaDB 10.0.23</li><li>PT Version: pt-table-checksum 2.2.18</li><li>主从环境<ul><li>Master: 192.168.0.17:53309</li><li>Slave: 192.168.0.18:3309</li></ul></li></ul><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>在使用pt-table-checksum配置主从校验的时候，本地和生产环境都可以正常校验，而在测试环境校验的时候，却输出以下警告信息：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Cannot connect to h=192.168.0.18,p=...,u=pt_table_check</span><br><span class="line">Diffs cannot be detected because no slaves were found.  Please <span class="built_in">read</span> the --recursion-method documentation <span class="keyword">for</span> information.</span><br></pre></td></tr></table></figure></p><p>pt-table-checksum无法连接从库。<br>由于没有发现从库，数据校验时无法实时检测从库与主库的数据是否一致（<code>DIFFS</code>列始终为<code>0</code>），需要通过<code>--recursion-method</code>选项指定其他的方式来搜索、连接从库（此处<code>--recursion-method</code>使用的是默认值<code>processlist,hosts</code>）。</p><a id="more"></a><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>执行的详细命令及输出如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; ./bin/pt-table-checksum --socket=/var/lib/mysql/mysql.sock --user=pt_table_check --password=<span class="string">'checksum123'</span> --tables=road_to_dba.test1 --replicate=percona_schema.checksums --no-check-binlog-format --no-check-replication-filters</span><br><span class="line"></span><br><span class="line">Cannot connect to h=192.168.0.18,p=...,u=pt_table_check</span><br><span class="line">Diffs cannot be detected because no slaves were found.  Please <span class="built_in">read</span> the --recursion-method documentation <span class="keyword">for</span> information.</span><br><span class="line">            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE</span><br><span class="line">09-21T20:57:37      0      0      972       1       0   0.033 road_to_dba.test1</span><br></pre></td></tr></table></figure></p><p>虽然在校验时pt-table-checksum没有连接到从库，但校验能够在主库正常运行，而且能够通过复制传递到从库。校验完成后，在从库也可以通过checksums表查询到数据校验不一致的表信息。</p><p>本着严(qiang)谨(po)的(zheng)态度，决定还是对于上述警告信息彻底解决掉。经过分析，具体<strong>原因如下</strong>：</p><ul><li>默认情况下，pt-table-checksum使用的从库连接参数，是从主库的连接参数继承而来的，包括用户名（<code>--user</code>）、密码（<code>--password</code>）、端口（<code>--port</code>）等。</li><li>在本次校验中，没有显式指定从库的用户名（<code>--slave-user</code>），密码（<code>--slave-password</code>），及端口。</li><li>所以，在没有显式指定从库的连接参数的情况下，<strong>默认是，主库和从库的用户名、密码、端口是相同的</strong>；但是在我的<strong>测试环境中，主从环境的端口是不同的</strong>。所以导致pt-table-checksum虽然搜索到了从库，但是无法连接从库（<code>Cannot connect to h=192.168.0.18,p=...,u=pt_table_check</code>），紧接着报没有发现从库的错误。</li></ul><p>由于pt-table-checksum没有参数可以用来指定从库的端口，所以使用dsn方式来指定从库的连接信息（<code>--recursion-method dsn=D=percona,t=dsns,h=host,P=3309,u=username,p=passwd</code>）。</p><h1 id="dsn是什么"><a href="#dsn是什么" class="headerlink" title="dsn是什么"></a>dsn是什么</h1><p>首先介绍俩名词：</p><ul><li>dsn方法：<code>dsn</code>是参数<code>--recursion-method</code>的一个<strong>参数值</strong>。注意是dsn，不是dns…</li><li>DSN：<code>DSN</code>，即DATA SOURCE NAME，数据源名称。<code>DSN</code>包含从库的各个连接参数（<code>user</code>、<code>password</code>、<code>port</code>等），由逗号分隔的多个<code>option=value</code>字符串组成。<br>如：<code>h=host,P=3309,u=username,p=passwd</code>。</li></ul><p>dsn方法是指将从库的DSN信息存储在表（DSN表）里，然后将该表和DSN信息赋值给dsn，作为<code>--recursion-method</code>的参数值。<br>格式如：<code>--recursion-method dsn=D=percona,t=dsns,h=host,P=3309,u=username,p=passwd</code>。</p><p>当指定pt-table-checksum的<code>--recursion-method</code>参数值为dsn时，它只会连接和检测这些指定的从库。当从库的MySQL用户名、密码、端口与主库不相同时，也可以通过dsn的方式来指定。</p><p>DSN的部分选项如下：</p><blockquote><ul><li>D<br>DSN表所在的数据库名。</li><li>h<br>从库的host。</li><li>p<br>小写p，从库的密码。当密码包括逗号（<code>,</code>）时，需要使用反斜杠转义。</li><li>P<br>大写P，从库的端口。</li><li>S<br>连接使用的socket文件。</li><li>t<br>存储DSN信息的DSN表名。</li><li>u<br>从库的MySQL用户名。</li></ul></blockquote><p>每一个选项和其值的形式为<code>option=value</code>，<code>=</code>的前后不能空格，如果选项值有空格，则必须使用引号引起来。</p><p>将DSN作为<code>--recursion-method</code>的参数值时，必须包含<code>D</code>和<code>t</code>选项；或者只包含<code>t</code>选项，同时DSN表指定数据库前缀（如<code>percona.dsns</code>）。</p><p>DSN表结构如下：<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`dsns`</span> (</span><br><span class="line">  <span class="string">`id`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,</span><br><span class="line">  <span class="string">`parent_id`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">  <span class="string">`dsn`</span> <span class="built_in">varchar</span>(<span class="number">255</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">  PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>)</span><br><span class="line">);</span><br></pre></td></tr></table></figure></p><p>存储在表中的DSNs以<code>id</code>值排序，但是这里可以忽略<code>id</code>和<code>parent_id</code>列，只需将从库的DSN信息存储在<code>dsn</code>列即可。存储的DSN格式如前面在命令行上指定DSN一样，如：<code>h=host,P=3309,u=username,p=passwd</code>。</p><p>DSN的详细介绍可参考Percona官方文档：<a href="https://www.percona.com/doc/percona-toolkit/2.2/dsn_data_source_name_specifications.html" target="_blank" rel="noopener">https://www.percona.com/doc/percona-toolkit/2.2/dsn_data_source_name_specifications.html</a></p><h1 id="解决问题"><a href="#解决问题" class="headerlink" title="解决问题"></a>解决问题</h1><p>上面绕的有点晕。。。其实只需要知道如何使用dsn指定从库连接信息即可。</p><p>下面通过指定<code>--recursion-method</code>为dsn的方式，解决测试环境在数据校验时无法连接从库的问题。</p><ol><li><p>在主库新建DSN表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">CREATE</span> <span class="keyword">TABLE</span> <span class="string">`percona_schema.dsns`</span> (</span><br><span class="line">    <span class="string">`id`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,</span><br><span class="line">    <span class="string">`parent_id`</span> <span class="built_in">int</span>(<span class="number">11</span>) <span class="keyword">DEFAULT</span> <span class="literal">NULL</span>,</span><br><span class="line">    <span class="string">`dsn`</span> <span class="built_in">varchar</span>(<span class="number">255</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">    PRIMARY <span class="keyword">KEY</span> (<span class="string">`id`</span>)</span><br><span class="line">  );</span><br></pre></td></tr></table></figure></li><li><p>这里为了测试，和主库的MySQL账号区分开，新建了一个账号<code>pt_table_check2</code>专用于连接从库<br>主库账号是<code>pt_table_check</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">GRANT</span> <span class="keyword">SELECT</span>, PROCESS, SUPER, <span class="keyword">REPLICATION</span> <span class="keyword">SLAVE</span> <span class="keyword">ON</span> *.* <span class="keyword">TO</span> pt_table_check2@<span class="string">'192.168.0.%'</span> <span class="keyword">IDENTIFIED</span> <span class="keyword">BY</span> <span class="string">'checksum123'</span>;</span><br></pre></td></tr></table></figure></li><li><p>将从库的DSN信息写入DSN表</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">INSERT</span> <span class="keyword">INTO</span> percona_schema.dsns(dsn) <span class="keyword">VALUES</span> (<span class="string">"h=192.168.0.18,P=3309,u=pt_table_check2,p=checksum123"</span>);</span><br></pre></td></tr></table></figure></li><li><p>在主库使用dsn方式，重新运行pt-table-checksum进行校验</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">  shell&gt; ./bin/pt-table-checksum --socket=/var/lib/mysql/mysql.sock --user=pt_table_check --password=<span class="string">'checksum123'</span> --tables=road_to_dba.test1 --replicate=percona_schema.checksums --no-check-binlog-format --no-check-replication-filters --recursion-method dsn=t=percona_schema.dsns,h=192.168.0.18,P=3309,u=pt_table_check2,p=checksum123</span><br><span class="line">  </span><br><span class="line">               TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE</span><br><span class="line">  09-21T21:22:30      0      1      972       1       0   0.273 road_to_dba.test1</span><br></pre></td></tr></table></figure></li></ol><p>从第4步可以看到，pt-table-checksum已经能够检测到从库，并且检测到主从数据不一致（<code>DIFFS = 1</code>）。<br>问题解决。</p><h1 id="无法连接-检测从库的影响"><a href="#无法连接-检测从库的影响" class="headerlink" title="无法连接/检测从库的影响"></a>无法连接/检测从库的影响</h1><p>虽然在使用pt-table-checksum时，如果无法连接/检测到从库，仍可以完成主从一致性校验。但是，这样可能会产生一些其他的问题，如下：</p><ol><li>pt-table-checksum在执行校验时，无法实时检测主从的数据是否一致。即，输出的<code>DIFFS</code>列始终为0。</li><li>无法检测到从库是否有使用复制过滤，可能会造成从库复制卡住。</li><li>当某个表在主库上作为一个分块进行校验时，无法检测其在从库的数据量，当该表在从库的数据量很大时，会造成从库负载过高。</li><li>无法检测到从库的复制延迟状态，造成从库复制延迟过大。</li></ol>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;问题场景&quot;&gt;&lt;a href=&quot;#问题场景&quot; class=&quot;headerlink&quot; title=&quot;问题场景&quot;&gt;&lt;/a&gt;问题场景&lt;/h1&gt;&lt;h2 id=&quot;系统环境&quot;&gt;&lt;a href=&quot;#系统环境&quot; class=&quot;headerlink&quot; title=&quot;系统环境&quot;&gt;&lt;/a&gt;系统环境&lt;/h2&gt;&lt;p&gt;测试环境：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OS: CentOS 7&lt;/li&gt;
&lt;li&gt;DB Version: MariaDB 10.0.23&lt;/li&gt;
&lt;li&gt;PT Version: pt-table-checksum 2.2.18&lt;/li&gt;
&lt;li&gt;主从环境&lt;ul&gt;
&lt;li&gt;Master: 192.168.0.17:53309&lt;/li&gt;
&lt;li&gt;Slave: 192.168.0.18:3309&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;问题&quot;&gt;&lt;a href=&quot;#问题&quot; class=&quot;headerlink&quot; title=&quot;问题&quot;&gt;&lt;/a&gt;问题&lt;/h2&gt;&lt;p&gt;在使用pt-table-checksum配置主从校验的时候，本地和生产环境都可以正常校验，而在测试环境校验的时候，却输出以下警告信息：&lt;br&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Cannot connect to h=192.168.0.18,p=...,u=pt_table_check&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Diffs cannot be detected because no slaves were found.  Please &lt;span class=&quot;built_in&quot;&gt;read&lt;/span&gt; the --recursion-method documentation &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; information.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;pt-table-checksum无法连接从库。&lt;br&gt;由于没有发现从库，数据校验时无法实时检测从库与主库的数据是否一致（&lt;code&gt;DIFFS&lt;/code&gt;列始终为&lt;code&gt;0&lt;/code&gt;），需要通过&lt;code&gt;--recursion-method&lt;/code&gt;选项指定其他的方式来搜索、连接从库（此处&lt;code&gt;--recursion-method&lt;/code&gt;使用的是默认值&lt;code&gt;processlist,hosts&lt;/code&gt;）。&lt;/p&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="Percona Toolkit" scheme="https://db.tyoung.me/tags/Percona-Toolkit/"/>
    
      <category term="pt-table-checksum" scheme="https://db.tyoung.me/tags/pt-table-checksum/"/>
    
      <category term="主从一致性校验" scheme="https://db.tyoung.me/tags/%E4%B8%BB%E4%BB%8E%E4%B8%80%E8%87%B4%E6%80%A7%E6%A0%A1%E9%AA%8C/"/>
    
      <category term="DSN" scheme="https://db.tyoung.me/tags/DSN/"/>
    
  </entry>
  
  <entry>
    <title>pt-table-checksum使用方法及主从一致性校验</title>
    <link href="https://db.tyoung.me/2016/09/usage_of_pt-table-checksum_and_replication_consistency_check/"/>
    <id>https://db.tyoung.me/2016/09/usage_of_pt-table-checksum_and_replication_consistency_check/</id>
    <published>2016-09-19T14:43:41.000Z</published>
    <updated>2020-04-21T15:15:49.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="软件介绍"><a href="#软件介绍" class="headerlink" title="软件介绍"></a>软件介绍</h1><p>pt-table-checksum是Percona Toolkit工具系列中的一个，可以用来检测MySQL主、从数据的一致性。<br>其原理是，在主库执行校验语句（binlog格式为STATEMENT），通过复制传递到从库，如果数据不一致，则主、从会产生不同的校验值，以此来判断主从数据是否一致。</p><a id="more"></a><h1 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h1><ul><li>pt-table-checksum将每个表切分成多个块（chunks），每个块包含多行数据，每次仅对一个块进行校验。</li><li>它可以根据参数指定的每个块的校验执行时间，将表分成不同大小的块。</li><li>将单个表切分成多个块进行校验，可以保证不会引起从库太大的延迟，也不会对服务器负载造成太大干扰。默认的每个块的校验执行时间是0.5s。</li><li>pt-table-checksum会持续跟踪服务器执行校验语句的时间，并且会随着服务器性能的变化，来动态调整分块的大小。</li><li>将表分块时，需要使用索引（优先使用主键或唯一键）。如果表没有索引，且表的行数量较小时，pt-table-checksum会将整个表作为一个数据块进行校验。</li><li>pt-table-checksum会持续监控从库状态，如果从库复制延迟太大，校验会暂停，以等待从库追上主库。如果从库发生错误，或者复制停止，它也会暂停及等待。</li><li>pt-table-checksum对于校验过程中产生的错误是有复原能力的。如果正在执行校验的SQL被kill掉，这对pt-table-checksum来说不是一个致命的错误，它会重新执行被kill掉的查询语句；如果再次失败，则会跳过，继续进行表的下一个分块的校验。<br>当出现锁等待超时的时候，也会进行相同的重试行为，同时输出警告信息。<br>如果连接服务器失败，pt-table-checksum也会进行重连和继续进行校验。</li><li>当在运行的过程中被完全终止后，可以使用<code>--resume</code>参数，继续从上次终止时正在处理的表的当前分块开始，继续校验。<br>我们也可以使用<code>CTRL-C</code>按键来停止校验，pt-table-checksum会在完成对当前正在处理的分块的校验后，正常退出。之后我们也可以启动程序继续进行校验。</li><li>当pt-table-checksum完成对一个表的所有分块的校验后，它会暂停并等待所有检测到的从库执行完这个表的校验语句。一旦从库执行完成，它会比对主、从的校验结果是否一致，并输出一行结果。</li></ul><h1 id="使用限制"><a href="#使用限制" class="headerlink" title="使用限制"></a>使用限制</h1><ul><li>pt-table-checksum要求复制是基于STATEMENT格式的，并且它在运行时会在主库上设置<code>binlog_format=STATEMENT</code>，但是由于MySQL的限制，这一设置并不会传递到从库。<br>因此当从库的binlog格式是ROW格式时，无法直接对从库的从库进行校验。<br>pt-table-checksum会自动检测所有服务器的<code>binlog_format</code>，可以通过参数<code>--[no]check-binlog-format</code>来指定检测与否。</li><li>pt-table-checksum假设主从的数据库和表结构都是一致的。<br>如果主库上的库不存在于从库上，或者从库的表结构与主库不一致，将会导致主从复制中断。</li></ul><h1 id="输出"><a href="#输出" class="headerlink" title="输出"></a>输出</h1><p>pt-table-checksum的输出有两种格式：带<code>--replicate-check-only</code>参数和正常不带这个参数时，输出结果的格式是不同的。</p><h2 id="不带-replicate-check-only参数的输出"><a href="#不带-replicate-check-only参数的输出" class="headerlink" title="不带--replicate-check-only参数的输出"></a>不带<code>--replicate-check-only</code>参数的输出</h2><p>pt-table-checksum在完成校验后会以表格形式输出结果，每个表的校验结果为一行输出，每完成校验一张表会输出一行校验结果。</p><p>输出格式如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE</span><br><span class="line">09-12T10:34:38      0      0        1       1       0   0.059 road_to_dba.names</span><br><span class="line">09-12T10:34:38      0      0        5       1       0   0.016 road_to_dba.t_bigint</span><br></pre></td></tr></table></figure></p><p>各列的含义如下：</p><ul><li>TS<br>pt-table-checksum完成该表的校验时的时间。</li><li>ERRORS<br>在校验表的过程中出现的错误和警告的数量。<br>错误和警告信息在校验的过程中会以标准错误的形式输出。</li><li>DIFFS<br>主库数据与一个（或多个）从库数据不一致的分块的数量。<br>当指定<code>--no-replicate-check</code>时，该值始终为0。当指定<code>--replicate-check-only</code>时，只输出数据不一致的表的校验结果。</li><li>ROWS<br>查询和校验的表的行数。</li><li>CHUNKS<br>表被分成的分块的数量。</li><li>SKIPPED<br>校验表时，跳过的分块的数量。<br>数据分块被跳过可能由以下问题引起：<ul><li>MySQL没有使用<code>--chunk-index</code>指定的索引；</li><li>通过分析执行计划（<code>--[no]check-plan</code>）检测到MySQL没有使用全部的表分块使用的索引；</li><li>数据分块的大小大于<code>--chunk-size * --chunk-size-limit</code>；</li><li>锁等待超时（重试的次数大于<code>--retries</code>指定的值）；</li><li>校验的查询语句被kill掉（重试的次数大于<code>--retries</code>指定的值）</li></ul></li><li>TIME<br>表的校验执行时长。</li><li>TABLE<br>校验的表名（含库名）。</li></ul><h2 id="带-replicate-check-only参数的输出"><a href="#带-replicate-check-only参数的输出" class="headerlink" title="带--replicate-check-only参数的输出"></a>带<code>--replicate-check-only</code>参数的输出</h2><p>如果指定了<code>--replicate-check-only</code>参数，则只会输出校验结果不一致的从库数据。<br>输出结果的格式为：每一个从库为一个段落，每一个校验结果不同的分块占一行，各列值之间以空格分隔。如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Differences on node601</span><br><span class="line">TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY</span><br><span class="line">road_to_dba.tbl1 1 0 1 PRIMARY 1 100</span><br><span class="line">road_to_dba.tbl1 6 0 1 PRIMARY 501 600</span><br><span class="line"></span><br><span class="line">Differences on node603</span><br><span class="line">TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY</span><br><span class="line">road_to_dba.tbl1 1 0 1 PRIMARY 1 100</span><br><span class="line">road_to_dba.tbl2 9 5 0 PRIMARY 101 200</span><br></pre></td></tr></table></figure></p><p>输出的每个段落的第一行表示校验结果与主库不一致的从库的信息。<br>各列的含义如下：</p><ul><li>TABLE<br>与主库数据不一致的表的名称（包含库名）。</li><li>CHUNK<br>表中与主库数据不一致的分块号。</li><li>CNT_DIFF<br><code>从库的分块的行数量</code>减去<code>主库的分块的行数量</code>的差值。</li><li>CRC_DIFF<br>如果从库分块的CRC校验值与主库的不同，则为1；否则，为0。</li><li>CHUNK_INDEX<br>将表进行分块所使用的索引。</li><li>LOWER_BOUNDARY<br>分块的下边界所使用的索引值。</li><li>UPPER_BOUNDARY<br>分块的上边界所使用的索引值。</li></ul><h1 id="退出状态码"><a href="#退出状态码" class="headerlink" title="退出状态码"></a>退出状态码</h1><p>pt-table-checksum的退出状态码有3种值：<code>0</code>，<code>255</code>，<code>其他的位掩码值</code>。</p><ul><li><code>0</code>表示没有校验过程中没有任何错误出现。即，没有错误、警告、不同的校验值、跳过数据分块或表等。</li><li><code>255</code>表示数据校验出现严重错误。也就是说，校验的进程终止或崩溃了。错误信息作为标准错误（<code>STDERR</code>）输出。</li><li>如果退出状态码不是0或255，各个位掩码值表示的含义如下：<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">  FLAG              BIT VALUE  MEANING</span><br><span class="line">  ================  =========  ==========================================</span><br><span class="line">  ERROR                     1  出现了一个不严重的错误</span><br><span class="line">  ALREADY_RUNNING           2  --pid选项指定的文件已存在，并且对应的PID在运行中</span><br><span class="line">  CAUGHT_SIGNAL             4  Caught SIGHUP, SIGINT, SIGPIPE, or SIGTERM</span><br><span class="line">  NO_SLAVES_FOUND           8  没有检测到从库或集群节点</span><br><span class="line">  TABLE_DIFF               16  本次校验至少有一个分块的数据不同</span><br><span class="line">  SKIP_CHUNK               32  至少有一个数据分块被跳过</span><br><span class="line">  SKIP_TABLE               64  至少有一个表被跳过</span><br></pre></td></tr></table></figure></li></ul><h1 id="常用参数"><a href="#常用参数" class="headerlink" title="常用参数"></a>常用参数</h1><h2 id="–ask-pass"><a href="#–ask-pass" class="headerlink" title="–ask-pass"></a>–ask-pass</h2><p>通过提示输入密码，而不是在命令行指定密码。</p><h2 id="–-no-check-binlog-format"><a href="#–-no-check-binlog-format" class="headerlink" title="–[no]check-binlog-format"></a>–[no]check-binlog-format</h2><p>默认：<code>yes</code><br>检查binlog格式。<br>如果binlog格式不是STATEMENT，需要指定<code>--no-check-binlog-format</code>，如果不指定此项，会报错。</p><h2 id="–-no-check-replication-filters"><a href="#–-no-check-replication-filters" class="headerlink" title="–[no]check-replication-filters"></a>–[no]check-replication-filters</h2><p>默认：<code>yes</code><br>pt-table-checksum会检查复制过滤相关的参数，例如，<code>binlog_ignore_db</code>，<code>replicate_do_db</code>等。如果检测到已配置任何复制过滤参数，它将会终止校验，并输出错误信息。</p><p>如果只是校验指定的数据库或表，且没有被复制过滤掉，则可以指定<code>--no-check-replication-filters</code>来进行数据校验。<br>如果被校验的表在主库存在，但是在从库被复制过滤掉了，则会导致复制中断卡住。</p><h2 id="–chunk-time"><a href="#–chunk-time" class="headerlink" title="–chunk-time"></a>–chunk-time</h2><p>值类型：浮点数<br>默认：<code>0.5</code>(s)<br>根据这个时间来动态的调整数据分块的大小，以使每个分块的校验执行时间不超过此值。</p><h2 id="–databases"><a href="#–databases" class="headerlink" title="–databases"></a>–databases</h2><p>缩写形式：<code>-d</code><br>指定需要校验的数据库，多个库以逗号分隔。</p><h2 id="–databases-regex"><a href="#–databases-regex" class="headerlink" title="–databases-regex"></a>–databases-regex</h2><p>使用正则表达式的形式来指定需要校验的数据库。</p><h2 id="–host"><a href="#–host" class="headerlink" title="–host"></a>–host</h2><p>缩写形式：<code>-h</code><br>值类型：字符串<br>默认：<code>localhost</code></p><p>需要连接的服务器的主机地址。</p><h2 id="–ignore-databases"><a href="#–ignore-databases" class="headerlink" title="–ignore-databases"></a>–ignore-databases</h2><p>指定需要忽略校验的数据库，多个库以逗号分隔。</p><h2 id="–ignore-databases-regex"><a href="#–ignore-databases-regex" class="headerlink" title="–ignore-databases-regex"></a>–ignore-databases-regex</h2><p>值类型：字符串<br>以正则表达式的形式指定需要忽略的数据库。</p><h2 id="–ignore-tables"><a href="#–ignore-tables" class="headerlink" title="–ignore-tables"></a>–ignore-tables</h2><p>指定需要忽略校验的表，多个表名以逗号分隔。表名前面可以指定数据库名。<br><code>--replicate</code>选项指定的表，始终会被忽略掉。</p><h2 id="–ignore-tables-regex"><a href="#–ignore-tables-regex" class="headerlink" title="–ignore-tables-regex"></a>–ignore-tables-regex</h2><p>以正则表达式的形式指定需要忽略校验的表。</p><h2 id="–password"><a href="#–password" class="headerlink" title="–password"></a>–password</h2><p>缩写形式：<code>-p</code><br>数据库连接的密码，如果密码包括逗号（<code>,</code>），则必须使用反斜杠。</p><h2 id="–port"><a href="#–port" class="headerlink" title="–port"></a>–port</h2><p>缩写形式：<code>-P</code><br>数据库连接的端口。</p><h2 id="–recursion-method"><a href="#–recursion-method" class="headerlink" title="–recursion-method"></a>–recursion-method</h2><p>默认：<code>processlist,hosts</code><br>指定搜索从库的递归方法。当pt-table-checksum无法搜索到从库时，其可以正常的进行数据校验，但是无法直接检测从库数据与主库是否一致。<br>如果搜索不到从库，可以尝试指定其他的递归方法，或者使用dsn来指定需要检测的从库。</p><p>允许的方法有：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">METHOD       USES</span><br><span class="line">===========  =============================================</span><br><span class="line">processlist  SHOW PROCESSLIST</span><br><span class="line">hosts        SHOW SLAVE HOSTS</span><br><span class="line">cluster      SHOW STATUS LIKE <span class="string">'wsrep\_incoming\_addresses'</span></span><br><span class="line">dsn=DSN      DSNs from a table</span><br><span class="line">none         Do not find slaves</span><br></pre></td></tr></table></figure></p><p>详细可参考官方文档：<a href="https://www.percona.com/doc/percona-toolkit/2.2/pt-table-checksum.html#cmdoption-pt-table-checksum--recursion-method" target="_blank" rel="noopener">https://www.percona.com/doc/percona-toolkit/2.2/pt-table-checksum.html#cmdoption-pt-table-checksum--recursion-method</a></p><h2 id="–replicate"><a href="#–replicate" class="headerlink" title="–replicate"></a>–replicate</h2><p>默认：<code>percona.checksums</code><br>将校验结果写入到指定的库和表中。</p><blockquote><p>本文后续所说的<strong>校验信息表</strong>即指该表。</p></blockquote><p>表结构如下：<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> checksums (</span><br><span class="line">   db             <span class="built_in">CHAR</span>(<span class="number">64</span>)     <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">   tbl            <span class="built_in">CHAR</span>(<span class="number">64</span>)     <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">   <span class="keyword">chunk</span>          <span class="built_in">INT</span>          <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">   chunk_time     <span class="built_in">FLOAT</span>            <span class="literal">NULL</span>,</span><br><span class="line">   chunk_index    <span class="built_in">VARCHAR</span>(<span class="number">200</span>)     <span class="literal">NULL</span>,</span><br><span class="line">   lower_boundary <span class="built_in">TEXT</span>             <span class="literal">NULL</span>,</span><br><span class="line">   upper_boundary <span class="built_in">TEXT</span>             <span class="literal">NULL</span>,</span><br><span class="line">   this_crc       <span class="built_in">CHAR</span>(<span class="number">40</span>)     <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">   this_cnt       <span class="built_in">INT</span>          <span class="keyword">NOT</span> <span class="literal">NULL</span>,</span><br><span class="line">   master_crc     <span class="built_in">CHAR</span>(<span class="number">40</span>)         <span class="literal">NULL</span>,</span><br><span class="line">   master_cnt     <span class="built_in">INT</span>              <span class="literal">NULL</span>,</span><br><span class="line">   ts             <span class="built_in">TIMESTAMP</span>    <span class="keyword">NOT</span> <span class="literal">NULL</span> <span class="keyword">DEFAULT</span> <span class="keyword">CURRENT_TIMESTAMP</span> <span class="keyword">ON</span> <span class="keyword">UPDATE</span> <span class="keyword">CURRENT_TIMESTAMP</span>,</span><br><span class="line">   PRIMARY <span class="keyword">KEY</span> (db, tbl, <span class="keyword">chunk</span>),</span><br><span class="line">   <span class="keyword">INDEX</span> ts_db_tbl (ts, db, tbl)</span><br><span class="line">) <span class="keyword">ENGINE</span>=<span class="keyword">InnoDB</span> <span class="keyword">DEFAULT</span> <span class="keyword">CHARSET</span>=utf8;</span><br></pre></td></tr></table></figure></p><p><code>lower_boundary</code>和<code>upper_boundary</code>列的类型可以设置为<code>BLOB</code>，详情参考<code>--binary-index</code>参数。</p><p>默认情况下，<code>--[no]create-replicate-table</code>是开启的。因此，当<code>--replicate</code>指定的库和表不存在时，pt-table-checksum会自动创建这些库和表。</p><p>如果用于校验的MySQL用户没有新建表的权限，则也可以在校验主从数据之前，使用上述表结构手动创建该表。</p><p><code>--replicate</code>参数指定的表，在校验数据一致性时，默认是被忽略的。即，<code>--ignore-tables</code>参数会自动的包含该表。</p><h2 id="–-no-replicate-check"><a href="#–-no-replicate-check" class="headerlink" title="–[no]replicate-check"></a>–[no]replicate-check</h2><p>默认：<code>yes</code><br>在校验完每一个表后，校验从库与主库的数据一致性。<br>pt-table-checksum会在所有检测到的从库上，执行一个简单的<code>SELECT</code>语句，来比较从库的校验值与主库的校验值是否一致。如果不一致，则将不一致的分块的数量，输出到<code>DIFFS</code>列。</p><h2 id="–replicate-check-only"><a href="#–replicate-check-only" class="headerlink" title="–replicate-check-only"></a>–replicate-check-only</h2><p>如果指定此选项，pt-table-checksum不会校验任何表，而是使用上一次数据校验存储在<code>--replicate</code>指定的校验信息表的校验数据，来检测主从数据的一致性。<br>使用该选项时，只会输出校验结果不一致的表的信息。</p><p>该选项只和<code>--[no]replicate-check</code>选项搭配使用。这两个选项配合起来可以做定时校验和监控。例如，使用cron任务定时校验主从数据时指定<code>--no-replicate-check</code>，然后再在Zabbix或Nagios监控时，指定<code>--replicate-check-only</code>来检测主从数据一致性。</p><h2 id="–slave-user"><a href="#–slave-user" class="headerlink" title="–slave-user"></a>–slave-user</h2><p>值类型：字符串<br>连接从库时所使用的MySQL用户名。<br>当连接从库的用户名和主库不同时，可以使用此参数单独指定从库用户。</p><h2 id="–slave-password"><a href="#–slave-password" class="headerlink" title="–slave-password"></a>–slave-password</h2><p>值类型：字符串<br>指定连接从库的密码，可以和参数<code>--slave-user</code>一起使用，并且所有从库的密码都必须是一样的。</p><h2 id="–set-vars"><a href="#–set-vars" class="headerlink" title="–set-vars"></a>–set-vars</h2><p>值类型：array<br>设置MySQL变量值，每个变量值的形式为<code>variable=value</code>，多个变量以逗号分隔。<br>pt-table-checksum默认设置的变量值为：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wait_timeout=10000</span><br><span class="line">innodb_lock_wait_timeout=1</span><br></pre></td></tr></table></figure></p><p>当无法设置变量值的时候，pt-table-checksum会输出相应的警告信息，并继续进行校验。</p><h2 id="–socket"><a href="#–socket" class="headerlink" title="–socket"></a>–socket</h2><p>缩写形式：<code>-S</code><br>指定socket文件。</p><h2 id="–tables"><a href="#–tables" class="headerlink" title="–tables"></a>–tables</h2><p>缩写形式：<code>-t</code><br>指定需要检查的表，多个表用逗号分隔。表名前面可以加上数据库的名称。</p><h2 id="–tables-regex"><a href="#–tables-regex" class="headerlink" title="–tables-regex"></a>–tables-regex</h2><p>使用正则表达式的形式指定需要检查的表。</p><h2 id="–user"><a href="#–user" class="headerlink" title="–user"></a>–user</h2><p>缩写形式：<code>-u</code></p><p>指定连接的用户名。</p><h2 id="–where"><a href="#–where" class="headerlink" title="–where"></a>–where</h2><p>只校验符合WHERE条件的数据。</p><p>通常情况下，如果某个表每天只会往里面新增写入数据，则可以使用WHERE条件只校验昨天的数据，以加快校验速度。<br>如：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pt-table-checksum --<span class="built_in">where</span> <span class="string">"ts &gt; CURRENT_DATE - INTERVAL 1 DAY"</span></span><br></pre></td></tr></table></figure></p><h1 id="其他参数"><a href="#其他参数" class="headerlink" title="其他参数"></a>其他参数</h1><h2 id="–binary-index"><a href="#–binary-index" class="headerlink" title="–binary-index"></a>–binary-index</h2><p>该参数选项和<code>--create-replicate-table</code>选项一起使用，使用该参数会将校验信息表的<code>lower_boundary</code>和<code>upper_boundary</code>列定义为<code>BLOB</code>类型。<br>如果被校验的表的索引包含binary数据类型，则需要使用选项。</p><h2 id="–check-interval"><a href="#–check-interval" class="headerlink" title="–check-interval"></a>–check-interval</h2><p>值类型：时间<br>默认：<code>1</code><br>当发现从库的延迟时间超过<code>--max-lag</code>定义的时间后，需要休眠等待的时间。</p><h2 id="–-no-check-plan"><a href="#–-no-check-plan" class="headerlink" title="–[no]check-plan"></a>–[no]check-plan</h2><p>默认：<code>yes</code><br>在执行查询语句之前使用<code>EXPLAIN</code>检查执行计划，以保证校验工作的安全性。<br>查询语句包括确定表数据分块的上下边界的语句，和查询分块的语句。如果MySQL将使用一个糟糕的执行计划，pt-table-checksum会跳过这个分块。</p><h2 id="–check-slave-lag"><a href="#–check-slave-lag" class="headerlink" title="–check-slave-lag"></a>–check-slave-lag</h2><p>值类型：字符串<br>指定需要检测复制延迟的从库，参数值是一个<code>DSN</code>，并且继承主库的属性和连接选项（<code>--port</code>、<code>--user</code>等）。<br>默认情况下，pt-table-checksum会监测所有从库的延迟。如果某些从库配置了延迟复制，则可以使用此参数指定只需要检测延迟的从库，以忽略那些配置了复制延迟的从库。</p><h2 id="–-no-check-slave-tables"><a href="#–-no-check-slave-tables" class="headerlink" title="–[no]check-slave-tables"></a>–[no]check-slave-tables</h2><p>默认：<code>yes</code><br>检查主库的表存在于从库上，且具有<code>--columns</code>选项指定的所有的列。<br>如果从库上不存在某些表，或者缺少某些列，在校验数据一致性的时候，pt-table-checksum将会导致复制中断。<br>如果确定从库的表和列都和主库的一样，则可以禁用此项。</p><h2 id="–chunk-index"><a href="#–chunk-index" class="headerlink" title="–chunk-index"></a>–chunk-index</h2><p>值类型：字符串<br>指定将表进行分块所使用的索引。<br>默认情况下，pt-table-checksum会自动选择最合适的索引来对表进行分块。使用此选项可以使用指定的索引。如果指定的索引不存在，则pt-table-checksum会使用其默认的行为来选择索引。<br>建议在校验单表数据时可以使用此参数，而不要在校验整个服务器的数据时使用此参数。</p><h2 id="–chunk-index-columns"><a href="#–chunk-index-columns" class="headerlink" title="–chunk-index-columns"></a>–chunk-index-columns</h2><p>值类型：整数<br>和参数<code>--chunk-index</code>一起使用，指定只使用指定（复合）索引的最左边的几列。</p><h2 id="–chunk-size"><a href="#–chunk-size" class="headerlink" title="–chunk-size"></a>–chunk-size</h2><p>默认：<code>1000</code><br>每一个数据分块的行数。允许的后缀有：<code>k</code>，<code>M</code>，<code>G</code>。<br>推荐在大多数情况下，不要使用此参数，而是使用<code>--chunk-time</code>参数。</p><p>使用该参数可能会引起一个问题：</p><blockquote><p>如果分块所使用的索引不是唯一的，则可能导致分块的行数比实际指定的要大得多。<br>例如，一个分块使用索引可以检索到的行数为10000，则使用该索引的WHERE语句是无法正好匹配1000条记录的，那么这个分块就会包含10000行记录。<br>这样的分块，很可能会由于超过<code>--chunk-size-limit</code>的限制而被跳过。</p></blockquote><h2 id="–chunk-size-limit"><a href="#–chunk-size-limit" class="headerlink" title="–chunk-size-limit"></a>–chunk-size-limit</h2><p>值类型：浮点数<br>默认：<code>2.0</code><br>指定分块的行数最多可以超过<code>--chunk-size</code>参数指定的行数的多少倍。</p><p>pt-table-checksum使用<code>EXPLAIN</code>来估算分块的行数。如果这个估算值超过了<code>--chunk-size</code>参数值的某个倍数（由<code>--chunk-size-limit</code>定义），则分块会被跳过。</p><p>最小值是1，表示分块的行数不能超过<code>--chunk-size</code>指定的值。由于分块的行数是估算的，所以不建议指定为1。<br>当参数值为0时，则不会检查是否超过指定的行数。</p><h2 id="–columns"><a href="#–columns" class="headerlink" title="–columns"></a>–columns</h2><p>缩写形式：<code>-c</code><br>值类型：array<br>多个列以逗号分隔。只校验这些列。如果一个表不包含该选项指定的任何一列，则会被跳过。<br>该选项对所有的表有效，所以一般在进行单表校验时，指定此选项才是有意义的，除非被校验的多个表具有相同的列。</p><h2 id="–config"><a href="#–config" class="headerlink" title="–config"></a>–config</h2><p>值类型：array<br>指定配置文件，多个值以逗号分隔。<br>如果使用该参数，该选项必须放在第一个位置。</p><h2 id="–-no-create-replicate-table"><a href="#–-no-create-replicate-table" class="headerlink" title="–[no]create-replicate-table"></a>–[no]create-replicate-table</h2><p>默认：<code>yes</code><br>如果<code>--replicate</code>选项指定的数据库和表不存在，则创建该库和表。表结构与<code>--replicate</code>选项下提到的表结构一样。</p><h2 id="–defaults-file"><a href="#–defaults-file" class="headerlink" title="–defaults-file"></a>–defaults-file</h2><p>缩写形式：<code>-F</code><br>只从给定的文件读取MySQL的参数。必须使用绝对路径来指定。</p><h2 id="–-no-empty-replicate-table"><a href="#–-no-empty-replicate-table" class="headerlink" title="–[no]empty-replicate-table"></a>–[no]empty-replicate-table</h2><p>默认：<code>yes</code><br>在校验每个表之前，删除之前存在校验信息表的该表的校验数据。</p><p>该选项不会TRUNCATE整个表，而只是在校验每个表之前，删除该表相关的校验数据。<br>如果使用<code>--resume</code>选项从之前的一个校验继续执行校验，则重新开始校验时所在的那张表的校验数据不会被清除掉。</p><h2 id="–engines"><a href="#–engines" class="headerlink" title="–engines"></a>–engines</h2><p>缩写形式：<code>-e</code><br>指定需要校验的表的存储引擎。</p><h2 id="–explain"><a href="#–explain" class="headerlink" title="–explain"></a>–explain</h2><p>可以多次使用该参数选项。默认是0次。<br>输出当前数据校验的查询语句，但不执行。该选项会使<code>--[no]empty-replicate-table</code>选项无效。<br>当使用该参数一次时，会输出表的校验查询语句（不含具体的上下边界值）。<br>当使用该参数两次时，会迭代的调用数据分块算法，输出表的每一个分块的上、下边界值，但是不会执行这些校验查询语句。</p><h2 id="–float-precision"><a href="#–float-precision" class="headerlink" title="–float-precision"></a>–float-precision</h2><p>值类型：整数<br><code>FLOAT</code>和<code>DOUBLE</code>类型转换成字符串时的精度。<br>指定浮点数被四舍五入（<code>ROUND()</code>）转换成字符串时，小数点后保留的数字的个数。<br>默认情况下，浮点数没有被四舍五入，而是被使用<code>CONCAT()</code>函数转换成字符串。</p><h2 id="–function"><a href="#–function" class="headerlink" title="–function"></a>–function</h2><p>值类型：字符串<br>校验时使用的hash函数，包括<code>FNV1A_64</code>、<code>MURMUR_HASH</code>、<code>SHA1</code>、<code>MD5</code>、<code>CRC32</code>等。<br>默认的是<code>CRC32</code>。</p><h2 id="–help"><a href="#–help" class="headerlink" title="–help"></a>–help</h2><p>显示帮助信息。</p><h2 id="–ignore-columns"><a href="#–ignore-columns" class="headerlink" title="–ignore-columns"></a>–ignore-columns</h2><p>指定需要忽略校验的列名，多个列以逗号分隔。<br>如果一个表的所有列都在<code>--ignore-columns</code>指定忽略的列中，则会跳过该表。</p><h2 id="–ignore-engines"><a href="#–ignore-engines" class="headerlink" title="–ignore-engines"></a>–ignore-engines</h2><p>默认：<code>FEDERATED,MRG_MyISAM</code><br>指定需要忽略校验的存储引擎，多个值以逗号分隔。</p><h2 id="–max-lag"><a href="#–max-lag" class="headerlink" title="–max-lag"></a>–max-lag</h2><p>类型：时间<br>默认：<code>1s</code></p><p>当发现从库的延迟超过该参数的值时，则会暂停校验，直至从库的延迟小于该值。<br>pt-table-checksum在校验完每一个分块后，都会检查所有检测到的从库的延迟（根据<code>Seconds_Behind_Master</code>判断）。如果延迟大于该值，则会休眠等待<code>--check-interval</code>定义的秒数，然后再次检查从库。<br>如果从库停止了，pt-table-checksum则会一直等待，直至从库重新启动。当从库重新启动且延迟不再大的时候，会继续进行校验。</p><h2 id="–max-load"><a href="#–max-load" class="headerlink" title="–max-load"></a>–max-load</h2><p>值类型：array<br>默认：<code>Threads_running=25</code><br>在校验完每一个分块后，执行<code>SHOW GLOBAL STATUS</code>，检查相关状态的值是否超过该选项定义的阈值。当超过阈值时，pt-table-checksum会暂停校验；当值低于阈值后，会继续进行校验。<br>该选项支持指定多个MySQL status变量（以逗号分隔），并为其分别指定阈值（可选的。形式：<code>=MAX_VALUE</code>或<code>:MAX_VALUE</code>）。如果没有指定阈值，则pt-table-checksum会将当前值增大20%，作为阈值。<br>例如，可以指定<code>Threads_connected=110</code>，来限定当Threads_connected超过110时，则暂停校验。</p><h2 id="–pid"><a href="#–pid" class="headerlink" title="–pid"></a>–pid</h2><p>创建指定的PID文件。</p><h2 id="–progress"><a href="#–progress" class="headerlink" title="–progress"></a>–progress</h2><p>type：array<br>默认值：<code>time,30</code><br>每隔多久将执行的进度信息以标准错误输出（<code>STDERR</code>）。<br>该参数的值由两部分构成，以逗号分隔。第一部分的取值可以是：<code>percentage</code>，<code>time</code>，或者<code>iterations</code>；第二部分指定每隔多久进行一次信息输出：in percentage，seconds，或者number of iterations。<br>pt-table-checksum会对许多耗时的操作输出进度信息，包括等待从库赶上主库（从库延迟时）。</p><h2 id="–quiet"><a href="#–quiet" class="headerlink" title="–quiet"></a>–quiet</h2><p>缩写形式：<code>-q</code><br>可以多次叠加使用该选项，默认未使用。使用该选项使pt-table-checksum只输出最重要的信息，并且会使选项<code>--progress</code>无效。<br>指定该参数一次，则只会输出错误、警告，和具有不同校验值的表。<br>指定该参数两次，则只会输出错误信息。在这种情况下，可以使用退出状态码来判断是否有警告或者不同的校验值。</p><h2 id="–recurse"><a href="#–recurse" class="headerlink" title="–recurse"></a>–recurse</h2><p>值类型：整数<br>在主从结构中，递归搜索从库的层数。<br>默认是无限的。</p><h2 id="–replicate-check-retries"><a href="#–replicate-check-retries" class="headerlink" title="–replicate-check-retries"></a>–replicate-check-retries</h2><p>值类型：整数<br>默认：<code>1</code><br>当发现某个表的校验结果不一致时，对该表进行重复校验的次数。只有当经过这些次数的校验后，还存在的不一致的校验信息才作为最终的结果。</p><p>使用这个参数，是为了解决使用<code>-–resume</code>参数而导致的虚假的主从不一致信息。当该参数值为2或者更大时，基本可以消除这些虚假的主从不一致信息。<br>详情可以参考以下链接：</p><ul><li>Bug #1311654: <a href="https://bugs.launchpad.net/percona-toolkit/+bug/1311654" target="_blank" rel="noopener">https://bugs.launchpad.net/percona-toolkit/+bug/1311654</a></li></ul><h2 id="–replicate-database"><a href="#–replicate-database" class="headerlink" title="–replicate-database"></a>–replicate-database</h2><p>pt-table-checksum在进行数据校验时，执行的<code>USE database</code>语句始终使用该参数指定的数据库。<br>默认情况下，会将当前校验的表所在的库，作为<code>USE database</code>的库来执行。<br>使用该参数选项来避免复制过滤引起的问题（过滤参数如<code>binlog_ignore_db</code>，<code>replicate_ignore_db</code>等）。</p><h2 id="–resume"><a href="#–resume" class="headerlink" title="–resume"></a>–resume</h2><p>在上一次校验中断后，使用此参数可以继续上一次的校验。该参数会禁用<code>--[no]empty-replicate-table</code>参数。<br>如果pt-table-checksum在校验完所有的表之前被终止了，则使用<code>--resume</code>参数再次启动pt-table-checksum时，会从上次校验的最后一个表的最后一个校验完成的分块开始校验。</p><h2 id="–retries"><a href="#–retries" class="headerlink" title="–retries"></a>–retries</h2><p>值类型：整数<br>默认：<code>2</code></p><p>当出现一个非致命的错误时，对该分块进行重试校验的次数。<br>非致命的错误包括锁等待超时、校验查询的SQL线程被kill了，等等。</p><h2 id="–run-time"><a href="#–run-time" class="headerlink" title="–run-time"></a>–run-time</h2><p>值类型：时间<br>pt-table-checksum执行校验的总时长。<br>允许的时间后缀有：<code>s</code>（秒），<code>m</code>（分），<code>h</code>（时），<code>d</code>(天)。</p><p>当校验很多表时，可以将该参数和<code>--resume</code>参数结合在一起使用。</p><blockquote><p>使用<code>--run-time</code>在指定分配的时间进行校验后退出，然后使用<code>--resume</code>参数在指定时间继续之前的校验。</p></blockquote><h2 id="–separator"><a href="#–separator" class="headerlink" title="–separator"></a>–separator</h2><p>值类型：字符串<br>默认：<code>#</code><br>定义函数<code>CONCAT_WS()</code>使用的分隔符。该参数定义的字符，用于在校验时连接各列的值。</p><h2 id="–slave-skip-tolerance"><a href="#–slave-skip-tolerance" class="headerlink" title="–slave-skip-tolerance"></a>–slave-skip-tolerance</h2><p>值类型：浮点数<br>默认：<code>1.0</code></p><p>当某个表在主库只被作为一个数据分块校验，而在从库的数据大小却超过了可接受的最大值时，该表会被跳过。由于表的行数是粗略估计的，在多数情况下，由于很小的主从数据差异而进行的表跳过是没有必要的。<br>该参数的定义可以减少这种不必要的跳过。<br>使用该参数可指定从库的行数超过主库的行数的最大的容忍值。<br>例如，当参数值为<code>1.2</code>时，表在从库的行数最多是主库的<strong>1.2</strong>倍。</p><h2 id="–trim"><a href="#–trim" class="headerlink" title="–trim"></a>–trim</h2><p>对校验数据的<code>VARCHAR</code>列添加<code>TRIM()</code>函数。<br>MySQL 5.0之后的版本，<code>VARCHAR</code>列会保存字符串首尾的空格；但是MySQL 5.0之前的版本会移除这些空格。<br>指定该选项，可以移除<code>VARCHAR</code>列数据的首尾的空格。</p><h2 id="–version"><a href="#–version" class="headerlink" title="–version"></a>–version</h2><p>显示程序的版本。</p><h2 id="–-no-version-check"><a href="#–-no-version-check" class="headerlink" title="–[no]version-check"></a>–[no]version-check</h2><p>默认：<code>yes</code><br>自动的检查Percona Toolkit，MySQL，和其他程序的版本。<br>首先，pt-table-checksum会检查它自己和其他软件的版本，检查的软件如MySQL、Perl、Perl module DBD::mysql等等。然后，它会检查和输出这些软件版本的已知问题。</p><h1 id="使用示例"><a href="#使用示例" class="headerlink" title="使用示例"></a>使用示例</h1><h2 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pt-table-checksum [OPTIONS] [DSN]</span><br></pre></td></tr></table></figure><h2 id="系统环境"><a href="#系统环境" class="headerlink" title="系统环境"></a>系统环境</h2><ul><li>OS Version: CentOS 6</li><li>DB Version: MySQL 5.6.29</li><li>PT Version: pt-table-checksum 2.2.18</li><li>主从环境:<br>主从端口相同，都是3376。<ul><li>Master: 192.168.0.162:3376</li><li>Slave1: 192.168.0.161:3376</li></ul></li></ul><h2 id="安装依赖软件"><a href="#安装依赖软件" class="headerlink" title="安装依赖软件"></a>安装依赖软件</h2><p>安装 Perl, DBI, DBD::mysql等<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; yum install perl perl-devel perl-Time-HiRes perl-DBI perl-DBD-MySQL perl-Digest-MD5</span><br></pre></td></tr></table></figure></p><h2 id="安装Percona-Toolkit"><a href="#安装Percona-Toolkit" class="headerlink" title="安装Percona Toolkit"></a>安装Percona Toolkit</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; wget percona.com/get/percona-toolkit.tar.gz</span><br><span class="line">shell&gt; tar zxvf percona-toolkit.tar.gz</span><br><span class="line">shell&gt; <span class="built_in">cd</span> percona-toolkit-2.2.18</span><br><span class="line">shell&gt; ./bin/pt-table-checksum --version</span><br><span class="line">pt-table-checksum 2.2.18</span><br></pre></td></tr></table></figure><h2 id="新建MySQL帐号"><a href="#新建MySQL帐号" class="headerlink" title="新建MySQL帐号"></a>新建MySQL帐号</h2><p>新建账号<code>pt_table_check</code>用于连接主库和从库进行校验：<br><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO pt_table_check@'%' IDENTIFIED BY 'checksum123';</span><br><span class="line">mysql&gt; GRANT CREATE, INSERT, UPDATE, DELETE ON percona_schema.* TO pt_table_check@'%';</span><br></pre></td></tr></table></figure></p><h2 id="执行数据校验"><a href="#执行数据校验" class="headerlink" title="执行数据校验"></a>执行数据校验</h2><p><strong>在主库上执行</strong></p><p>校验表road_to_dba.t_int主从数据的一致性：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; ./bin/pt-table-checksum --socket=/tmp/mysql3376.sock --user=pt_table_check --password=<span class="string">'checksum123'</span> --tables=road_to_dba.t_int --no-check-binlog-format --replicate=percona_schema.checksums</span><br></pre></td></tr></table></figure></p><p>结果：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE</span><br><span class="line">09-19T18:50:19      0      1        9       1       0   0.042 road_to_dba.t_int</span><br></pre></td></tr></table></figure></p><p>可以从DIFFS列看出有一个数据分块的主从数据不一致。</p><h2 id="查看差异汇总"><a href="#查看差异汇总" class="headerlink" title="查看差异汇总"></a>查看差异汇总</h2><p><strong>在从库执行</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT db, tbl, SUM(this_cnt) AS total_rows, COUNT(*) AS chunks</span><br><span class="line">FROM percona_schema.checksums</span><br><span class="line">WHERE (</span><br><span class="line"> master_cnt &lt;&gt; this_cnt</span><br><span class="line"> OR master_crc &lt;&gt; this_crc</span><br><span class="line"> OR ISNULL(master_crc) &lt;&gt; ISNULL(this_crc))</span><br><span class="line">GROUP BY db, tbl;</span><br><span class="line">+<span class="comment">-------------+-------+------------+--------+</span></span><br><span class="line">| db          | tbl   | total_rows | chunks |</span><br><span class="line">+<span class="comment">-------------+-------+------------+--------+</span></span><br><span class="line">| road_to_dba | t_int |         10 |      1 |</span><br><span class="line">+<span class="comment">-------------+-------+------------+--------+</span></span><br><span class="line">1 row in <span class="keyword">set</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><p>从以上查询结果可以看出：</p><blockquote><p>表road_to_dba.t_int总共有一个分块（<code>chunks</code>）的主从数据不一致。</p></blockquote><p>或者</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT * FROM percona_schema.checksums WHERE master_cnt &lt;&gt; this_cnt OR master_crc &lt;&gt; this_crc OR ISNULL(master_crc) &lt;&gt; ISNULL(this_crc);</span><br><span class="line">+<span class="comment">-------------+-------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+</span></span><br><span class="line">| db          | tbl   | chunk | chunk_time | chunk_index | lower_boundary | upper_boundary | this_crc | this_cnt | master_crc | master_cnt | ts                  |</span><br><span class="line">+<span class="comment">-------------+-------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+</span></span><br><span class="line">| road_to_dba | t_int |     1 |   0.000546 | NULL        | NULL           | NULL           | 2e1ed7d3 |       10 | 17818634   |          9 | 2016-09-19 18:50:19 |</span><br><span class="line">+<span class="comment">-------------+-------+-------+------------+-------------+----------------+----------------+----------+----------+------------+------------+---------------------+</span></span><br><span class="line">1 row in <span class="keyword">set</span> (<span class="number">0.00</span> sec)</span><br></pre></td></tr></table></figure><p>从以上查询可以看出：</p><blockquote><p>表road_to_dba.t_int的<code>分块1</code>的主从数据不一致。该分块在主库的行数（<code>master_cnt</code>）为<code>9</code>，在从库的行数（<code>this_cnt</code>）为<code>10</code>；该分块在主库的校验值（<code>master_crc</code>）为<code>17818634</code>，在从库的校验值（<code>this_crc</code>）为<code>2e1ed7d3</code>；</p></blockquote><h1 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h1><ul><li>Percona官方文档：<a href="https://www.percona.com/doc/percona-toolkit/2.2/pt-table-checksum.html" target="_blank" rel="noopener">https://www.percona.com/doc/percona-toolkit/2.2/pt-table-checksum.html</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;软件介绍&quot;&gt;&lt;a href=&quot;#软件介绍&quot; class=&quot;headerlink&quot; title=&quot;软件介绍&quot;&gt;&lt;/a&gt;软件介绍&lt;/h1&gt;&lt;p&gt;pt-table-checksum是Percona Toolkit工具系列中的一个，可以用来检测MySQL主、从数据的一致性。&lt;br&gt;其原理是，在主库执行校验语句（binlog格式为STATEMENT），通过复制传递到从库，如果数据不一致，则主、从会产生不同的校验值，以此来判断主从数据是否一致。&lt;/p&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="Percona Toolkit" scheme="https://db.tyoung.me/tags/Percona-Toolkit/"/>
    
      <category term="pt-table-checksum" scheme="https://db.tyoung.me/tags/pt-table-checksum/"/>
    
      <category term="主从一致性校验" scheme="https://db.tyoung.me/tags/%E4%B8%BB%E4%BB%8E%E4%B8%80%E8%87%B4%E6%80%A7%E6%A0%A1%E9%AA%8C/"/>
    
  </entry>
  
  <entry>
    <title>XtraBackup error：log block numbers mismatch分析处理</title>
    <link href="https://db.tyoung.me/2016/09/how_to_deal_with_xtrabackup_error_log_block_numbers_mismatch/"/>
    <id>https://db.tyoung.me/2016/09/how_to_deal_with_xtrabackup_error_log_block_numbers_mismatch/</id>
    <published>2016-09-11T02:34:24.000Z</published>
    <updated>2020-04-21T15:15:49.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="日志信息"><a href="#日志信息" class="headerlink" title="日志信息"></a>日志信息</h1><p>大清早的起来，打开手机看到Zabbix的邮件提醒，MariaDB数据库备份失败，数据库的备份计划已经正常运行将近一年了，于是对于这次备份失败很是好奇。远程连上服务器，查看XtraBackup备份日志的部分信息如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">160910 00:05:01 Connecting to MySQL server host: localhost, user: xxx, password: <span class="built_in">set</span>, port: xxx, socket: /var/lib/mysql/mysql.sock</span><br><span class="line">Using server version 10.0.23-MariaDB-enterprise-log</span><br><span class="line">innobackupex version 2.3.5 based on MySQL server 5.6.24 Linux (x86_64) (revision id: 45cda89)</span><br><span class="line">incremental backup from 0 is enabled.</span><br><span class="line">xtrabackup: uses posix_fadvise().</span><br><span class="line">xtrabackup: <span class="built_in">cd</span> to /opt/mysql_data</span><br><span class="line">xtrabackup: open files <span class="built_in">limit</span> requested 65535, <span class="built_in">set</span> to 65535</span><br><span class="line">xtrabackup: using the following InnoDB configuration:</span><br><span class="line">xtrabackup:   innodb_data_home_dir = ./</span><br><span class="line">xtrabackup:   innodb_data_file_path = ibdata1:12M:autoextend</span><br><span class="line">xtrabackup:   innodb_log_group_home_dir = ./</span><br><span class="line">xtrabackup:   innodb_log_files_in_group = 2</span><br><span class="line">xtrabackup:   innodb_log_file_size = 50331648</span><br><span class="line">Found and using lsn: 846260275194 <span class="keyword">for</span> name backup-53309-all_databases</span><br><span class="line">xtrabackup: error: <span class="built_in">log</span> block numbers mismatch:</span><br><span class="line">xtrabackup: error: expected <span class="built_in">log</span> block no. 586990567, but got no. 587187167 from the <span class="built_in">log</span> file.</span><br><span class="line">xtrabackup: error: it looks like InnoDB <span class="built_in">log</span> has wrapped around before xtrabackup could process all records due to either <span class="built_in">log</span> copying being too slow, or  <span class="built_in">log</span> files being too small.</span><br><span class="line">xtrabackup: Error: xtrabackup_copy_logfile() failed.</span><br></pre></td></tr></table></figure></p><a id="more"></a><h1 id="原因分析"><a href="#原因分析" class="headerlink" title="原因分析"></a>原因分析</h1><p>主要错误日志：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">xtrabackup: error: <span class="built_in">log</span> block numbers mismatch:</span><br><span class="line">xtrabackup: error: expected <span class="built_in">log</span> block no. 586990567, but got no. 587187167 from the <span class="built_in">log</span> file.</span><br><span class="line">xtrabackup: error: it looks like InnoDB <span class="built_in">log</span> has wrapped around before xtrabackup could process all records due to either <span class="built_in">log</span> copying being too slow, or  <span class="built_in">log</span> files being too small.</span><br></pre></td></tr></table></figure></p><p>从以上错误日志可以看出，大概的意思是说：<br>XtraBackup在顺序拷贝完redo log末尾的数据后，重新从redo log的起始位置去拷贝时，发现起始位置的<code>log block no.</code>与刚才尾部的<code>no.</code>不连续。</p><p>当然日志里也进一步给出了解释：<br>在XtraBackup处理完所有的redo log数据之前，redo log起始位置的数据就被后续写入的log覆盖掉了。原因可能是拷贝redo log的速度太慢了，或者redo log文件的大小设置太小了。</p><p>结合从网上找到的资料，引起以上问题的可能原因如下：</p><ol><li>redo log的文件大小（<code>innodb_log_file_size</code>*<code>innodb_log_files_in_group</code>）设置过小；</li><li>XtraBackup拷贝redo log的速度有些慢（可能受其他的系统任务的比较频繁的磁盘IO影响）；</li><li>如果备份文件是存储在远程文件系统上，则还有可能是受网络带宽较小或拥堵导致；</li></ol><h1 id="本次问题分析"><a href="#本次问题分析" class="headerlink" title="本次问题分析"></a>本次问题分析</h1><p>redo log相关的系统变量：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">innodb_log_files_in_group = 2</span><br><span class="line">innodb_log_file_size = 50331648    <span class="comment"># 48M</span></span><br></pre></td></tr></table></figure></p><p>从以上设置可以看出，MariaDB设置的redo log大小是<code>2 * 48M</code>，文件大小设置的有些小。</p><p>备份文件是存在远程文件系统的，查看了下Zabbix系统监控的当时的网络流量很小，而且此前备份一直是正常的，排除网络带宽和流量拥堵的影响。</p><p>此时又想起了一件事……<br>备份计划是每天00:05开始的，就在上个月我在主库添加了一个定时任务，每天对某个日志表进行归档操作，执行时间也是00:05。<br>应该是这个导致了00:05后redo log的快速循环写入，同时redo log文件设置的总大小又不大，导致XtraBackup在备份的时候，出现错误“log block numbers mismatch”。</p><h1 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h1><p>由于<code>innodb_log_file_size</code>变量不能动态更改，暂时也不能重启数据库更改变量值。所以将XtraBackup的开始时间推迟了一段时间，以错开日志归档时的IO高峰期。</p><p>备份计划推迟后，昨天的备份没有再次出现错误，后续还待进一步观察是否会再次出现此错误。</p><h1 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h1><ul><li>链接1：<a href="https://bugs.launchpad.net/percona-xtrabackup/+bug/1050355" target="_blank" rel="noopener">https://bugs.launchpad.net/percona-xtrabackup/+bug/1050355</a></li><li>链接2：<a href="https://bugs.launchpad.net/percona-xtrabackup/+bug/1206309" target="_blank" rel="noopener">https://bugs.launchpad.net/percona-xtrabackup/+bug/1206309</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;日志信息&quot;&gt;&lt;a href=&quot;#日志信息&quot; class=&quot;headerlink&quot; title=&quot;日志信息&quot;&gt;&lt;/a&gt;日志信息&lt;/h1&gt;&lt;p&gt;大清早的起来，打开手机看到Zabbix的邮件提醒，MariaDB数据库备份失败，数据库的备份计划已经正常运行将近一年了，于是对于这次备份失败很是好奇。远程连上服务器，查看XtraBackup备份日志的部分信息如下：&lt;br&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;160910 00:05:01 Connecting to MySQL server host: localhost, user: xxx, password: &lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt;, port: xxx, socket: /var/lib/mysql/mysql.sock&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Using server version 10.0.23-MariaDB-enterprise-log&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;innobackupex version 2.3.5 based on MySQL server 5.6.24 Linux (x86_64) (revision id: 45cda89)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;incremental backup from 0 is enabled.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: uses posix_fadvise().&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: &lt;span class=&quot;built_in&quot;&gt;cd&lt;/span&gt; to /opt/mysql_data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: open files &lt;span class=&quot;built_in&quot;&gt;limit&lt;/span&gt; requested 65535, &lt;span class=&quot;built_in&quot;&gt;set&lt;/span&gt; to 65535&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: using the following InnoDB configuration:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup:   innodb_data_home_dir = ./&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup:   innodb_data_file_path = ibdata1:12M:autoextend&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup:   innodb_log_group_home_dir = ./&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup:   innodb_log_files_in_group = 2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup:   innodb_log_file_size = 50331648&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Found and using lsn: 846260275194 &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; name backup-53309-all_databases&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: error: &lt;span class=&quot;built_in&quot;&gt;log&lt;/span&gt; block numbers mismatch:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: error: expected &lt;span class=&quot;built_in&quot;&gt;log&lt;/span&gt; block no. 586990567, but got no. 587187167 from the &lt;span class=&quot;built_in&quot;&gt;log&lt;/span&gt; file.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: error: it looks like InnoDB &lt;span class=&quot;built_in&quot;&gt;log&lt;/span&gt; has wrapped around before xtrabackup could process all records due to either &lt;span class=&quot;built_in&quot;&gt;log&lt;/span&gt; copying being too slow, or  &lt;span class=&quot;built_in&quot;&gt;log&lt;/span&gt; files being too small.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;xtrabackup: Error: xtrabackup_copy_logfile() failed.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="MariaDB" scheme="https://db.tyoung.me/tags/MariaDB/"/>
    
      <category term="Percona XtraBackup" scheme="https://db.tyoung.me/tags/Percona-XtraBackup/"/>
    
      <category term="XtraBackup error" scheme="https://db.tyoung.me/tags/XtraBackup-error/"/>
    
      <category term="Percona Toolkit" scheme="https://db.tyoung.me/tags/Percona-Toolkit/"/>
    
  </entry>
  
  <entry>
    <title>MySQL启动方式及多实例</title>
    <link href="https://db.tyoung.me/2016/06/mysql_server_startup_programs_and_mutiple_mysql_instances/"/>
    <id>https://db.tyoung.me/2016/06/mysql_server_startup_programs_and_mutiple_mysql_instances/</id>
    <published>2016-06-25T18:19:26.000Z</published>
    <updated>2020-04-21T15:15:49.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="MySQL启动方式"><a href="#MySQL启动方式" class="headerlink" title="MySQL启动方式"></a>MySQL启动方式</h1><h2 id="mysqld"><a href="#mysqld" class="headerlink" title="mysqld"></a>mysqld</h2><p>启动方式：</p><blockquote><p>本文假设已添加MySQL安装目录<code>/usr/local/mysql/bin</code>至系统环境变量PATH<br>所以在执行MySQL相关命令时，不再切换到MySQL安装目录，或者使用完整路径。</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell &gt; mysqld --user=mysql &amp;</span><br><span class="line"></span><br><span class="line">[1] 23046</span><br><span class="line">2016-06-24 22:57:33 0 [Note] mysqld (mysqld 5.6.29-log) starting as process 23046 ...</span><br></pre></td></tr></table></figure><a id="more"></a><ol><li><code>mysqld</code>，即MySQL服务器。MySQL安装过程中，很多工作是由<code>mysqld</code>来完成的。</li><li>使用<code>mysqld</code>启动MySQL服务器之后，系统仅有一个<code>mysqld</code>进程。如下：<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; ps aux | grep mysqld</span><br><span class="line"></span><br><span class="line">mysql    23046  0.2  9.6 780496 48480 pts/0    Sl   22:57   0:00 mysqld --user=mysql</span><br></pre></td></tr></table></figure></li></ol><h2 id="mysqld-safe"><a href="#mysqld-safe" class="headerlink" title="mysqld_safe"></a>mysqld_safe</h2><p>启动方式：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld_safe --user=mysql &amp;</span><br><span class="line"></span><br><span class="line">[1] 23159</span><br><span class="line">160624 23:11:43 mysqld_safe Logging to <span class="string">'/data/mysql/mysql3376/data/error.log'</span>.</span><br><span class="line">160624 23:11:43 mysqld_safe Starting mysqld daemon with databases from /data/mysql/mysql3376/data</span><br></pre></td></tr></table></figure></p><ol><li><code>mysqld_safe</code>启动时会调用<code>mysqld</code>来启动MySQL服务器</li><li><code>mysqld_safe</code>是<code>mysqld</code>的守护进程，添加了一些安全特性，当MySQL服务器出现错误时会重启<code>mysqld</code>。</li><li>使用<code>mysqld_safe</code>启动MySQL服务器之后，系统有两个进程：<code>mysqld</code>和<code>mysqld_safe</code>。如下：<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; ps aux | grep mysqld</span><br><span class="line"></span><br><span class="line">  root      2892  0.1  0.2 106232  1400 pts/0    S    11:43   0:00 /bin/sh /usr/<span class="built_in">local</span>/mysql/bin/mysqld_safe --user=mysql</span><br><span class="line">  mysql     3934  0.1  9.6 780496 48472 pts/0    Sl   11:43   0:00 /usr/<span class="built_in">local</span>/mysql/bin/mysqld --basedir=/usr/<span class="built_in">local</span>/mysql --datadir=/data/mysql/mysql3376/data --plugin-dir=/usr/<span class="built_in">local</span>/mysql/lib/plugin --user=mysql --<span class="built_in">log</span>-error=/data/mysql/mysql3376/data/error.log --pid-file=/data/mysql/mysql3376/data/node601.pid --socket=/tmp/mysql3376.sock --port=3376</span><br></pre></td></tr></table></figure></li></ol><h2 id="mysql-server"><a href="#mysql-server" class="headerlink" title="mysql.server"></a>mysql.server</h2><p>启动方式：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启动MySQL</span></span><br><span class="line">shell&gt; mysql.server start</span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭MySQL</span></span><br><span class="line">shell&gt; mysql.server stop</span><br></pre></td></tr></table></figure></p><ol><li><code>mysql.server</code>是一个SHELL脚本，通过调用<code>mysqld_safe</code>来启动MySQL；</li><li>使用RPM或其他的Linux系统的包管理器安装MySQL时，<code>mysql.server</code>通常会被安装在<code>/etc/init.d</code>路径下，文件名为<code>mysql</code>或<code>mysqld</code>；</li><li><p>使用二进制包或源码安装时，<code>mysql.server</code>在MySQL安装目录的<code>support-files</code>下，可以手动将其复制到<code>/etc/init.d</code>路径下；</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; cp mysql.server /etc/init.d/mysql</span><br><span class="line">shell&gt; chmod +x /etc/init.d/mysql</span><br></pre></td></tr></table></figure><p>此时也可以使用以下命令来启动和关闭MySQL</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启动</span></span><br><span class="line">shell&gt; service mysql start</span><br><span class="line"><span class="comment"># shell&gt; /etc/init.d/mysql start</span></span><br><span class="line"><span class="comment"># 关闭</span></span><br><span class="line">shell&gt; service mysql stop</span><br><span class="line"><span class="comment"># shell&gt; /etc/init.d/mysql stop</span></span><br><span class="line"><span class="comment"># 重启</span></span><br><span class="line">shell&gt; service mysql restart</span><br><span class="line"><span class="comment"># shell&gt; /etc/init.d/mysql restart</span></span><br></pre></td></tr></table></figure></li><li><p>使用mysql.server启动MySQL服务器之后，系统有两个进程：<code>mysqld</code>和<code>mysqld_safe</code>。如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; ps aux | grep mysqld</span><br><span class="line"></span><br><span class="line">root      4453  0.2  0.2  11472  1388 pts/0    S    12:41   0:00 /bin/sh /usr/<span class="built_in">local</span>/mysql/bin/mysqld_safe --datadir=/data/mysql/mysql3376/data --pid-file=/data/mysql/mysql3376/data/node601.pid</span><br><span class="line">mysql     5508  0.3  9.6 780496 48480 pts/0    Sl   12:41   0:00 /usr/<span class="built_in">local</span>/mysql/bin/mysqld --basedir=/usr/<span class="built_in">local</span>/mysql --datadir=/data/mysql/mysql3376/data --plugin-dir=/usr/<span class="built_in">local</span>/mysql/lib/plugin --user=mysql --<span class="built_in">log</span>-error=/data/mysql/mysql3376/data/error.log --pid-file=/data/mysql/mysql3376/data/node601.pid --socket=/tmp/mysql3376.sock --port=3376</span><br></pre></td></tr></table></figure></li></ol><p>以上为使用<code>mysqld</code>、<code>mysqld_safe</code>、<code>mysql.server</code>进行MySQL单个实例的启动，使用<code>[mysqld_multi]</code>进行MySQL多实例的启动，将会在本文后面进行介绍。</p><h1 id="MySQL配置文件"><a href="#MySQL配置文件" class="headerlink" title="MySQL配置文件"></a>MySQL配置文件</h1><p>在介绍MySQL多实例之前，先介绍下MySQL配置文件。</p><ol><li><p>在启动MySQL时，若没有在命令行显式指定配置文件的路径，默认情况下，MySQL会从以下位置依次读取配置文件。并且，后读取的配置文件中的参数会优先于其前面的配置文件的参数生效。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/etc/my.cnf</span><br><span class="line">/etc/mysql/my.cnf</span><br><span class="line">/usr/<span class="built_in">local</span>/mysql/etc/my.cnf</span><br><span class="line">~/.my.cnf</span><br></pre></td></tr></table></figure><p>可以通过以下命令查看MySQL默认读取的配置文件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld --verbose --<span class="built_in">help</span> | grep -A 5 <span class="string">'Default options'</span></span><br><span class="line"></span><br><span class="line">2016-06-25 12:50:43 0 [Note] mysqld (mysqld 5.6.29-log) starting as process 5602 ...</span><br><span class="line">2016-06-25 12:50:43 5602 [Note] Plugin <span class="string">'FEDERATED'</span> is disabled.</span><br><span class="line">Default options are <span class="built_in">read</span> from the following files <span class="keyword">in</span> the given order:</span><br><span class="line">/etc/my.cnf /etc/mysql/my.cnf /usr/<span class="built_in">local</span>/mysql/etc/my.cnf ~/.my.cnf</span><br></pre></td></tr></table></figure></li><li><p>MySQL配置文件由一个或多个group组成，每个group的名称为要设置参数的MySQL程序的名称或者组名。</p><ul><li>常见的group有：<code>[mysqld]</code>、<code>[mysql]</code>、<code>[client]</code>等。</li></ul></li><li>以MySQL程序命名的group包含的参数，对该程序生效。比如：<ul><li><code>[mysqld]</code>、<code>[mysql]</code>下的参数分别对<code>mysqld</code>服务器程序和<code>mysql</code>客户端程序生效；</li><li><code>[mysqldump]</code>下的参数对mysqldump程序生效；</li><li>等等…</li></ul></li><li><code>[client]</code>分组下的参数，对所有的MySQL客户端程序生效。<ul><li>如果某个参数不能被所有的MySQL客户端程序识别，不要把该参数放在<code>[client]</code>分组下。否则，会引起不能识别该参数的程序报错并退出。</li></ul></li><li>MySQL常用程序读取的配置文件中group名称：<ol><li>mysql：<code>[mysql]</code>、<code>[client]</code></li><li>mysqld：<code>[mysqld]</code>、<code>[server]</code></li><li>mysqld_safe：<code>[mysqld]</code>、 <code>[server]</code>、<code>[mysqld_safe]</code>；为了向后兼容，也读取<code>[safe_mysqld]</code>分组下的参数；</li><li>mysql.server：<code>[mysql.server]</code>、<code>[mysqld]</code>；为了向后兼容，也读取<code>[mysql_server]</code>下的参数；</li></ol></li></ol><h1 id="MySQL多实例"><a href="#MySQL多实例" class="headerlink" title="MySQL多实例"></a>MySQL多实例</h1><h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><ol><li>在同一台服务器上，不同的业务使用不同的实例，互不影响；</li><li>MySQL服务器随着连接数的上升，性能会下降，可以将连接数比较多的单个实例拆分成多个实例；</li><li>多实例在互联网公司比较常用；</li></ol><h2 id="多实例参数"><a href="#多实例参数" class="headerlink" title="多实例参数"></a>多实例参数</h2><p>MySQL多个实例的以下参数应保持不同：</p><ol><li>数据目录：<code>datadir=dir_name</code></li><li>端口：<code>port=port_num</code></li><li>socket文件名称：<code>socket=file_name</code></li><li>pid文件名称：<code>pid-file=file_name</code></li><li>一些日志的名称和路径<ol><li>通用查询日志：<code>general_log_file=file_name</code></li><li>二进制日志：<code>log-bin=file_name</code></li><li>慢查询日志：<code>slow_query_log_file=file_name</code></li><li>错误日志：<code>log-error=file_name</code></li></ol></li></ol><p>默认情况下，pid文件、以及以上各种日志文件，在各实例的数据目录下面，若已设置<code>datadir</code>为不同的目录，可不再显式设置这些选项。</p><p>设置<code>tmpdir</code>为不同的目录，可以方便的识别临时文件是由哪些MySQL实例产生的。当然，这并不是必须要设置的。</p><h2 id="new_instance">安装多实例</h2><p>参照<a href="/2016/06/install_and_initialize_mysql">《MySQL安装和初始化》</a>一文的介绍，现有系统已安装一个端口为<code>3376</code>的实例，在此基础上新增加一个端口为<code>3377</code>的实例。</p><ol><li><p>关键参数对比</p><ol><li><p>端口为3376的实例的参数：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[mysqld]</span><br><span class="line">port = 3376</span><br><span class="line">socket = /tmp/mysql3376.sock</span><br><span class="line">datadir = /data/mysql/mysql3376/data</span><br><span class="line">tmpdir = /data/mysql/mysql3376/tmp</span><br><span class="line"><span class="built_in">log</span>-bin = /data/mysql/mysql3376/logs/mysql-bin</span><br></pre></td></tr></table></figure></li><li><p>端口为3377的实例的参数：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[mysqld]</span><br><span class="line">port = 3377</span><br><span class="line">socket = /tmp/mysql3377.sock</span><br><span class="line">datadir = /data/mysql/mysql3377/data</span><br><span class="line">tmpdir = /data/mysql/mysql3377/tmp</span><br><span class="line"><span class="built_in">log</span>-bin = /data/mysql/mysql3377/logs/mysql-bin</span><br></pre></td></tr></table></figure></li></ol></li><li><p>新建目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mkdir -pv /data/mysql/mysql3377/&#123;data,logs,tmp&#125;</span><br></pre></td></tr></table></figure></li><li><p>修改配置文件</p><ul><li><p>将3376实例的配置文件复制到3377的目录下，并批量修改配置文件中的<code>3376</code>为<code>3377</code>。<br>由于以上各参数值都是由实例相应的端口组成，所以这里只需要替换配置文件中的端口号，即可达到不同实例不同的参数。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; cp /etc/my.cnf /data/mysql/mysql3377/my3377.cnf</span><br><span class="line">shell&gt; <span class="built_in">cd</span> /data/mysql/mysql3377</span><br><span class="line">shell&gt; sed -i <span class="string">'s/3376/3377/g'</span> my3377.cnf</span><br></pre></td></tr></table></figure></li><li><p>替换之后配置文件的参数如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; grep 3377 my3377.cnf</span><br><span class="line"></span><br><span class="line"><span class="comment"># client</span></span><br><span class="line">port            = 3377</span><br><span class="line">socket          = /tmp/mysql3377.sock</span><br><span class="line"><span class="comment"># mysqld</span></span><br><span class="line">port            = 3377</span><br><span class="line">datadir         = /data/mysql/mysql3377/data</span><br><span class="line">tmpdir          = /data/mysql/mysql3377/tmp</span><br><span class="line">socket          = /tmp/mysql3377.sock</span><br><span class="line"><span class="built_in">log</span>-bin     = /data/mysql/mysql3377/logs/mysql-bin</span><br><span class="line">server-id       =1613377</span><br><span class="line">innodb_data_home_dir = /data/mysql/mysql3377/data</span><br><span class="line">innodb_log_group_home_dir = /data/mysql/mysql3377/logs</span><br></pre></td></tr></table></figure></li></ul></li><li><p>修改目录权限</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; chown -R mysql:mysql /data/mysql/mysql3377</span><br><span class="line">shell&gt; ll /data/mysql/mysql3377</span><br><span class="line"></span><br><span class="line">total 4</span><br><span class="line">drwxr-xr-x 2 mysql mysql    6 Jun 25 16:56 data</span><br><span class="line">drwxr-xr-x 2 mysql mysql    6 Jun 25 16:56 logs</span><br><span class="line">-rwxr-xr-x 1 mysql mysql 3020 Jun 25 17:06 my3377.cnf</span><br><span class="line">drwxr-xr-x 2 mysql mysql    6 Jun 25 16:56 tmp</span><br></pre></td></tr></table></figure></li><li><p>初始化MySQL 3377实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; <span class="built_in">cd</span> /usr/<span class="built_in">local</span>/mysql/</span><br><span class="line">shell&gt; ./scripts/mysql_install_db --defaults-file=/data/mysql/mysql3377/my3377.cnf --user=mysql</span><br></pre></td></tr></table></figure></li><li><p>启动3377实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld --defaults-file=/data/mysql/mysql3377/my3377.cnf --user=mysql &amp;</span><br><span class="line"></span><br><span class="line">[2] 6961</span><br><span class="line">2016-06-25 17:40:20 0 [Note] mysqld (mysqld 5.6.29-log) starting as process 6961 ...</span><br></pre></td></tr></table></figure><p>查看后台进程，已启动两个MySQL实例：<code>3376</code>和<code>3377</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; netstat -nalp | grep mysqld</span><br><span class="line">tcp        0      0 :::3376                     :::*                        LISTEN      6857/mysqld         </span><br><span class="line">tcp        0      0 :::3377                     :::*                        LISTEN      6961/mysqld         </span><br><span class="line">unix  2      [ ACC ]     STREAM     LISTENING     23304  6857/mysqld         /tmp/mysql3376.sock</span><br><span class="line">unix  2      [ ACC ]     STREAM     LISTENING     23462  6961/mysqld         /tmp/mysql3377.sock</span><br></pre></td></tr></table></figure></li><li><p>关闭3377实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqladmin -S /tmp/mysql3377.sock -vvv shutdown</span><br><span class="line"></span><br><span class="line">Shutdown signal sent to server;  Waiting <span class="keyword">for</span> pid file to disappear</span><br><span class="line">[2]+  Done                    mysqld --defaults-file=/data/mysql/mysql3377/my3377.cnf --user=mysql</span><br></pre></td></tr></table></figure></li></ol><h2 id="mysqld-multi"><a href="#mysqld-multi" class="headerlink" title="mysqld_multi"></a>mysqld_multi</h2><p>从以上配置3377实例的过程可以看出，可以为每个实例指定单独的配置文件。在启动时，指定对应的配置文件（<code>--defaults-file</code>）；在关闭时，指定实例对应的socket（或者ip和端口），即可分别管理每一个实例。</p><p>而多个实例的管理，也可以采用另一种方法：各个实例的参数都在同一个配置文件里配置，使用<code>mysqld_multi</code>管理这些实例。</p><blockquote><p>这里的“配置文件”可以是默认的<code>/etc/my.cnf</code>，也可以是由<code>--defaults-file</code>指定的。</p></blockquote><h3 id="mysqld-multi相关配置文件"><a href="#mysqld-multi相关配置文件" class="headerlink" title="mysqld_multi相关配置文件"></a>mysqld_multi相关配置文件</h3><p>关于mysqld_multi的配置例子，可以使用命令<code>mysqld_multi --example</code>查看，如下为其中的一部分：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">shell &gt; mysqld_multi --example</span><br><span class="line"></span><br><span class="line">[mysqld_multi]</span><br><span class="line">mysqld     = /usr/<span class="built_in">local</span>/mysql/bin/mysqld_safe</span><br><span class="line">mysqladmin = /usr/<span class="built_in">local</span>/mysql/bin/mysqladmin</span><br><span class="line">user       = multi_admin</span><br><span class="line">password   = my_password</span><br><span class="line"></span><br><span class="line">[mysqld2]</span><br><span class="line">socket     = /tmp/mysql.sock2</span><br><span class="line">port       = 3307</span><br><span class="line">pid-file   = /usr/<span class="built_in">local</span>/mysql/data2/hostname.pid2</span><br><span class="line">datadir    = /usr/<span class="built_in">local</span>/mysql/data2</span><br><span class="line">language   = /usr/<span class="built_in">local</span>/mysql/share/mysql/english</span><br><span class="line">user       = unix_user1</span><br><span class="line"></span><br><span class="line">[mysqld3]</span><br><span class="line">mysqld     = /path/to/mysqld_safe</span><br><span class="line">ledir      = /path/to/mysqld-binary/</span><br><span class="line">mysqladmin = /path/to/mysqladmin</span><br><span class="line">socket     = /tmp/mysql.sock3</span><br><span class="line">port       = 3308</span><br><span class="line">pid-file   = /usr/<span class="built_in">local</span>/mysql/data3/hostname.pid3</span><br><span class="line">datadir    = /usr/<span class="built_in">local</span>/mysql/data3</span><br><span class="line">language   = /usr/<span class="built_in">local</span>/mysql/share/mysql/swedish</span><br><span class="line">user       = unix_user2</span><br></pre></td></tr></table></figure></p><p><code>[mysqld_multi]</code>分组下的参数，对mysqld_multi程序自身生效；<code>[mysqldN]</code>分组下的参数，对特定的实例生效（N为正整数）。</p><ol><li><p><code>[mysqld_multi]</code>分组相关的参数选项如下：</p><ol><li><code>mysqld=prog_name</code><ul><li>用于启动MySQL的程序，可以是<code>mysqld</code>，也可以是<code>mysqld_safe</code></li><li>当mysqld指定为mysqld或者mysqld_safe时，启动实例时，会分别读取这两个程序相应的group的配置文件；</li></ul></li><li><code>mysqladmin=prog_name</code><ul><li>用于关闭MySQL服务的<code>mysqladmin</code>程序路径</li></ul></li><li><p><code>user=user_name</code></p><ul><li>调用<code>mysqladmin</code>时使用的MySQL用户名</li><li>每一个被管理的实例中都需要有此用户名，且密码相同（<em>如果密码不同，无法同时关闭多个实例</em>），且具有<code>SHUTDOWN</code>权限</li><li>可以使用以下命令在每一个实例中新建该用户<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; CREATE USER 'multi_admin'@'localhost' IDENTIFIED BY 'multipass';</span><br><span class="line">mysql&gt; GRANT SHUTDOWN ON *.* TO 'multi_admin'@'localhost';</span><br></pre></td></tr></table></figure></li></ul></li><li><p><code>password=password</code></p><ul><li>调用<code>mysqladmin</code>时，所使用的user的密码</li></ul></li><li><code>log=file_name</code><ul><li>用来记录mysqld_muti的启动日志</li></ul></li></ol></li><li>[mysqld<strong>N</strong>]<ul><li>该分组的参数，对特定的MySQL实例生效</li><li><code>[mysqld]</code>分组下可用的参数，都可以针对各个实例在<code>[mysqldN]</code>分组下再特别指定</li><li>N为正整数，建议N为端口号，便于区分实例的配置文件</li></ul></li><li>[mysqld]、[mysqld_safe]<ul><li>通用设置，对所有的实例都生效</li></ul></li></ol><h3 id="配置本文的3376、3377实例"><a href="#配置本文的3376、3377实例" class="headerlink" title="配置本文的3376、3377实例"></a>配置本文的3376、3377实例</h3><p>在<code>/etc/my.cnf</code>文件添加<code>[mysqld_multi]</code>、<code>[mysqld3376]</code>、<code>[mysqld3377]</code>分组的参数选项，如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">[mysqld_multi]</span><br><span class="line">mysqld = /usr/<span class="built_in">local</span>/mysql/bin/mysqld</span><br><span class="line">mysqladmin = /usr/<span class="built_in">local</span>/mysql/bin/mysqladmin</span><br><span class="line">user = multi_admin</span><br><span class="line">password = multipass</span><br><span class="line"><span class="built_in">log</span> = /data/mysql/multi.log</span><br><span class="line"></span><br><span class="line">[mysqld3376]</span><br><span class="line">port = 3376</span><br><span class="line">socket = /tmp/mysql3376.sock</span><br><span class="line">datadir = /data/mysql/mysql3376/data</span><br><span class="line">tmpdir = /data/mysql/mysql3376/tmp</span><br><span class="line"><span class="built_in">log</span>-bin = /data/mysql/mysql3376/logs/mysql-bin</span><br><span class="line">server-id = 1613376</span><br><span class="line">innodb_data_home_dir = /data/mysql/mysql3376/data</span><br><span class="line">innodb_log_group_home_dir = /data/mysql/mysql3376/logs</span><br><span class="line"><span class="comment"># 必须在此指定user=mysql（mysql为Linux系统用户）</span></span><br><span class="line"><span class="comment"># 或者，在[mysqld]分组下指定全局user=mysql，否则无法启动MySQL</span></span><br><span class="line">user = mysql</span><br><span class="line"></span><br><span class="line">[mysqld3377]</span><br><span class="line">port = 3377</span><br><span class="line">socket = /tmp/mysql3377.sock</span><br><span class="line">datadir = /data/mysql/mysql3377/data</span><br><span class="line">tmpdir = /data/mysql/mysql3377/tmp</span><br><span class="line"><span class="built_in">log</span>-bin = /data/mysql/mysql3377/logs/mysql-bin</span><br><span class="line">server-id = 1613377</span><br><span class="line">innodb_data_home_dir = /data/mysql/mysql3377/data</span><br><span class="line">innodb_log_group_home_dir = /data/mysql/mysql3377/logs</span><br><span class="line">user = mysql</span><br></pre></td></tr></table></figure></p><h3 id="mysqld-multi启动-关闭MySQL实例的方式"><a href="#mysqld-multi启动-关闭MySQL实例的方式" class="headerlink" title="mysqld_multi启动/关闭MySQL实例的方式"></a>mysqld_multi启动/关闭MySQL实例的方式</h3><blockquote><p>可以用来启动/关闭一个、多个或某个范围的实例<br>前提：已在配置文件中定义该实例对应分组的参数<code>[mysqldN]</code></p></blockquote><ol><li><p>单个实例：<code>Ni</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld_multi start Ni</span><br><span class="line">shell&gt; mysqld_multi stop Ni</span><br></pre></td></tr></table></figure></li><li><p>多个实例：<code>Ni,Nj,...,Nk</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld_multi start Ni,Nj,Nk</span><br><span class="line">shell&gt; mysqld_multi stop Ni,Nj,Nk</span><br></pre></td></tr></table></figure></li><li><p>某个范围的多个实例：<code>Ni-Nj</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld_multi start Ni-Nj</span><br><span class="line">shell&gt; mysqld_multi stop Ni-Nj</span><br></pre></td></tr></table></figure></li><li><p>多个分开的实例和某个范围的多个实例：<code>Ni,...,Nj-Nk</code></p><blockquote><p>逗号<code>,</code>，破折号<code>-</code>前后不可以有空格，否则空格后面的字符将会被忽略</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld_multi start Ni,Nj-Nk</span><br><span class="line">shell&gt; mysqld_multi stop Ni,Nj-Nk</span><br></pre></td></tr></table></figure></li></ol><h3 id="启动-关闭本文的3376、3377实例"><a href="#启动-关闭本文的3376、3377实例" class="headerlink" title="启动/关闭本文的3376、3377实例"></a>启动/关闭本文的3376、3377实例</h3><ol><li><p>启动3376实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqld_multi start 3376</span><br></pre></td></tr></table></figure><p>查看3376实例的mysqld进程是否已启动：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; ps aux | grep mysqld</span><br><span class="line"></span><br><span class="line">mysql     9686  0.2  9.6 780496 48484 pts/3    Sl   01:42   0:00 /usr/<span class="built_in">local</span>/mysql/bin/mysqld --port=3376 --socket=/tmp/mysql3376.sock --datadir=/data/mysql/mysql3376/data --tmpdir=/data/mysql/mysql3376/tmp --<span class="built_in">log</span>-bin=/data/mysql/mysql3376/logs/mysql-bin --server-id=1613376 --innodb_data_home_dir=/data/mysql/mysql3376/data --innodb_log_group_home_dir=/data/mysql/mysql3376/logs</span><br></pre></td></tr></table></figure></li><li><p>关闭3376实例</p><ul><li><strong>实际测试时，即使已经在配置文件的<code>[mysqld_multi]</code>分组下指定了password参数的值，关闭MySQL实例时，仍然会报密码错误。需要在命令行显式指定password的值，才能关闭实例。</strong>（原因未知）</li><li><p><code>[mysqld_multi]</code>的log中报错信息如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Stopping MySQL servers</span><br><span class="line">Warning: Using a password on the <span class="built_in">command</span> line interface can be insecure.</span><br><span class="line">^G/usr/<span class="built_in">local</span>/mysql/bin/mysqladmin: connect to server at <span class="string">'localhost'</span> failed</span><br><span class="line">error: <span class="string">'Access denied for user '</span>multi_admin<span class="string">'@'</span>localhost<span class="string">' (using password: YES)'</span></span><br></pre></td></tr></table></figure></li><li><p>使用以下命令关闭实例：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqld_multi stop 3376 --password=multipass</span><br></pre></td></tr></table></figure></li></ul></li><li><p>同时启动3376、3377实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld_multi start 3376,3377</span><br><span class="line">shell&gt; ps aux | grep mysqld</span><br><span class="line"></span><br><span class="line">mysql     9845  1.0  9.6 780496 48468 pts/3    Sl   01:53   0:00 /usr/<span class="built_in">local</span>/mysql/bin/mysqld --port=3376 --socket=/tmp/mysql3376.sock --datadir=/data/mysql/mysql3376/data --tmpdir=/data/mysql/mysql3376/tmp --<span class="built_in">log</span>-bin=/data/mysql/mysql3376/logs/mysql-bin --server-id=1613376 --innodb_data_home_dir=/data/mysql/mysql3376/data --innodb_log_group_home_dir=/data/mysql/mysql3376/logs</span><br><span class="line">mysql     9848  1.0  9.6 780496 48456 pts/3    Sl   01:53   0:00 /usr/<span class="built_in">local</span>/mysql/bin/mysqld --port=3377 --socket=/tmp/mysql3377.sock --datadir=/data/mysql/mysql3377/data --tmpdir=/data/mysql/mysql3377/tmp --<span class="built_in">log</span>-bin=/data/mysql/mysql3377/logs/mysql-bin --server-id=1613377 --innodb_data_home_dir=/data/mysql/mysql3377/data --innodb_log_group_home_dir=/data/mysql/mysql3377/logs</span><br></pre></td></tr></table></figure><p>3376、3377这两个实例的进程已同时启动</p></li><li><p>同时关闭3376、3377实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld_multi stop 3376,3377 --password=multipass</span><br><span class="line">shell&gt; ps aux | grep mysqld</span><br><span class="line"></span><br><span class="line">root      9958  0.0  0.1 103308   852 pts/3    S+   01:55   0:00 grep mysql</span><br></pre></td></tr></table></figure><p>两实例的进程已同时被关闭。</p></li></ol><h1 id="多实例安装——使用现有实例安装"><a href="#多实例安装——使用现有实例安装" class="headerlink" title="多实例安装——使用现有实例安装"></a>多实例安装——使用现有实例安装</h1><p><a href="#new_instance">第3节</a>中介绍的3377实例是全新安装的一个实例，安装完成后还需要进行初始化等操作。</p><p>新的实例的安装也可以在原有实例的数据的基础上进行安装。下面介绍在3377实例的基础上，来安装一个新的3378实例。</p><ol><li><p>新建3378实例的目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mkdir -pv  /data/mysql/mysql3378</span><br></pre></td></tr></table></figure></li><li><p>停止3377实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqladmin -vvv --socket=/tmp/mysql3377.sock shutdown</span><br><span class="line"></span><br><span class="line">Shutdown signal sent to server;  Waiting <span class="keyword">for</span> pid file to disappear</span><br><span class="line">[2]+  Done                    mysqld --defaults-file=/data/mysql/mysql3377/my3377.cnf</span><br></pre></td></tr></table></figure></li><li><p>将3377实例的数据等目录复制到3378目录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; cp -ar /data/mysql/mysql3377/* /data/mysql/mysql3378/</span><br><span class="line">shell&gt; <span class="built_in">cd</span> /data/mysql/mysql3378</span><br><span class="line">shell&gt; ll</span><br><span class="line"></span><br><span class="line">total 8</span><br><span class="line">drwxr-xr-x 4 mysql mysql  121 Jun 26 15:46 data</span><br><span class="line">drwxr-xr-x 2 mysql mysql 4096 Jun 26 15:45 logs</span><br><span class="line">-rwxr-xr-x 1 mysql mysql 3019 Jun 26 15:38 my3377.cnf</span><br><span class="line">drwxr-xr-x 2 mysql mysql    6 Jun 26 15:45 tmp</span><br></pre></td></tr></table></figure></li><li><p>修改3378实例的配置文件：<code>datadir</code>、<code>socket</code>、<code>port</code>等</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; <span class="built_in">cd</span> /data/mysql/mysql3378</span><br><span class="line">shell&gt; mv my3377.cnf my3378.cnf</span><br><span class="line">shell&gt; sed -i <span class="string">'s/3377/3378/g'</span> my3378.cnf</span><br></pre></td></tr></table></figure><p>修改后的配置信息如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; grep 3378  my3378.cnf</span><br><span class="line"></span><br><span class="line">port            = 3378</span><br><span class="line">socket          = /tmp/mysql3378.sock</span><br><span class="line">port            = 3378</span><br><span class="line">datadir         = /data/mysql/mysql3378/data</span><br><span class="line">tmpdir          = /data/mysql/mysql3378/tmp</span><br><span class="line">socket          = /tmp/mysql3378.sock</span><br><span class="line"><span class="built_in">log</span>-bin     = /data/mysql/mysql3378/logs/mysql-bin</span><br><span class="line">server-id       =1613378</span><br><span class="line">innodb_data_home_dir = /data/mysql/mysql3378/data</span><br><span class="line">innodb_log_group_home_dir = /data/mysql/mysql3378/logs</span><br></pre></td></tr></table></figure></li><li><p>删除3378数据目录的<code>auto.cnf</code>文件</p><blockquote><p>此文件为MySQL自动生成的server-uuid信息，需保证每个实例的该信息不同。<br>删除此文件后，mysqld启动时会自动重新生成此文件。</p><blockquote><p>auto.cnf：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[auto]</span><br><span class="line">server-uuid=fccde147-3b71-11e6-967d-0800272bc1fa</span><br></pre></td></tr></table></figure></blockquote></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; <span class="built_in">cd</span> /data/mysql/mysql3378/data/</span><br><span class="line">shell&gt; rm -f auto.cnf</span><br></pre></td></tr></table></figure></li><li><p>启动3378实例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; mysqld --defaults-file=/data/mysql/mysql3378/my3378.cnf --user=mysql &amp;</span><br><span class="line"></span><br><span class="line">[1] 3191</span><br><span class="line">2016-06-26 16:18:26 0 [Note] mysqld (mysqld 5.6.29-log) starting as process 3191 ...</span><br></pre></td></tr></table></figure><p>确认实例是否启动成功：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shell&gt; ps aux | grep mysqld</span><br><span class="line"></span><br><span class="line">mysql     3191  1.0  9.6 780496 48464 pts/2    Sl   16:18   0:00 mysqld --defaults-file=/data/mysql/mysql3378/my3378.cnf --user=mysql</span><br></pre></td></tr></table></figure></li></ol><h1 id="附件"><a href="#附件" class="headerlink" title="附件"></a>附件</h1><ol><li>3377实例单独的配置文件：<code>my3377.cnf</code><br>链接：<a href="http://pan.baidu.com/s/1nvlKAet" target="_blank" rel="noopener">http://pan.baidu.com/s/1nvlKAet</a> 密码：wv0o</li><li>使用mysqld_multi管理多实例时的配置文件：<code>/etc/my.cnf</code><br>链接：<a href="http://pan.baidu.com/s/1kUBWQTh" target="_blank" rel="noopener">http://pan.baidu.com/s/1kUBWQTh</a> 密码：vv99</li></ol><h1 id="声明"><a href="#声明" class="headerlink" title="声明"></a>声明</h1><p>本文部分内容来自<strong>知数堂远程培训：</strong><a href="https://zhishuedu.taobao.com/" target="_blank" rel="noopener">https://zhishuedu.taobao.com/</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;MySQL启动方式&quot;&gt;&lt;a href=&quot;#MySQL启动方式&quot; class=&quot;headerlink&quot; title=&quot;MySQL启动方式&quot;&gt;&lt;/a&gt;MySQL启动方式&lt;/h1&gt;&lt;h2 id=&quot;mysqld&quot;&gt;&lt;a href=&quot;#mysqld&quot; class=&quot;headerlink&quot; title=&quot;mysqld&quot;&gt;&lt;/a&gt;mysqld&lt;/h2&gt;&lt;p&gt;启动方式：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;本文假设已添加MySQL安装目录&lt;code&gt;/usr/local/mysql/bin&lt;/code&gt;至系统环境变量PATH&lt;br&gt;所以在执行MySQL相关命令时，不再切换到MySQL安装目录，或者使用完整路径。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;shell &amp;gt; mysqld --user=mysql &amp;amp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;[1] 23046&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2016-06-24 22:57:33 0 [Note] mysqld (mysqld 5.6.29-log) starting as process 23046 ...&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="MySQL启动方式" scheme="https://db.tyoung.me/tags/MySQL%E5%90%AF%E5%8A%A8%E6%96%B9%E5%BC%8F/"/>
    
      <category term="MySQL多实例" scheme="https://db.tyoung.me/tags/MySQL%E5%A4%9A%E5%AE%9E%E4%BE%8B/"/>
    
  </entry>
  
  <entry>
    <title>MySQL安装和初始化</title>
    <link href="https://db.tyoung.me/2016/06/install_and_initialize_mysql/"/>
    <id>https://db.tyoung.me/2016/06/install_and_initialize_mysql/</id>
    <published>2016-06-21T08:19:23.000Z</published>
    <updated>2020-04-21T15:15:48.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="系统详情"><a href="#系统详情" class="headerlink" title="系统详情"></a>系统详情</h1><ul><li>系统：CentOS 6.7</li><li>数据库版本：5.6.29-log MySQL Community Server (GPL)</li></ul><p><em>以下操作、介绍仅针对CentOS 6发行版本，其他发行版本的Linux可能有细微变化。</em></p><a id="more"></a><h1 id="安装方法介绍"><a href="#安装方法介绍" class="headerlink" title="安装方法介绍"></a>安装方法介绍</h1><p>MySQL安装方法主要有以下几种：</p><ol><li>二进制包安装（<code>Generic Binaries</code>）<ul><li>安装方法较简单，且可以自定义安装目录</li></ul></li><li>安装针对特定Linux发行版预编译好的软件包（<em>如CentOS的rpm软件包，Ubuntu的deb软件包等</em>）<ul><li>使用此方法安装，一般需要先手动解决各软件包的依赖关系，比较麻烦</li></ul></li><li>MySQL官方软件源安装（<em>一般，不同的Linux发行版对应不同的软件源，比如CentOS系统对应的是yum源</em>）<ul><li>使用此方法安装比较简单，只需在系统添加软件源，再执行一条安装命令即可搞定（如：<code>yum install mysql-community-server</code>）</li><li>但当在同一个系统，同时安装多个MySQL版本时，如果不清楚YUM源的安装路径及逻辑，容易造成混乱</li></ul></li><li>编译源码安装<ul><li>需要自己动手编译</li><li>且对于新手来说，自己编译的MySQL未必会比官方已经编译好的二进制包/软件包好</li><li>除非对于MySQL默认的功能、参数有个性化需求需要修改，不推荐编译安装</li></ul></li></ol><p>本文主要介绍使用二进制包安装MySQL，其他安装方法的详细操作，可参考官方文档：<a href="http://dev.mysql.com/doc/refman/5.6/en/installing.html" target="_blank" rel="noopener">http://dev.mysql.com/doc/refman/5.6/en/installing.html</a></p><h1 id="下载MySQL二进制包"><a href="#下载MySQL二进制包" class="headerlink" title="下载MySQL二进制包"></a>下载MySQL二进制包</h1><h2 id="下载链接"><a href="#下载链接" class="headerlink" title="下载链接"></a>下载链接</h2><ul><li>MySQL官方下载链接：<ul><li>下载主页：<a href="http://dev.mysql.com/downloads/mysql/" target="_blank" rel="noopener">http://dev.mysql.com/downloads/mysql/</a></li><li>5.6.29版本链接：<a href="http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.29-linux-glibc2.5-x86_64.tar.gz" target="_blank" rel="noopener">http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.29-linux-glibc2.5-x86_64.tar.gz</a></li></ul></li><li>如果下载速度较慢，可以使用sohu镜像下载：  <ul><li>下载主页：<a href="http://mirrors.sohu.com/mysql/MySQL-5.6/" target="_blank" rel="noopener">http://mirrors.sohu.com/mysql/MySQL-5.6/</a></li></ul></li></ul><h2 id="下载MySQL"><a href="#下载MySQL" class="headerlink" title="下载MySQL"></a>下载MySQL</h2><p>可以在Windows系统下载后，上传到服务器；也可以直接在Linux服务器上执行以下命令，进行下载：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.29-linux-glibc2.5-x86_64.tar.gz</span><br></pre></td></tr></table></figure></p><h1 id="安装MySQL，及进行初始化"><a href="#安装MySQL，及进行初始化" class="headerlink" title="安装MySQL，及进行初始化"></a>安装MySQL，及进行初始化</h1><blockquote><p>以下命令需使用<strong>root权限</strong>执行。</p></blockquote><h2 id="新建程序安装目录"><a href="#新建程序安装目录" class="headerlink" title="新建程序安装目录"></a>新建程序安装目录</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir -pv /opt/mysql</span><br></pre></td></tr></table></figure><h2 id="解压安装包至安装目录"><a href="#解压安装包至安装目录" class="headerlink" title="解压安装包至安装目录"></a>解压安装包至安装目录</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xvzf mysql-5.6.29-linux-glibc2.5-x86_64.tar.gz -C /opt/mysql</span><br></pre></td></tr></table></figure><h2 id="新建软链接mysql，链接至mysql-5-6-29-linux-glibc2-5-x86-64目录"><a href="#新建软链接mysql，链接至mysql-5-6-29-linux-glibc2-5-x86-64目录" class="headerlink" title="新建软链接mysql，链接至mysql-5.6.29-linux-glibc2.5-x86_64目录"></a>新建软链接mysql，链接至mysql-5.6.29-linux-glibc2.5-x86_64目录</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ln -sv /opt/mysql/mysql-5.6.29-linux-glibc2.5-x86_64 /usr/<span class="built_in">local</span>/mysql</span><br></pre></td></tr></table></figure><h2 id="新建mysql用户和组"><a href="#新建mysql用户和组" class="headerlink" title="新建mysql用户和组"></a>新建mysql用户和组</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">groupadd mysql</span><br><span class="line">useradd -g mysql -r -s /sbin/nologin mysql</span><br></pre></td></tr></table></figure><h2 id="新建MySQL数据、日志、tmp目录"><a href="#新建MySQL数据、日志、tmp目录" class="headerlink" title="新建MySQL数据、日志、tmp目录"></a>新建MySQL数据、日志、tmp目录</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 此处本人以MySQL端口3376为文件夹后缀，便于区分不同端口的MySQL实例的数据目录</span></span><br><span class="line"><span class="comment"># 一次性创建3个目录（逗号后面不能有空格），-p 递归创建目录</span></span><br><span class="line">mkdir -pv /data/mysql/mysql3376/&#123;data,logs,tmp&#125;</span><br></pre></td></tr></table></figure><h2 id="修改数据目录的所有者、组为mysql"><a href="#修改数据目录的所有者、组为mysql" class="headerlink" title="修改数据目录的所有者、组为mysql"></a>修改数据目录的所有者、组为mysql</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chown -R mysql:mysql /data/mysql</span><br></pre></td></tr></table></figure><h2 id="添加、修改MySQL配置文件my-cnf"><a href="#添加、修改MySQL配置文件my-cnf" class="headerlink" title="添加、修改MySQL配置文件my.cnf"></a>添加、修改MySQL配置文件<code>my.cnf</code></h2><blockquote><p>可下载使用本文提供的<code>my.cnf</code>：  </p><blockquote><p>链接：<a href="http://pan.baidu.com/s/1slP7LCx" target="_blank" rel="noopener">http://pan.baidu.com/s/1slP7LCx</a> 密码：7oib</p></blockquote><p>也可使用自己的<code>my.cnf</code></p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cp ./my.cnf /etc/</span><br></pre></td></tr></table></figure><p>配置文件中的关键参数如下，其他见附件：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[client]</span><br><span class="line">port            = 3376</span><br><span class="line">socket          = /tmp/mysql3376.sock</span><br><span class="line"></span><br><span class="line"><span class="comment"># The MySQL server</span></span><br><span class="line">[mysqld]</span><br><span class="line">port            = 3376</span><br><span class="line">basedir         = /usr/<span class="built_in">local</span>/mysql</span><br><span class="line">datadir         = /data/mysql/mysql3376/data</span><br><span class="line">socket          = /tmp/mysql3376.sock</span><br></pre></td></tr></table></figure></p><h2 id="初始化数据目录datadir"><a href="#初始化数据目录datadir" class="headerlink" title="初始化数据目录datadir"></a>初始化数据目录<code>datadir</code></h2><ul><li>使用二进制包安装，和源码编译安装时，需要初始化数据目录</li><li>一般情况下，仅在第一次安装MySQL时，需要初始化数据目录</li><li>使用<code>mysql_install_db</code>进行初始化</li><li>初始化数据目录时，不会覆盖已有的权限表信息和已有的数据</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 注意指定`user`参数值为`mysql`</span></span><br><span class="line"><span class="built_in">cd</span> /usr/<span class="built_in">local</span>/mysql</span><br><span class="line">./scripts/mysql_install_db --defaults-file=/etc/my.cnf --user=mysql</span><br></pre></td></tr></table></figure><p>执行以上命令后，若出现类似于以下的输出，包含两个<code>OK</code>，则说明初始化成功。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Installing MySQL system tables...2016-06-20 23:39:36 0 [Note] ./bin/mysqld (mysqld 5.6.29-log) starting as process 1866 ...</span><br><span class="line">OK</span><br><span class="line"></span><br><span class="line">Filling <span class="built_in">help</span> tables...2016-06-20 23:39:43 0 [Note] ./bin/mysqld (mysqld 5.6.29-log) starting as process 1912 ...</span><br><span class="line">OK</span><br><span class="line"></span><br><span class="line">To start mysqld at boot time you have to copy</span><br><span class="line">support-files/mysql.server to the right place <span class="keyword">for</span> your system</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p><h1 id="MySQL安装的后续设置"><a href="#MySQL安装的后续设置" class="headerlink" title="MySQL安装的后续设置"></a>MySQL安装的后续设置</h1><h2 id="添加系统环境变量"><a href="#添加系统环境变量" class="headerlink" title="添加系统环境变量"></a>添加系统环境变量</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 建议直接在 /etc/profile.d/ 目录新增 mysql.sh 文件设置环境变量，而不是直接在 /etc/profile 文件里添加环境变量</span></span><br><span class="line"><span class="comment"># 以免操作错误，清空了 /etc/profile，造成系统问题</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"export PATH=\$PATH:/usr/local/mysql/bin"</span> &gt; /etc/profile.d/mysql.sh</span><br><span class="line"><span class="built_in">source</span> /etc/profile.d/mysql.sh</span><br></pre></td></tr></table></figure><p>添加环境变量后，可以直接在系统任意位置运行<code>mysql</code>、<code>mysqld</code>等命令，而不用再在执行这些命令前，切换到MySQL安装目录<code>/usr/local/mysql/bin</code>。</p><h2 id="添加自启动服务"><a href="#添加自启动服务" class="headerlink" title="添加自启动服务"></a>添加自启动服务</h2><blockquote><p>实际生产环境不建议自启动MySQL  </p><blockquote><ul><li>线上库本着一个原则，出错了就停下来，如果开自动启动，出现异常了就无法感知出来</li><li>可以自己写脚本自动修复错误后，自动/批量启动</li></ul></blockquote></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /usr/<span class="built_in">local</span>/mysql</span><br><span class="line">cp ./support-files/mysql.server /etc/init.d/mysql</span><br><span class="line">chkconfig --add mysql</span><br><span class="line">chkconfig mysql on</span><br></pre></td></tr></table></figure><h1 id="启动MySQL"><a href="#启动MySQL" class="headerlink" title="启动MySQL"></a>启动MySQL</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqld --user=mysql &amp;</span><br></pre></td></tr></table></figure><ol><li>若没有报错信息，则基本说明MySQL启动成功</li><li><p>使用以下命令查看是否存在MySQL进程  </p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps aux | grep mysql</span><br></pre></td></tr></table></figure><p>如下，存在mysqld进程，说明启动成功</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@node601 ~]<span class="comment"># ps aux | grep mysql</span></span><br><span class="line">mysql     1972  0.0  9.6 780496 48472 pts/1    Sl   14:56   0:00 mysqld --user=mysql</span><br></pre></td></tr></table></figure></li><li><p>如果未启动成功，可查看错误日志里的<code>ERROR</code>信息，确认原因  </p><ul><li>错误日志默认在<code>datadir</code>文件夹，路径：<code>/data/mysql/mysql3376/data/</code></li><li>错误日志默认名称为<code>`hostname`.error</code>，我的配置文件里指定了错误日志名称<code>log-error</code>为<code>error.log</code></li></ul></li><li><p>MySQL启动不起来，很多时候是由于权限设置不当引起的，还有可能是以下一些原因：</p><ol><li><p>防火墙没有开启MySQL的端口，建议新手直接关闭防火墙</p><ul><li><p>CentOS 6 关闭iptables：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">service iptables stop</span><br><span class="line">chkconfig iptables off</span><br></pre></td></tr></table></figure><p>检查iptables是否关闭自启动，如下全为off，则说明已关闭</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@node601 data]<span class="comment"># chkconfig --list iptables </span></span><br><span class="line">iptables           0:off    1:off    2:off    3:off    4:off    5:off    6:off</span><br></pre></td></tr></table></figure></li><li><p>CentOS 7 关闭firewalld.service</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">systemctl stop firewalld.service</span><br><span class="line">systemctl <span class="built_in">disable</span> firewalld.service</span><br></pre></td></tr></table></figure></li></ul></li><li><p>selinux未关闭，需关闭selinux</p><ol><li>检查selinux是否关闭：<code>getenforce</code><br>输出结果若为<code>Enforcing</code>则说明未关闭；若为<code>Disabled</code>，则说明已关闭。</li><li><p>临时关闭selinux（<em>重启后失效</em>）</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">setenforce permissive</span><br></pre></td></tr></table></figure></li><li><p>永久关闭selinux</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/sysconfig/selinux</span><br></pre></td></tr></table></figure><p>修改<code>SELINUX=disabled</code></p></li></ol></li></ol></li></ol><h1 id="测试MySQL"><a href="#测试MySQL" class="headerlink" title="测试MySQL"></a>测试MySQL</h1><h2 id="查看错误日志是不是有ERROE错误信息"><a href="#查看错误日志是不是有ERROE错误信息" class="headerlink" title="查看错误日志是不是有ERROE错误信息"></a>查看错误日志是不是有<code>ERROE</code>错误信息</h2><p>若没有<code>ERROR</code>，则说明启动正常（<em>搜索日志中是否存在<code>ERROR</code>字段</em>）</p><h2 id="查看MySQL-Server的版本"><a href="#查看MySQL-Server的版本" class="headerlink" title="查看MySQL Server的版本"></a>查看MySQL Server的版本</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mysqladmin -u root -p version</span><br><span class="line"><span class="comment"># 没有设置root密码的话，可以直接使用以下命令查询</span></span><br><span class="line"><span class="comment"># mysqladmin version</span></span><br></pre></td></tr></table></figure><p>输出信息如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">[root@node601 ~]<span class="comment"># mysqladmin version</span></span><br><span class="line">mysqladmin  Ver 8.42 Distrib 5.6.29, <span class="keyword">for</span> linux-glibc2.5 on x86_64</span><br><span class="line">Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.</span><br><span class="line"></span><br><span class="line">Oracle is a registered trademark of Oracle Corporation and/or its</span><br><span class="line">affiliates. Other names may be trademarks of their respective</span><br><span class="line">owners.</span><br><span class="line"></span><br><span class="line">Server version        5.6.29-log</span><br><span class="line">Protocol version    10</span><br><span class="line">Connection        Localhost via UNIX socket</span><br><span class="line">UNIX socket        /tmp/mysql3376.sock</span><br><span class="line">Uptime:            1 min 28 sec</span><br><span class="line"></span><br><span class="line">Threads: 1  Questions: 2  Slow queries: 0  Opens: 70  Flush tables: 1  Open tables: 63  Queries per second avg: 0.022</span><br></pre></td></tr></table></figure></p><p>错误日志无<code>ERROR</code>信息，及以上命令输出信息正常，则说明MySQL已正常启动，MySQL连接正常。</p><h2 id="关闭MySQL"><a href="#关闭MySQL" class="headerlink" title="关闭MySQL"></a>关闭MySQL</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mysqladmin -vvv shutdown</span><br><span class="line"><span class="comment"># 指定socket</span></span><br><span class="line"><span class="comment"># mysqladmin -vvv -S /tmp/mysql3376.sock shutdown</span></span><br></pre></td></tr></table></figure><p>输出如下：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@node601 data]<span class="comment"># mysqladmin -vvv shutdown</span></span><br><span class="line">Shutdown signal sent to server;  Waiting <span class="keyword">for</span> pid file to disappear</span><br></pre></td></tr></table></figure></p><h1 id="巩固MySQL安全"><a href="#巩固MySQL安全" class="headerlink" title="巩固MySQL安全"></a>巩固MySQL安全</h1><p>MySQL安装后，需要执行以下操作，来增强数据库的安全性</p><ol><li>删除匿名用户</li><li>移除任何人都可以访问<code>test</code>及<code>test_</code>开头的库的授权</li><li>删除test库</li><li>设置root密码</li></ol><p>可以通过使用以下命令，自动执行以上操作：<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 需要先启动MySQL</span></span><br><span class="line">mysqld --user=mysql &amp;</span><br><span class="line"><span class="comment"># 由于只能使用默认的socket '/tmp/mysql.sock'连接server，无法使用自定义路径的/tmp/mysql3376.sock</span></span><br><span class="line"><span class="comment"># 所以先新建一个软链接至/tmp/mysql3376.sock，再执行mysql_secure_installation</span></span><br><span class="line">ln -s /tmp/mysql3376.sock /tmp/mysql.sock</span><br><span class="line">mysql_secure_installation</span><br><span class="line"><span class="comment"># 执行完，再删除掉软链接</span></span><br><span class="line">rm -f /tmp/mysql.sock</span><br></pre></td></tr></table></figure></p><h1 id="附件"><a href="#附件" class="headerlink" title="附件"></a>附件</h1><p>可以从以下百度网盘分享，下载以下列出的文件，上传到服务器的同一个目录，执行以下命令，进行一键安装和初始化。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">source</span> install_mysql.sh</span><br></pre></td></tr></table></figure></p><ul><li>链接：<a href="http://pan.baidu.com/s/1i5Jc0Qx" target="_blank" rel="noopener">http://pan.baidu.com/s/1i5Jc0Qx</a> ，密码：6xxr</li></ul><p>文件列表：</p><ol><li>MySQL二进制安装包<code>mysql-5.6.29-linux-glibc2.5-x86_64.tar.gz</code></li><li>MySQL配置文件<code>my.cnf</code></li><li>安装脚本<code>install_mysql.sh</code></li></ol><h1 id="声明"><a href="#声明" class="headerlink" title="声明"></a>声明</h1><p>本文部分内容来自<strong>知数堂远程培训：</strong><a href="https://zhishuedu.taobao.com/" target="_blank" rel="noopener">https://zhishuedu.taobao.com/</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;系统详情&quot;&gt;&lt;a href=&quot;#系统详情&quot; class=&quot;headerlink&quot; title=&quot;系统详情&quot;&gt;&lt;/a&gt;系统详情&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;系统：CentOS 6.7&lt;/li&gt;
&lt;li&gt;数据库版本：5.6.29-log MySQL Community Server (GPL)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;以下操作、介绍仅针对CentOS 6发行版本，其他发行版本的Linux可能有细微变化。&lt;/em&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="MySQL安装" scheme="https://db.tyoung.me/tags/MySQL%E5%AE%89%E8%A3%85/"/>
    
  </entry>
  
  <entry>
    <title>MySQL迁移到MariaDB</title>
    <link href="https://db.tyoung.me/2016/03/migrate_mysql_to_mariadb/"/>
    <id>https://db.tyoung.me/2016/03/migrate_mysql_to_mariadb/</id>
    <published>2016-03-12T12:00:00.000Z</published>
    <updated>2020-04-21T15:15:48.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="业务场景"><a href="#业务场景" class="headerlink" title="业务场景"></a>业务场景</h1><p>为了后期数据库管理方便，统一公司当前使用的MySQL数据库版本（当前存在MySQL和MariaDB同时使用的情况），需要将某项目的MySQL数据库替换为MariaDB。<br><a id="more"></a></p><h1 id="服务器详情"><a href="#服务器详情" class="headerlink" title="服务器详情"></a>服务器详情</h1><ul><li>操作系统：CentOS 7</li><li>MySQL版本：MySQL 5.5.8（二进制包安装）</li><li>MariaDB版本：MariaDB 10.0.23（YUM安装）</li></ul><h1 id="执行步骤"><a href="#执行步骤" class="headerlink" title="执行步骤"></a>执行步骤</h1><p>为了降低替换风险，需保持旧有的MySQL服务和新安装的MariaDB服务同时运行，待测试确认MariaDB没有问题后，再停止原有MySQL服务，完全切换到MariaDB。</p><p><strong>主要操作为：</strong><br>在项目的测试服务器上安装MariaDB数据库，且MariaDB和MySQL使用不同的配置文件和数据目录，将MySQL的所有数据（含权限信息）迁移到MariaDB，保持MySQL和MariaDB同时运行。</p><h2 id="调整MySQL服务读取的配置文件路径"><a href="#调整MySQL服务读取的配置文件路径" class="headerlink" title="调整MySQL服务读取的配置文件路径"></a>调整MySQL服务读取的配置文件路径</h2><p>由于MySQL读取的是默认配置文件/etc/my.cnf，为了使MySQL和MariaDB配置文件互不影响，采取两个DB服务分别读取不同配置文件的方法。将MySQL配置文件路径调整为/opt/mysql/my.cnf</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 复制配置文件</span></span><br><span class="line">shell &gt; cp /etc/my.cnf /opt/mysql/my.cnf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭MySQL服务后并重启，以读取新路径的配置文件</span></span><br><span class="line">shell &gt; ./bin/mysqld_safe --defaults-file=/opt/mysql/my.cnf --user=mysql</span><br></pre></td></tr></table></figure><h2 id="安装MariaDB-Enterprise（YUM）"><a href="#安装MariaDB-Enterprise（YUM）" class="headerlink" title="安装MariaDB Enterprise（YUM）"></a>安装MariaDB Enterprise（YUM）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># MariaDB源配置可参考 https://mariadb.com/my_portal/download</span></span><br><span class="line">shell &gt; yum install MariaDB-server MariaDB-client</span><br></pre></td></tr></table></figure><h2 id="修改MariaDB配置文件（-etc-my-cnf-d-mariadb-enterprise-cnf）"><a href="#修改MariaDB配置文件（-etc-my-cnf-d-mariadb-enterprise-cnf）" class="headerlink" title="修改MariaDB配置文件（/etc/my.cnf.d/mariadb-enterprise.cnf）"></a>修改MariaDB配置文件（/etc/my.cnf.d/mariadb-enterprise.cnf）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 修改端口和数据目录</span></span><br><span class="line">port = 3308</span><br><span class="line">datadir = /opt/mysql_data</span><br></pre></td></tr></table></figure><h2 id="将MySQL数据目录下的所有文件复制到MariaDB数据目录（复制数据时，需停止MySQL服务）"><a href="#将MySQL数据目录下的所有文件复制到MariaDB数据目录（复制数据时，需停止MySQL服务）" class="headerlink" title="将MySQL数据目录下的所有文件复制到MariaDB数据目录（复制数据时，需停止MySQL服务）"></a>将MySQL数据目录下的所有文件复制到MariaDB数据目录（复制数据时，需停止MySQL服务）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell &gt; cp -aR /opt/mysql/data/* /opt/mysql_data/</span><br></pre></td></tr></table></figure><h2 id="启动MariaDB服务"><a href="#启动MariaDB服务" class="headerlink" title="启动MariaDB服务"></a>启动MariaDB服务</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell &gt; service mysql start</span><br></pre></td></tr></table></figure><h2 id="运行mysql-upgrade"><a href="#运行mysql-upgrade" class="headerlink" title="运行mysql_upgrade"></a>运行mysql_upgrade</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell &gt; mysql_upgrade --verbose --port=3308 --protocol=tcp -uroot -p</span><br></pre></td></tr></table></figure><p>该程序执行完成后，MySQL权限表和其他的表会进行一些相应的转换，MySQL成功迁移到MariaDB。</p><h2 id="查看系统进程，MySQL和MariaDB服务同时在运行"><a href="#查看系统进程，MySQL和MariaDB服务同时在运行" class="headerlink" title="查看系统进程，MySQL和MariaDB服务同时在运行"></a>查看系统进程，MySQL和MariaDB服务同时在运行</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">shell &gt; ps -aux | grep mysql</span><br></pre></td></tr></table></figure><p><img src="/static/post_images/migrate_mysql_to_mariadb_1.png" alt="migrate_mysql_to_mariadb_1"></p><h1 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h1><ol><li><a href="https://mariadb.com/kb/en/mariadb/upgrading-to-mariadb-from-mysql-50-or-older/" title="Upgrading to MariaDB From MySQL 5.0 or Older" target="_blank" rel="noopener">Upgrading to MariaDB From MySQL 5.0 or Older</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;业务场景&quot;&gt;&lt;a href=&quot;#业务场景&quot; class=&quot;headerlink&quot; title=&quot;业务场景&quot;&gt;&lt;/a&gt;业务场景&lt;/h1&gt;&lt;p&gt;为了后期数据库管理方便，统一公司当前使用的MySQL数据库版本（当前存在MySQL和MariaDB同时使用的情况），需要将某项目的MySQL数据库替换为MariaDB。&lt;br&gt;
    
    </summary>
    
      <category term="MySQL" scheme="https://db.tyoung.me/categories/MySQL/"/>
    
    
      <category term="MySQL" scheme="https://db.tyoung.me/tags/MySQL/"/>
    
      <category term="MariaDB" scheme="https://db.tyoung.me/tags/MariaDB/"/>
    
  </entry>
  
</feed>
