場景:需要對現在數據庫的數據進行批量的進行is_del=1的操作,但是遇到一個問題,在執行sql的時候發現sql不能在查詢特定表的時候再嵌套查詢來做update的操作,經過討論,后續我們想到用臨時表的方案來解決這個問題。
開始進行數據測試,進行單用戶的update操作,一切都比較順利沒有任何問題,操作的也是我們想操作的數據,接下來進行批量的數據操作,sql語句運行一會出現如下錯誤:
ERROR 1114 (HY000): The table 'adv_date_tmp' is full
報錯為臨時表已滿,原因是沒有調整mysql的默認臨時表大小導致的報錯。
tmp_table_size
如果內存內的臨時表超過該值,MySQL自動將它轉換為硬盤上的MyISAM表。如果你執行許多高級GROUP BY查詢並且有大量內存,則可以增加tmp_table_size的值。
max_heap_table_size
該變量設置MEMORY (HEAP)表可以增長到的最大空間大小。該變量用來計算MEMORY表的MAX_ROWS值。在已有的MEMORY表上設置該變量沒有效果,除非用CREATE TABLE或TRUNCATE TABLE等語句重新創建表。
默認情況下的臨時表大小不能滿足特定場景的需求,這個時候就需要將臨時表的大小進行動態的調整,一般我們推薦進行set session動態進行會話調整(可以不重啟服務器進行調整),不過也可以通過調整my.cnf的配置來進行永久的調整(需要重啟服務,不推薦這種操作)。
查詢mysql的默認配置臨時表的大小
mysql> show variables like '%tmp_table%'; +----------------+----------+ | Variable_name | Value | +----------------+----------+ | max_tmp_tables | 32 | | tmp_table_size | 16777216 | +----------------+----------+ 2 rows in set (0.00 sec) mysql> show variables like '%max_heap%'; +---------------------+----------+ | Variable_name | Value | +---------------------+----------+ | max_heap_table_size | 16777216 | +---------------------+----------+ 1 row in set (0.00 sec)
在線調整臨時表大小
mysql> set session tmp_table_size=1024*1024*1024; Query OK, 0 rows affected (0.00 sec) mysql> set session max_heap_table_size=1024*1024*1024; Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%tmp_table%'; +----------------+------------+ | Variable_name | Value | +----------------+------------+ | max_tmp_tables | 32 | | tmp_table_size | 1073741824 | +----------------+------------+ 2 rows in set (0.00 sec) mysql> show variables like '%max_heap%'; +---------------------+------------+ | Variable_name | Value | +---------------------+------------+ | max_heap_table_size | 1073741824 | +---------------------+------------+ 1 row in set (0.00 sec)
進行sql語句操作
mysql> CREATE TEMPORARY TABLE IF NOT EXISTS tmp_table ENGINE = MEMORY SELECT adf.opt_id FROM `test`.`test.count` a INNER JOIN `test`.`test.prise` e ON a.prise_id=e.prise_id AND e.is_del=0 AND e.domain IN('test1','test2','test3','test4','test5','test6','test7','test8','test9','test10','test11','test12','test13','test14','test15','test16','test17','test18','test19') INNER JOIN `online`.`FILTER` adf ON adf.user_id=a.user_id AND adf.is_del=0 AND adf.is_global=0 AND adf.`type`='fixed' AND adf.`name` IN ('今天', '昨天', '最近7天', '最近30天', '最近90天', '最近一年') LEFT JOIN `online`.`OPT_ID_DELETE` oid ON adf.opt_id=oid.opt_id WHERE a.is_del=0 AND a.username='admin' AND oid.opt_id is NULL; Query OK, 101976 rows affected (2 min 3.82 sec) Records: 101976 Duplicates: 0 Warnings: 0
更新表數據
mysql> UPDATE `online`.`FILTER` SET is_del=1 WHERE opt_id IN( SELECT opt_id FROM tmp_table); mysql> drop table tmp_table;
Ok,整個操作完成。