Mysql

壓力測試以使 MySQL InnoDB 的記憶體飽和

  • April 15, 2018

我正在調查 Windows 32 位記憶體問題(2G 限制),並且正在進行一項測試,該測試將最大限度地利用 MySQL 的記憶體,包括 InnoDB 緩衝池、每個連接記憶體和/或任何其他記憶體使用。

也許我可以使用一個查詢mysqlslap

更新

我認為其他人會從載入測試 mysql 的簡單方法中受益,這是一個簡單的問題,很多人都有“工具”。他們將幫助我的晦澀情況,我可以用它來調查我們的真正問題。

我們調整了配置,幾個月來都很好,但最近我們最終得到了mysqld: Out of memory (Needed 220428 bytes),MySQL 將在幾分鐘後崩潰。

我不是在研究你通常的“哎呀,我分配給緩衝池太多了”的問題。該記憶體是在啟動時分配的,不正確的設置會導致立即關閉。我真的在追求另外的 20%。僅僅用高緩衝池創建最大數量的連接並不能重現問題,所以我想強調一切。我不排除強調緩衝池,以防我們實際上遇到與它相關的 MySQL 錯誤。

以下是感興趣的人的資訊轉儲:

我對上述任何一項都沒有權威我只是希望能夠產生高記憶體活動,這樣我們就可以 A)重現問題,然後 B)在中期解決它,然後再移出 32 位,這是真正的解決方案,但是明天不會發生。

更新 2

原來 Mysql 5.5 的 mysqld.exe 已經建構為/LARGEADDRESSAWARE但不能將 innodb 引擎大小設置為等於或大於 1600M。連接確實/3GB使用了來自(通過 mysqlslap 證明)的額外記憶體。

vcvars32.bat
dumpbin.exe /headers mysqld.exe
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file mysqld.exe

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
            14C machine (x86)
              5 number of sections
       4E6A3CEF time date stamp Sat Sep 10 04:21:03 2011
              0 file pointer to symbol table
              0 number of symbols
             E0 size of optional header
            122 characteristics
                  Executable
                  Application can handle large (>2GB) addresses
                  32 bit word machine

我的結論。如果您不使用/3GB或以其他方式將連接記憶體 + innodb 緩衝記憶體設置為大於可用記憶體,那麼您最終肯定會得到mysqld: Out of memory……儘管 mysql 似乎最好拒絕連接以避免這個問題。

把消息帶回家,測試你可以max_connections用 mysqlslap實際實現,剩下的就是維護作業系統記憶體(和其他資源,如免費系統 PTE)。

來自MySQL 5.5 參考手冊中的Windows 平台限制:

在 Windows 32 位平台上,預設情況下不可能在單個程序中使用超過 2GB 的 RAM,包括 MySQL。

要調查什麼?我們已經知道當您最大化記憶體時會發生什麼:Really Bad Things™。

如果您的設置很可能會定期需要這麼多記憶體,那麼 32 位 Windows 是錯誤的平台。

幾乎普遍來說,最大的記憶體消耗者當然是 InnoDB 緩衝池,但是不需要任何查詢來測試它……你根本不需要任何活動或任何表,因為聲明的全部記憶體量innodb_buffer_pool_size在伺服器啟動時立即分配。緩衝池永遠不會增長,永遠不會縮小,永遠不會改變。空閒頁面的數量發生了變化,但從作業系統的角度來看,它們並不是“免費的”——它們仍然是分配的,只是在 InnoDB 中標記為不包含任何感興趣的內容。

如果作業系統拒絕分配為緩衝池提供的記憶體量,MySQL 將簡單地拒絕啟動。

在此處進行了說明,其中 OP 錯誤地認為伺服器正在崩潰並重新啟動“因為”無法為緩衝池分配記憶體,但實際上是由於 Linux 特定原因而崩潰但隨後拒絕重新啟動,因為系統由於其他東西過度使用了可用記憶體,因此不會分配池所需的記憶體總量……但是 InnoDB 緩衝池的這種 allocate-all-at-startup 行為不是特定於平台的。

因此,您應該能夠將此值設置為接近最大值,然後發現將伺服器程序置於邊緣之上根本不需要太多額外的努力。但我仍然不確定重點是什麼。

正如您所意識到的,MySQL將記憶體用於各種不同的目的,其中一些是動態大小的、可在每個連接的基礎上定義並按需分配的,這使得基於限制記憶體使用來配置伺服器幾乎不可能一些最壞情況下的絕對值,但期望該伺服器能夠有效地處理其典型負載。

最簡單的說明是,您可以通過限制同時客戶端連接的最大數量來明顯降低給定實例的理論最大記憶體使用率……但是任何給定的應用程序都需要一定數量的可用連接才能有效地執行,並且如果這個數字低於你的目標值,那麼你並沒有真正解決任何問題——感覺就像你已經解決了。

我說,要麼你的伺服器有足夠的記憶體來處理工作負載,要麼沒有。如果不是這樣,那麼嘗試“調整”你的方式來擺脫潛在的麻煩不太可能提供很多解決方案。


關於如何輕鬆產生更多記憶體需求的一些想法……

SELECT * FROM large_table ORDER BY non_indexed_column;

SELECT * FROM large_table WHERE non_indexed_column = some_value;

SELECT * FROM large_table WHERE some_column LIKE '%a_freqent_match%';

像這樣的查詢可能會觸發排序緩衝區、讀取緩衝區和/或隨機讀取緩衝區的分配,這應該向作業系統發出新請求以獲取緩衝區所需的記憶體。


簡單的解決方案:

DELIMITER $$

DROP PROCEDURE IF EXISTS `test`.`eat_memory_until_server_crashes` $$
CREATE PROCEDURE `test`.`eat_memory_until_server_crashes`()
BEGIN

-- this procedure is intended to eat as much memory as it can
-- it creates a series of consecutively-numbered session variables as large
-- as your configuration will allow them to be.

-- do not run this unless you intend to crash your server

-- also, do not run from a gui tool -- use the mysql command line client:

-- mysql> CALL test.eat_memory_until_server_crashes;

-- if you kill the query or thread before the server crashes, 
-- the memory consumed will be returned to the OS

 DECLARE counter INT DEFAULT 0;
 LOOP
   SET counter = counter + 1;
   SET @qry = CONCAT('SET @crash_me_',counter,' := REPEAT(\'a\', @@max_allowed_packet)');
   SELECT counter, @qry;
   PREPARE hack FROM @qry;
   EXECUTE hack;
   DEALLOCATE PREPARE hack;
   -- adjust timing or remove this entirely depending on how quickly you want this to happen
   DO SLEEP(0.1);
 END LOOP;

END $$

DELIMITER ;

靈感來源:施瓦茨,男爵;扎伊采夫,彼得;瓦迪姆·特卡琴科 (2012-03-05)。高性能 MySQL:優化、備份和複製(Kindle 位置 12194)。OReilly Media - A. Kindle 版。

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