<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                有一天小編胡亂寫SQL, left join了30張表, 結果導致了Mysql server gone away… 我們來看看crash堆棧 ~~~ <signal handler called> base_list_iterator::next update_ref_and_keys make_join_statistics JOIN::optimize mysql_execute_select ~~~ 可以看出, 在產生執行計劃過程中crash了。 ## 追查 堆棧表明,?`update_ref_and_keys`函數中`join_tab->join->join_list`為無效地址。 排查看到函數入口處這個變量還是ok的, 那么在gdb里watch一下。 ~~~ Hardware watchpoint 4: join_tab->join->join_list Old value = (List<TABLE_LIST> *) 0x3431f60 New value = (List<TABLE_LIST> *) 0xc800000000000000 ~~~ 這么整齊的地址一看就有問題。函數棧: ~~~ Key_field::Key_field add_key_field add_key_equal_fields add_key_fields update_ref_and_keys ~~~ 而`add_key_fields`修改`join_tab->join->join_list`實際是不合理的, 因此這里說明一下路徑上幾個關鍵的函數。 ## 原因分析 還要從子查詢優化說起,當遇到semi-join子查詢情況下,?`JOIN::optimize()`會調用`JOIN::flatten_subqueries`改寫SQL, 如下形式: ~~~ SELECT ... FROM ot1, ... WHERE oe IN (SELECT ie FROM it1, ..., itN WHERE subq_where) AND outer_where ~~~ 會被修改為: ~~~ SELECT ... FROM ot SEMI JOIN (it1, ... , itN), WHERE outer_where AND subq_where AND oe=ie ~~~ 函數`JOIN::flatten_subqueries`, 做了以下幾件事: * 創建semi join(it1, …, itN)的節點并添加到外層查詢語句的FROM語法樹下 * 將`subq_where AND oe=ie`加入到外層查詢語句的WHERE樹下 * 再移除原先的子查詢語句 `JOIN::flatten_subqueries`中, 對于每一個子查詢, 調用函數`JOIN::convert_subquery_to_semijoin`, 那么子查詢上維護的query信息也要同步加到外部查詢上。所以可見, 子查詢中的信息, 會轉交給外部查詢。 之后,?`JOIN::optimize()`調用`update_ref_and_keys`, 這個函數用來處理出最終查詢要使用的索引。crash的問題也出現在這個函數中, 因此還要看`update_ref_and_keys`內部做了什么。 在函數`update_ref_and_keys`中, 一個重要的數組, key_fields, 用來存放所有可能用到的索引字段。先通過`key_fields=(Key_field*) thd->alloc(sz)`分配空間, 再調用`add_key_fields`遞歸遍歷WHERE樹, 遇到等值表達式, 會填充到`key_fields`數組中。而之前已經看到, add_key_field在寫key_fields時卻修改了`join_tab->join->join_list`。 ~~~ // add_key_fields中修改了join_tab->join->join_list的代碼 new (*key_fields) Key_field(field, *value, and_level, exists_optimize, eq_func, null_rejecting, NULL, get_semi_join_select_list_index(field)); (*key_fields)++; ~~~ 可見在new的時候拿到了`join_tab->join->join_list`, 是(*key_fields++)的時候, 加過頭了。從而可推斷, key_fields沒有分配到應該有的內存空間。那么出問題的就是sz用來分配空間的數字了。 ~~~ // sz的計算方法 sz= max(sizeof(Key_field), sizeof(SARGABLE_PARAM)) * (((select_lex->cond_count + 1) * 2 + select_lex->between_count) * m + 1); ~~~ 這里涉及到兩個變量`select_lex->cond_count`和`select_lex->between_count`, 而cond_count就是number of conditions; 構造的語句中的等值表達式足有31條, 而這里在分配時是2, 活該內存越界。 而這個變量在子查詢優化過程中, 子查詢應該將其移交給外部查詢語句。 ## 修復 函數`JOIN::convert_subquery_to_semijoin`中, 改寫完SQL后, 忘記把子查詢的cond_count和between_cond信息更新到外部查詢了, 這時只要手動添加即可。 [官方修復(5.6.25)參見](https://github.com/mysql/mysql-server/commit/71e74f2a0118f460abc4f7a3da215c61785d35f0) [相關worklog參見](http://dev.mysql.com/worklog/task/?id=5275) ## 復現 可以通過以下方式復現 ~~~ create table t1 ( `id` int(20), `col3` varchar(60) default null, primary key (id) ); create view `v_test` as select t1.col1 as col1, t2.col2 as col2, ... t30.col30 as col30 from (((((((((((((((((((((((((((((t1 left join t2 on (t1.id = t2.id)) left join t3 on (t1.id = t3.id)) ... left join t30 on (t1.id = t30.id)); ~~~ 然后執行 ~~~ create table tt (id int(20), b varchar(200)); select * from tt where b in (select col1_1 fromom v_test); ~~~ MySQL5.6在5.6.25之前的小版本都可以復現, 請盡情調戲 .^.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看