<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      GreatSQL CTE 查詢報告臨時表找不到問題解析

      GreatSQL CTE 查詢報告臨時表找不到問題解析

      一、問題發現

      在客戶現場的一次問題報告中發現某個帶有CTE語句進行查詢的時候,把tmp_table_size設置為最小1024,數據量少的時候卻報錯臨時表找不到。注意:該問題在最新的MySQL版本中仍存在。

      看下面例子:

      1、準備表

      CREATE TABLE t7 (
        ID int NOT NULL AUTO_INCREMENT,
        NAME varchar(128) COLLATE utf8mb4_bin DEFAULT NULL,
        PARENTNODEID int DEFAULT NULL,
        STATE int DEFAULT NULL,
        PRIMARY KEY (`ID`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
      
      greatsql> INSERT INTO t7 VALUES (-1,'萬里',0,1);
      

      2、tmp_table_size為默認值場合

      如下所示用默認tmp_table_size并且進行CTE派生表查詢,可以發現結果正常顯示一條數據,符合預期。

      -- tmp_table_size參數為默認值的情況
      greatsql> SHOW variables LIKE '%tmp_table_size%';
      +----------------+----------+
      | Variable_name  | Value    |
      +----------------+----------+
      | tmp_table_size | 16777216 |
      +----------------+----------+
      
      greatsql> WITH RECURSIVE cte AS(   (select id    from t7 where id= -1)   UNION   (select b.id     from t7 b inner join cte on cte.id=b.parentNodeid and b.state =1) ) select * from cte;      
      +------+
      | id   |
      +------+
      |   -1 |
      +------+
      

      3、tmp_table_size修改小的場合

      如下所示設置最小的tmp_table_size并且進行CTE派生表查詢,可以發現報錯了,問題復現。

      greatsql> WITH RECURSIVE cte AS(   (select id    from t7 where id= -1)   UNION   (select b.id     from t7 b inner join cte on cte.id=b.parentNodeid and b.state =1) ) select * from cte;      
      ERROR 1813 (HY000): Tablespace '`tmp`.`#sqle7cc2_8_4`' exists.
      

      二、問題調查過程

      查詢帶有CTE派生表的時候內部會創建臨時表用于保存臨時數據,因此先看一下下面的運行流程圖:

      image.png

      上面的流程圖可以簡化歸納總結為以下:

      1、創建表A,創建表B ==>先賦值tmp table引擎
      2、創建表A引擎 ==> 創建表A表tmp table引擎,發現內存不夠,改為innodb引擎并創建表空間(見圖上紅字部分),但是表B還是用tmp table引擎
      3、打開表A,打開表B ==>表A打開成功,打開表B失敗,因為在kv_store列表找不到這個臨時表名
      4、插入表A,插入表B
      因此可以看出問題出在第二步,表A改變了引擎但是沒有對應改變表B的引擎,接著表B打開的時候列表找不到對應的名字報錯。
      

      三、問題解決

      結合上面分析,可以發現應該在第二步場景下,在表A的引擎改變的時候同步改變表B的引擎,因此對函數create_tmp_table_with_fallback修改如下:

      static bool resolve_cte_common_table_expr(TABLE *wtable,
                                                Table_ref *wtable_list) {
        assert(wtable_list);
        Derived_refs_iterator ref_it(wtable_list);
      
        if (wtable_list) {
          Common_table_expr *cte = wtable_list->common_table_expr();
          if (cte) {
            int i = 0, found = -1;
            TABLE *t;
            while ((t = ref_it.get_next())) {
              if (t == wtable) {
                found = i;
                break;
              }
              ++i;
            }
            assert(found >= 0);
            if (found > 0)
              // 'wtable' is at position 'found', move it to 0 to convert it first
              std::swap(cte->tmp_tables[0], cte->tmp_tables[found]);
            ref_it.rewind();
          }
        }
        TABLE new_table, *table = nullptr;
        bool error = false;
        TABLE_SHARE *share = wtable->s;
        uint count = 0;
        // 遍歷所有相關表并改變引擎
        while (true) {
          HA_CREATE_INFO create_info;
          table = ref_it.get_next();
          if (table == nullptr) break;
      
          table->file = get_new_handler(
              table->s, false, share->alloc_for_tmp_file_handler, innodb_hton);
          // for CTE's cloned table,it doesn't need to do
          // innobase_basic_ddl::create_impl again.
          if (count == 0) {
            error = table->file->create(share->table_name.str, table, &create_info,
                                        nullptr);
            if (error) return true;
          }
          count++;
        }
        return false;
      }
      
      static bool create_tmp_table_with_fallback(THD *thd, TABLE *table) {
        int error =
            table->file->create(share->table_name.str, table, &create_info, nullptr);
        if (error == HA_ERR_RECORD_FILE_FULL &&
            table->s->db_type() == temptable_hton) {
          Table_ref *const wtable_list = table->pos_in_table_list;
          // for CTE table,it should set all tables to innodb_hton.
          // 這里增加一個CTE判斷,如果是CTE就對所有相關表做操作,改變所有表的引擎。
          if (wtable_list && resolve_cte_common_table_expr(table, wtable_list))
            return true;
          else {
            table->file = get_new_handler(
                table->s, false, share->alloc_for_tmp_file_handler, innodb_hton);
            error = table->file->create(share->table_name.str, table, &create_info,
                                        nullptr);
          }
        }
      }
      

      接著執行上面的查詢,發現可以查出結果了。

      greatsql> SET tmp_table_size=1024;
      Query OK, 0 rows affected (0.00 sec)
      
      greatsql> WITH RECURSIVE cte AS(   (select id    from t7 where id= -1)   UNION   (select b.id     from t7 b inner join cte on cte.id=b.parentNodeid and b.state =1) ) select * from cte;      
      +------+
      | id   |
      +------+
      |   -1 |
      +------+
      1 row in set (0.10 sec)
      

      四、問題總結

      通過以上分析我們可以發現,帶有CTE派生表的查詢會在內部創建臨時表用于儲存中間數據,根據tmp_table_size值設置會影響臨時表存放地方,如果tmp_table_size設置小了那么一開始就會從內存表改為創建落盤表,但是CTE內部涉及好幾層迭代器,這時候每一層臨時表的引擎都需要改,而導致報錯的代碼只改了其中一層的臨時表,沒有把別的引擎一起改了,最后導致問題。

      這個問題涉及了2個不同的迭代器的強相關表,理論上應該一起操作引擎,但是有時候代碼處理一張表卻漏了處理另一張,這就會導致問題。

      建議:在沒修復該Bug前,可以先適當調大tmp_table_size參數值。

      posted @ 2025-10-30 11:08  GreatSQL  閱讀(5)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 草裙社区精品视频播放| 色伦专区97中文字幕| 国产在线精品第一区二区| aa性欧美老妇人牲交免费| 7777精品久久久大香线蕉| 国产精品多p对白交换绿帽| 国产成人无码av大片大片在线观看 | 亚洲婷婷综合色高清在线| 亚洲精品国产av一区二区| 三穗县| 一本久久a久久精品综合| 国产综合一区二区三区麻豆| 天堂av在线一区二区| 亚洲精品一二三四区| 精品一区二区三区蜜桃麻豆| 国产av无码专区亚洲aⅴ| 成人免费A级毛片无码片2022| 亚洲精品乱码久久观看网| 国产麻豆一区二区精彩视频| 亚洲情A成黄在线观看动漫尤物 | 亚洲午夜香蕉久久精品| 国产丰满乱子伦无码专区| 国产精品白浆无码流出| 精品人妻伦九区久久aaa片| 伊人久在线观看视频| 日韩精品一区二区午夜成人版 | 亚洲精品区二区三区蜜桃| 91福利视频一区二区| 久久精品亚洲日本波多野结衣| 大关县| 国产一区二区日韩在线| 2020国产欧洲精品网站 | 久久精品一本到99热免费| 欧美人与动牲交精品| 久久婷婷丁香五月综合五| 性欧美VIDEOFREE高清大喷水| 国产毛片精品av一区二区| 日韩精品国产二区三区| 四虎影视库国产精品一区| 国产成人精品亚洲日本片| 国产黄色三级三级看三级|