彼岸荼蘼 發表於 2025-12-22 15:47:00

MySQL 在哪些场景下不会写 binlog

<h1 data-tool="mdnice编辑器"><span style="color: rgba(0, 128, 0, 1)">背景</span></h1>
<p data-tool="mdnice编辑器"><span>在 MySQL 中,慢日志不仅可以记录在文件中,还可以记录在表中。具体是记录在文件还是表中是由<code><span>log_output</span></code><span>参数决定的。</span></span></p>
<p data-tool="mdnice编辑器"><span>该参数默认为<code><span>FILE</span></code><span>,即慢日志默认会记录在文件中。如果参数中包含<code><span>TABLE</span></code><span>,则慢日志还会记录在<code><span>mysql.slow_log</span></code><span>中,而<code><span>mysql.slow_log</span></code><span>使用的是 CSV 存储引擎。</span></span></span></span></span></p>
<p data-tool="mdnice编辑器"><span>最初研究这一问题,是为了确认在主从复制以及组复制(MGR)环境下,<code><span>mysql.slow_log</span></code><span>表中的慢日志是否会同步到其他节点。</span></span></p>
<p data-tool="mdnice编辑器"><span>随着分析的深入,发现 MySQL 实际上提供了多种机制和开关,用于确保操作不会写入 binlog。</span></p>
<p data-tool="mdnice编辑器"><span>由于&nbsp;<strong>ROW 格式</strong><span>&nbsp;是目前最常用的 binlog 格式,本文将从&nbsp;<strong>ROW 模式下 MySQL 判断操作是否写入 binlog 的实现逻辑</strong><span>&nbsp;入手,逐步引出相关控制开关,并分析它们各自的使用场景。</span></span></span></p>
<h1 data-tool="mdnice编辑器"><span style="color: rgba(0, 128, 0, 1)">ROW 格式下判断操作是否写入 binlog 的实现逻辑</span></h1>
<p data-tool="mdnice编辑器"><span>在 ROW 格式下,将数据变化记录到 binlog 的核心是在<code><span>binlog_log_row</span></code><span>函数中实现的:</span></span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>int<span>&nbsp;<span>binlog_log_row<span>(TABLE *table,&nbsp;<span>const<span>&nbsp;uchar *before_record,<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span>const<span>&nbsp;uchar *after_record, Log_func *log_func)<span>&nbsp;<span>{<span><br>bool<span>&nbsp;error =&nbsp;false<span>;<span><br><span>&nbsp; THD *const<span>&nbsp;thd = table-&gt;in_use;<span><br>// 判断当前操作是否需要写入 binlog<span><br>if<span>&nbsp;(check_table_binlog_row_based(thd, table)) {<span><br><span>&nbsp; &nbsp; ...<span><br><span>&nbsp; &nbsp;&nbsp;if<span>&nbsp;(likely(!(error = write_locked_table_maps(thd)))) {<span><br><span>&nbsp; &nbsp; &nbsp;&nbsp;boolconst<span>&nbsp;has_trans = thd-&gt;lex-&gt;sql_command == SQLCOM_CREATE_TABLE ||<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;table-&gt;file-&gt;has_transactions();<span><br><span>&nbsp; &nbsp; &nbsp;&nbsp;// 根据操作类型,将行镜像写入 binlog<span><br><span>&nbsp; &nbsp; &nbsp; error = (*log_func)(thd, table, has_trans, before_record, after_record);<span><br><span>&nbsp; &nbsp; }<span><br><span>&nbsp; }<span><br><span><br>return<span>&nbsp;error ? HA_ERR_RBR_LOGGING_FAILED :&nbsp;0<span>;<span><br><span>}<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>首先调用&nbsp;<code><span>check_table_binlog_row_based</span></code><span>&nbsp;判断当前操作是否需要写入 binlog,若需要,则会针对不同的操作类型,调用不同的函数来处理。具体来说:</span></span></p>
<ul class="list-paddingleft-1">
<li><span>INSERT:<code><span>Write_rows_log_event::binlog_row_logging_function</span></code><span>。</span></span></li>
<li><span>UPDATE:<code><span>Update_rows_log_event::binlog_row_logging_function</span></code><span>。</span></span></li>
<li><span>DELETE:<code><span>Delete_rows_log_event::binlog_row_logging_function</span></code><span>。</span></span></li>
</ul>
<p data-tool="mdnice编辑器"><span>接下来,重点看看<code><span>check_table_binlog_row_based</span></code><span>函数的处理逻辑。</span></span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>static<span>&nbsp;<span>bool<span>&nbsp;<span>check_table_binlog_row_based<span>(THD *thd, TABLE *table)<span>&nbsp;<span>{<span><br>if<span>&nbsp;(table-&gt;s-&gt;cached_row_logging_check ==&nbsp;-1<span>) {<span><br><span>&nbsp; &nbsp;&nbsp;<span>int<span>&nbsp;<span>const<span>&nbsp;<span>check<span>(table-&gt;s-&gt;tmp_table == NO_TMP_TABLE &amp;&amp;<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !table-&gt;no_replicate &amp;&amp;<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; binlog_filter-&gt;db_ok(table-&gt;s-&gt;db.str))<span>;<span><br><span>&nbsp; &nbsp; table-&gt;s-&gt;cached_row_logging_check = check;<span><br><span>&nbsp; }<span><br><span><br><span>&nbsp; assert(table-&gt;s-&gt;cached_row_logging_check ==&nbsp;0<span>&nbsp;||<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;table-&gt;s-&gt;cached_row_logging_check ==&nbsp;1<span>);<span><br><span><br>return<span>&nbsp;(thd-&gt;is_current_stmt_binlog_format_row() &amp;&amp;<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table-&gt;s-&gt;cached_row_logging_check &amp;&amp;<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (thd-&gt;variables.option_bits &amp; OPTION_BIN_LOG) &amp;&amp;<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mysql_bin_log.is_open());<span><br><span>}<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>要返回 false,只需满足以下任意一个条件:</span></p>
<ul class="list-paddingleft-1">
<li><span>当前 SQL 语句不能以 ROW 格式记录到 binlog 中:<code><span>thd-&gt;is_current_stmt_binlog_format_row()</span></code><span>为 false,例如 DDL 语句。</span></span></li>
<li><span>表不允许写入 binlog:<code><span>table-&gt;s-&gt;cached_row_logging_check</span></code><span>为 false。</span></span></li>
<li><span>当前线程未启用 binlog:<code><span>thd-&gt;variables.option_bits &amp; OPTION_BIN_LOG</span></code><span>为 false。</span></span></li>
<li><span>binlog 未打开:<code><span>mysql_bin_log.is_open()</span></code><span>&nbsp;为 false。</span></span></li>
</ul>
<p data-tool="mdnice编辑器"><span>因为第一个条件和第四个条件为 false 的情况并不常见,下面将重点分析<code><span>table-&gt;s-&gt;cached_row_logging_check</span></code><span>和<code><span>thd-&gt;variables.option_bits &amp; OPTION_BIN_LOG</span></code><span>为 false 时的场景。</span></span></span></p>
<h1 data-tool="mdnice编辑器"><span style="color: rgba(0, 128, 0, 1)">cached_row_logging_check 为 false 的场景</span></h1>
<p data-tool="mdnice编辑器"><code><span>table-&gt;s-&gt;cached_row_logging_check</span></code><span>的赋值逻辑如下:</span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>&nbsp;&nbsp;if<span>&nbsp;(table-&gt;s-&gt;cached_row_logging_check ==&nbsp;-1<span>) {<span><br><span>&nbsp; &nbsp;&nbsp;<span>int<span>&nbsp;<span>const<span>&nbsp;<span>check<span>(table-&gt;s-&gt;tmp_table == NO_TMP_TABLE &amp;&amp;<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !table-&gt;no_replicate &amp;&amp;<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; binlog_filter-&gt;db_ok(table-&gt;s-&gt;db.str))<span>;<span><br><span>&nbsp; &nbsp; table-&gt;s-&gt;cached_row_logging_check = check;<span><br><span>&nbsp; }<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>要使其为 false,必须满足以下任意一个条件:</span></p>
<ol class="list-paddingleft-1">
<li><span>当前表是临时表:&nbsp;<code><span>table-&gt;s-&gt;tmp_table == NO_TMP_TABLE</span></code><span>为 false。</span></span></li>
<li><span>库名不满足 --replicate-do-db、--replicate-ignore-db 复制规则:<code><span>binlog_filter-&gt;db_ok(table-&gt;s-&gt;db.str)</span></code><span>为 false。</span></span></li>
<li><span>表设置了 no_replicate。该属性是在<code><span>open_table_from_share()</span></code><span>函数中根据表的类型和存储引擎能力标志设置的。</span></span></li>
</ol>
<p data-tool="mdnice编辑器"><span>no_replicate 的设置逻辑如下:</span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>&nbsp;&nbsp;if<span>&nbsp;((share-&gt;table_category == TABLE_CATEGORY_LOG) ||<span><br><span>&nbsp; &nbsp; &nbsp; (share-&gt;table_category == TABLE_CATEGORY_RPL_INFO) ||<span><br><span>&nbsp; &nbsp; &nbsp; (share-&gt;table_category == TABLE_CATEGORY_GTID)) {<span><br><span>&nbsp; &nbsp; outparam-&gt;no_replicate =&nbsp;true<span>;<span><br><span>&nbsp; }&nbsp;else<span>&nbsp;if<span>&nbsp;(outparam-&gt;file) {<span><br><span>&nbsp; &nbsp;&nbsp;const<span>&nbsp;handler::Table_flags flags = outparam-&gt;file-&gt;ha_table_flags();<span><br><span>&nbsp; &nbsp; outparam-&gt;no_replicate =<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; !(flags &amp; (HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE)) ||<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; (flags &amp; HA_HAS_OWN_BINLOGGING);<span><br><span>&nbsp; }&nbsp;else<span>&nbsp;{<span><br><span>&nbsp; &nbsp; outparam-&gt;no_replicate =&nbsp;false<span>;<span><br><span>&nbsp; }<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>可以看到,no_replicate 会在以下几种情况设置为 true。</span></p>
<p data-tool="mdnice编辑器"><span>一、特殊类别的表。包括:</span></p>
<ul class="list-paddingleft-1">
<li><span>TABLE_CATEGORY_LOG 类别的表,具体包括 mysql.general_log, mysql.slow_log。</span></li>
<li><span>TABLE_CATEGORY_RPL_INFO 类别的表,具体包括 mysql.slave_relay_log_info,mysql.slave_master_info,mysql.slave_worker_info。</span></li>
<li><span>TABLE_CATEGORY_GTID 类别的表,具体包括 mysql.gtid_executed。</span></li>
</ul>
<p data-tool="mdnice编辑器"><span>二、根据存储引擎的能力标志判断。</span></p>
<p data-tool="mdnice编辑器"><span>这些标志是每个存储引擎单独设置的,一般是在<code><span>m_int_table_flags</span></code><span>或<code><span>table_flags</span></code><span>函数中定义的,主要是用来向 Server 层声明:这个存储引擎的表,支持哪些能力/约束。与复制相关的标志有三个:</span></span></span></p>
<ul class="list-paddingleft-1">
<li><span>HA_BINLOG_STMT_CAPABLE:支持 STATEMENT 格式 binlog。</span></li>
<li><span>HA_BINLOG_ROW_CAPABLE:支持 ROW 格式 binlog</span></li>
<li><span>HA_HAS_OWN_BINLOGGING:该引擎自己管理 binlog(如 NDB Cluster)。</span></li>
</ul>
<p data-tool="mdnice编辑器"><span>在 MySQL 支持的存储引擎中,只有 perfschema(对应 performance_schema)和 temptable(MySQL 8.0 引入的内部临时表存储引擎,主要用来替代老的 MEMORY/MyISAM 内部临时表)不会设置 HA_BINLOG_STMT_CAPABLE 或 HA_BINLOG_ROW_CAPABLE。</span></p>
<p data-tool="mdnice编辑器"><span>所以,针对 performance_schema 表的操作不会写入 binlog。</span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code># ls mysql-8.4.3/storage/<span><br><span>archive &nbsp;blackhole &nbsp;csv &nbsp;example &nbsp;federated &nbsp;heap &nbsp;innobase &nbsp;myisam &nbsp;myisammrg &nbsp;ndb &nbsp;perfschema &nbsp;secondary_engine_mock &nbsp;temptable<span><br></span></span></span></code></span></pre>
<h1 data-tool="mdnice编辑器"><span style="color: rgba(0, 128, 0, 1)">OPTION_BIN_LOG 为 false 的场景</span></h1>
<p data-tool="mdnice编辑器"><code><span>thd-&gt;variables</span></code><span>保存当前线程的会话级系统变量状态。其中,option_bits 是一个位图(bitmap),用于记录多个线程级选项标志,OPTION_BIN_LOG 则表示是否将当前线程的操作写入 binlog。</span></p>
<p data-tool="mdnice编辑器"><span>以下是几种典型场景。</span></p>
<p data-tool="mdnice编辑器"><span>一、显式关闭会话级 binlog</span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code>SET<span>&nbsp;SESSION<span>&nbsp;sql_log_bin =&nbsp;0<span>;<span><br></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>该参数对应的回调函数是<code><span>fix_sql_log_bin_after_update</span></code><span>。</span></span></p>
<p data-tool="mdnice编辑器"><span>当<code><span>sql_log_bin = 1</span></code><span>时,打开 OPTION_BIN_LOG,反之,则清除 OPTION_BIN_LOG。</span></span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>static<span>&nbsp;<span>bool<span>&nbsp;<span>fix_sql_log_bin_after_update<span>(sys_var *, THD *thd,<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;enum_var_type type [])<span>&nbsp;<span>{<span><br><span>&nbsp; assert(type == OPT_SESSION);<span><br><span><br><span>&nbsp;&nbsp;if<span>&nbsp;(thd-&gt;variables.sql_log_bin)<span><br><span>&nbsp; &nbsp; thd-&gt;variables.option_bits |= OPTION_BIN_LOG;<span><br><span>&nbsp;&nbsp;else<span><br><span>&nbsp; &nbsp; thd-&gt;variables.option_bits &amp;= ~OPTION_BIN_LOG;<span><br><span><br><span>&nbsp;&nbsp;return<span>&nbsp;false<span>;<span><br><span>}<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>二、从库未启用 log_replica_updates</span></p>
<p data-tool="mdnice编辑器"><span>当实例作为从库运行,且未开启 log_replica_updates 时,从库 SQL 线程重放的操作默认不写 binlog。</span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>void<span>&nbsp;<span>set_slave_thread_options<span>(THD *thd)<span>&nbsp;<span>{<span><br><span>&nbsp; ...<span><br><span>&nbsp; ulonglong options = thd-&gt;variables.option_bits | OPTION_BIG_SELECTS;<span><br><span>&nbsp;&nbsp;if<span>&nbsp;(opt_log_replica_updates)<span><br><span>&nbsp; &nbsp; options |= OPTION_BIN_LOG;<span><br><span>&nbsp;&nbsp;else<span><br><span>&nbsp; &nbsp; options &amp;= ~OPTION_BIN_LOG;<span><br><span>&nbsp; ...<span><br><span>}<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>三、使用<code><span>Disable_binlog_guard</span></code><span>临时关闭 binlog</span></span></p>
<p data-tool="mdnice编辑器"><code><span>Disable_binlog_guard</span></code><span>用于在特定代码块内临时关闭 binlog,并在离开作用域时自动恢复原状态。</span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>class<span>&nbsp;<span>Disable_binlog_guard<span>&nbsp;{<span><br><span>&nbsp;public<span>:<span><br><span>explicit<span>&nbsp;<span>Disable_binlog_guard<span>(THD *thd)<span><br><span>&nbsp; &nbsp; &nbsp; :&nbsp;<span>m_thd<span>(thd)<span>,<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span>m_binlog_disabled<span>(thd-&gt;variables.option_bits &amp; OPTION_BIN_LOG)<span>&nbsp;<span>{<span><br><span>&nbsp; &nbsp; thd-&gt;variables.option_bits &amp;= ~OPTION_BIN_LOG;<span><br><span>&nbsp; }<span><br><span><br><span>&nbsp; ~Disable_binlog_guard() {<span><br><span>&nbsp; &nbsp;&nbsp;if<span>&nbsp;(m_binlog_disabled) m_thd-&gt;variables.option_bits |= OPTION_BIN_LOG;<span><br><span>&nbsp; }<span><br><span><br>private<span>:<span><br><span>&nbsp; THD *const<span>&nbsp;m_thd;<span><br>constbool<span>&nbsp;m_binlog_disabled;<span><br><span>};<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>Disable_binlog_guard 被调用的场景有:</span></p>
<p data-tool="mdnice编辑器"><span>3.1 实例初始化(<code><span>--initialize</span></code><span>)</span></span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>static<span>&nbsp;<span>bool<span>&nbsp;<span>handle_bootstrap_impl<span>(handle_bootstrap_args *args)<span>&nbsp;<span>{<span><br><span>&nbsp; ...<span><br>if<span>&nbsp;(opt_initialize) {<span><br><span>&nbsp; &nbsp; assert(thd-&gt;system_thread == SYSTEM_THREAD_SERVER_INITIALIZE);<span><br><span><br><span>&nbsp; &nbsp; sysd::notify("STATUS=Initialization of MySQL system tables in progress\n"<span>);<span><br><span>&nbsp; &nbsp;&nbsp;<span><br><span>&nbsp; &nbsp;&nbsp;<span>const<span>&nbsp;Disable_binlog_guard&nbsp;<span>disable_binlog<span>(thd)<span>;<span><br><span>&nbsp; &nbsp;&nbsp;<span>const<span>&nbsp;Disable_sql_log_bin_guard&nbsp;<span>disable_sql_log_bin<span>(thd)<span>;<span><br><span><br><span>&nbsp; &nbsp; Compiled_in_command_iterator comp_iter;<span><br><span>&nbsp; &nbsp; rc = process_iterator(thd, &amp;comp_iter,&nbsp;true<span>);<span><br><span><br><span>&nbsp; &nbsp; thd-&gt;system_thread = SYSTEM_THREAD_INIT_FILE;<span><br><span><br><span>&nbsp; &nbsp; sysd::notify("STATUS=Initialization of MySQL system tables "<span>,<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rc ?&nbsp;"unsuccessful"<span>&nbsp;:&nbsp;"successful"<span>,&nbsp;"\n"<span>);<span><br><span><br><span>&nbsp; &nbsp;&nbsp;if<span>&nbsp;(rc !=&nbsp;0<span>) {<span><br><span>&nbsp; &nbsp; &nbsp;&nbsp;returntrue<span>;<span><br><span>&nbsp; &nbsp; }<span><br><span>&nbsp; }<span><br><span>&nbsp; ...<span><br>returnfalse<span>;<span><br><span>}<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>3.2 实例升级</span></p>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code><span>bool<span>&nbsp;<span>upgrade_system_schemas<span>(THD *thd)<span>&nbsp;<span>{<span><br><span>Disable_autocommit_guard&nbsp;<span>autocommit_guard<span>(thd)<span>;<span><br><span>&nbsp; Bootstrap_error_handler bootstrap_error_handler;<span><br><span><br><span>Server_option_guard&lt;<span>bool<span>&gt;&nbsp;<span>acl_guard<span>(&amp;opt_noacl,&nbsp;<span>true<span>)<span>;<span><br><span>Server_option_guard&lt;<span>bool<span>&gt;&nbsp;<span>general_log_guard<span>(&amp;opt_general_log,&nbsp;<span>false<span>)<span>;<span><br><span>Server_option_guard&lt;<span>bool<span>&gt;&nbsp;<span>slow_log_guard<span>(&amp;opt_slow_log,&nbsp;<span>false<span>)<span>;<span><br><span>Disable_binlog_guard&nbsp;<span>disable_binlog<span>(thd)<span>;<span><br><span>Disable_sql_log_bin_guard&nbsp;<span>disable_sql_log_bin<span>(thd)<span>;<span><br><span>&nbsp; ...<span><br><span>&nbsp; bootstrap_error_handler.set_log_error(false<span>);<span><br>bool<span>&nbsp;err =<span><br><span>&nbsp; &nbsp; &nbsp; fix_mysql_tables(thd) || fix_sys_schema(thd) || upgrade_help_tables(thd);<span><br>if<span>&nbsp;(!err) {<span><br><span>&nbsp; &nbsp;&nbsp;<span>/*<span><br><span>&nbsp; &nbsp; &nbsp; Initialize structures necessary for federated server from mysql.servers<span><br><span>&nbsp; &nbsp; &nbsp; table.<span><br><span>&nbsp; &nbsp; */<span><br><span>&nbsp; &nbsp; servers_init(thd);<span><br><span>&nbsp; &nbsp; err = (DBUG_EVALUATE_IF("force_fix_user_schemas"<span>,&nbsp;true<span>,<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dd::bootstrap::DD_bootstrap_ctx::instance()<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .is_server_upgrade_from_before(<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bootstrap::SERVER_VERSION_80011))<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;? check.check_all_schemas(thd)<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: check.check_system_schemas(thd)) ||<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; check.repair_tables(thd) ||<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dd::tables::DD_properties::instance().set<span>(<span><br><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thd,&nbsp;"MYSQLD_VERSION_UPGRADED"<span>, MYSQL_VERSION_ID);<span><br><span>&nbsp; }<span><br><span>&nbsp; ...<span><br>return<span>&nbsp;dd::end_transaction(thd, err);<span><br><span>}<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>3.3 CREATE SERVER, ALTER SERVER 和 DROP SERVER 操作。</span></p>
<p data-tool="mdnice编辑器"><span>3.4 INSTALL COMPONENT, UNINSTALL COMPONENT 操作。</span></p>
<p data-tool="mdnice编辑器"><span>3.5 INSTALL PLUGIN, UNINSTALL PLUGIN 操作。</span></p>
<p data-tool="mdnice编辑器"><span>3.6 一些内部操作,例如 ALTER TABLE 过程中创建/删除临时表、DROP DATABASE 时清理数据库对象、更新数据字典表、后台线程自动更新列直方图。</span></p>
<p data-tool="mdnice编辑器"><span>除了上面介绍的这些场景,通过将&nbsp;<code><span>thd-&gt;lex-&gt;no_write_to_binlog</span></code><span>&nbsp;设置为<code><span>true</span></code><span>(<code><span>thd-&gt;lex</span></code><span>表示当前 SQL 语句的语法解析上下文),可以在语句级别控制该语句不写入 binlog。</span></span></span></span></p>
<h1 data-tool="mdnice编辑器"><span style="color: rgba(0, 128, 0, 1)">NO_WRITE_TO_BINLOG 为 true 的场景</span></h1>
<p data-tool="mdnice编辑器"><span>以下场景会将 no_write_to_binlog 设置为 true。</span></p>
<ol class="list-paddingleft-1">
<li><span><span>SHUTDOWN、RESTART 命令。</span></span></li>
<li><span>RESET 系列命令,包括:RESET MASTER, RESET SLAVE, RESET PERSIST。</span></li>
<li><span>显式指定<code><span>NO_WRITE_TO_BINLOG</span></code><span>或<code><span>LOCAL</span></code><span>。部分维护类 SQL 命令(OPTIMIZE, ANALYZE, REPAIR, FLUSH)支持在语句中显式指定不写 binlog,如,</span></span></span></li>
</ol>
<pre data-tool="mdnice编辑器"><span data-cacheurl="" data-remoteid="" data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/BO1qQiajiacVlibSwibjXiaMnylbHVGpQcib8UWIFerYZgIR9sxBIBCgO6hYKkExWrhsjMPIQa1yIOMmrRGFx1dEib6vlCuJygOxAZF/640?wx_fmt=svg&amp;from=appmsg" data-fail="0"><code>OPTIMIZE<span>&nbsp;NO_WRITE_TO_BINLOG<span>&nbsp;TABLE<span>&nbsp;t1;<span><br>ANALYZE<span>&nbsp;LOCAL<span>&nbsp;TABLE<span>&nbsp;t1;<span><br>REPAIR<span>&nbsp;NO_WRITE_TO_BINLOG<span>&nbsp;TABLE<span>&nbsp;t1;<span><br>FLUSH<span>&nbsp;LOCAL<span>&nbsp;PRIVILEGES<span>;<span><br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></span></pre>
<p data-tool="mdnice编辑器"><span>需要注意的是,对于<code><span>FLUSH</span></code><span>命令,即使未显式指定<code><span>NO_WRITE_TO_BINLOG</span></code><span>,以下命令默认也不会写入 binlog:NO_WRITE_TO_BINLOG,FLUSH LOGS、FLUSH BINARY LOGS、FLUSH TABLES WITH READ LOCK、FLUSH TABLES tbl_name ... FOR EXPORT。</span></span></span></p>
<h1 data-tool="mdnice编辑器"><span style="color: rgba(0, 128, 0, 1)">总结</span></h1>
<p data-tool="mdnice编辑器"><span>虽然上面列举的场景较多,但实际上并不需要大家刻意去记。</span></p>
<p data-tool="mdnice编辑器"><span>简单来说,</span></p>
<ul class="list-paddingleft-1">
<li>
<p><span>凡是 MySQL 内部自动执行的操作(即非用户手动执行的操作),通常不会写入 binlog。 典型场景包括:实例初始化与升级、<code><span>mysql.slow_log</span></code><span>表的写入、数据字典的维护、<code><span>performance_schema</span></code><span>表数据的更新等。</span></span></span></p>
</li>
<li>
<p><span>对 mysql 库下的表进行 <span>DML 操作,只要不属于上面提到的特殊类别的表,基本都会写入 binlog。</span></span></p>
<p><span>但若执行的是 DDL 操作(如 truncate),基本都会写入 binlog。</span></p>
</li>
<li>
<p><span>对 performance_schema 中的表进行 DML、DDL 操作会提示权限不足,即便是用 root 用户执行。但部分表允许执行 truncate 操作,且 truncate 操作不会写入 binlog。</span></p>
</li>
</ul><br><br>
来源:https://www.cnblogs.com/ivictor/p/19382809
頁: [1]
查看完整版本: MySQL 在哪些场景下不会写 binlog