type
status
date
slug
summary
tags
category
icon
password

症狀

當執行語句時,返回 ERROR 1114 (HY000): The table '/tmp/#sql1967_9_3' is full 錯誤,但是 Disk 仍有充足的空間:
我們都知道當 tempoary table 使用的 memory 不足夠時會轉換到 disk 上操作,因此照理來說只有當 memory、disk 都不足夠時才應該出現這類錯誤訊息。

原因

前置知識 - 關於 internal tempoary table 的引擎

在 8.0.13 版本之前,是使用 MEMORY 引擎來建立 internal tempoary table,其不足之處在於不支援可變長度的資料型態,這導致了以下問題:
  1. 當欄位出現 TEXT、BLOB 型態會直接改為在 disk 上建立 tempoary table。
  1. 對於 VARCHAR 型態總會映射為 CHAR 型態,導致內存浪費。
因此在 8.0.13 開始引進了 TempTable 引擎解決這些問題,且預設 internal tempoary table 使用 TempTable 引擎。

BUG 細節

當使用 temporary table 進行 aggregation 操作情況下,如果 group-by 欄位的值已經存在則會 update 該行,否則會 insert 新的一行。
bug#99100 說明中可以看到回報者透過 gdb 發現,當 temporary table(TempTable 引擎) 在進行 update 操作 (table()->file->ha_update_row) 時,消耗的 memory 如果超過 temptable_max_ram 會直接就拋出 HA_ERR_RECORD_FILE_FULL 的錯誤。
💡
temptable_max_ram:所有的 internal tempoary table(TempTable) 的最大內存使用量
也就是說在 TempTable 引擎下,雖然 insert 操作會在 memory 不足時轉到 Disk 上操作,但是 update 操作並沒有而是直接返回錯誤。

觸發情境

版本:MySQL 8.0.13~8.0.26
當使用到 internal tempoary table (Using tempoary) 進行 aggregation 操作,且當包含可變長度欄位 (例如:varchar) 時,就有可能會因為 temptable_max_ram 不足夠,即使 Disk 空間足夠也會引發此錯誤。

修正方案

  1. 此 BUG 在 8.0.27 中修復,因此可以透過升級修正:
    1. 💡
      InnoDB: A query that used a temporary table for aggregation exhausted the memory available to the TempTable storage engine, causing an update operation to fail with a table is full error. (Bug #31117893, Bug #99100) https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-27.html
      💡
      修正方案根據 github 內修正的 commit 上說明: 當使用 temporary table 進行 aggregation 操作情況下,如果 group-by 欄位的值已經存在則會 update 該行,否則會 insert 新的一行。 如果 temporary table 中包含可變長度欄位(例如:varchar),則 TempTable 在實現時可能會在 update 操作耗盡 memory。 修正方案是當發生此狀況時將 tempoary table 移動到 disk 上並重新執行剛剛的 update 操作。
  1. 暫時將 internal_tmp_mem_storage_engineTempTable 調整為 Memory

    參考