Mysql

為什麼導入 MySQL 轉儲會導致如此多的 I/O?

  • May 9, 2015

我導入了 100 個 SQL 格式的轉儲文件。總大小為 20 GB。導入後生成的 .ibd 文件的總大小為 40 GB。mysqld.exe 在磁碟上寫入 1.1 TB 並讀取 120 GB。為什麼會有這麼多 I/O?

我使用 MySQL Workbench 的預設選項來創建 SQL 格式的轉儲文件,即:

在此處輸入圖像描述

*它似乎與 MySQL 參考手冊的 InnoDB 表的批量數據載入*部分的建議非常吻合(除了autocommit=0,它不在我的轉儲中)。轉儲中生成的程式碼標題如下所示:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `askbot_activityauditstatus`
--
LOCK TABLES `askbot_activityauditstatus` WRITE;
/*!40000 ALTER TABLE `askbot_activityauditstatus` DISABLE KEYS */;
INSERT INTO `askbot_activityauditstatus` VALUES 
etc

我知道我可以嘗試使用其他轉儲工具來加快速度,但我很好奇。寫的數量給我留下了特別深刻的印象。

我使用 Windows 7 SP1 x64、MySQL 5.6 和 MySQL Workbench 6.0。

從根本上說,恢復轉儲文件涉及插入所有行並為所有數據建構所有索引。鑑於此,轉儲文件的生成方式、您是否使用一個或多個文件、或者您選擇了哪些可用選項(儘管其中一些extended-insert可能會使選擇的情況變得更糟)都不是特別相關。

當您恢復文件時,您還:

  • 將數據寫入事務日誌
  • 將數據寫入雙寫緩衝區
  • 將數據寫入表空間文件
  • 將索引寫入雙寫緩衝區
  • 將索引寫入表空間文件
  • 如果啟用,則將數據寫入二進制日誌……並且如果您具有binlog_format“語句”的預設設置,那麼您實際上是在寫入轉儲文件中的幾乎每個字節加上成本……但是如果您binlog_format設置為“行”,您正在為二進制日誌編寫更緊湊的版本……如果您binlog_format設置為“混合”,那麼二進制日誌中實際使用的格式取決於您的預設事務隔離級別。

設置innodb_flush_log_at_trx_commit從非常昂貴但符合 ACID 的預設值 1 到稍微不太安全的值 2 或明顯不太安全的值 0 肯定會加快您的插入速度,儘管它不太可能減少實際的 I/O,因為該值不會更改寫入事務日誌的內容,它只會更改 InnoDB 堅持要求作業系統確認日誌內容已保存到磁碟的頻率。如果在值設置為 2 或 0 期間發生崩潰,我在安全意義上使用“安全”,以防止最近的交易失去;1 防止 MySQL 或系統崩潰時的數據失去;如果 MySQL 崩潰而不是系統崩潰,2 可以防止數據失去,0 也不能防止。一旦你把它放回去,它就沒有任何後遺症。

快速旁注,顯示的一些看起來像評論的東西不是評論。/*!mnnrr 格式是 MySQL 向後兼容擴展,它告訴伺服器“如果您是 MySQL 版本 m.nn.rr 或更高版本,請執行此語句,否則忽略。”

/*!40000 ALTER TABLE `table_name` DISABLE KEYS */;
/*!40000 ALTER TABLE `table_name` ENABLE KEYS */;

每個表都在轉儲文件中被這些包圍。這些對 MyISAM 比對 InnoDB 更有用,因為DISABLE KEYS指示儲存引擎在發布之前不要更新任何非唯一索引ENABLE KEYS,允許寫入所有行數據,然後批量索引。使用 InnoDB,索引是在處理插入時建構的……所以當索引樹正在建構和洗牌時,那裡有很多 I/O 潛力。

InnoDB 緩衝池的大小將在磁碟 I/O 量中發揮作用——如果它相對較小,可能會很重要——因為任何不能留在記憶體中的東西都必須立即刷新到磁碟, 僅在再次需要時才被讀回,這對於索引尤其如此,對於實際行來說更是如此,因為在 InnoDB 中,行以主鍵順序物理儲存,並以主鍵mysqldump將它們寫入文件順序…所以它們按照它們將被儲存的順序插入…但是二級索引必須來回穿梭到磁碟,因為索引頁隨著給定表上的插入操作的進行而更新.

因此,由於所有不同的日誌記錄、安全性和 ACID 機制,每次插入都有一個“額外”活動的基線……而且索引似乎是可能創建大量額外 I/O 的萬用字元候選者。

引用自:https://dba.stackexchange.com/questions/54626