mysql 寫入文章 優化了MYSQL大量寫入問題

2021-10-17 16:01:34 字數 2909 閱讀 5902

今天這裡主要給大家介紹,在有大量寫入的場景,進行優化的方案。

總的來說mysql資料庫寫入效能主要受限於資料庫自身的配置,以及作業系統的效能,磁碟io的效能。主要的優化手段包括以下幾點:

1、調整資料庫引數

(1) innodb_flush_log_at_trx_commit

預設為1,這是資料庫的事務提交設定引數,可選值如下:

0: 日誌緩衝每秒一次地被寫到日誌檔案,並且對日誌檔案做到磁碟操作的重新整理,但是在乙個事務提交不做任何操作。

1:在每個事務提交時,日誌緩衝被寫到日誌檔案,對日誌檔案做到磁碟操作的重新整理。

2:在每個提交,日誌緩衝被寫到檔案,但不對日誌檔案做到磁碟操作的重新整理。對日誌檔案每秒重新整理一次。

有人會說如果改為不是1的值會不會不安全呢? 安全性比較如下:

在 mysql 的手冊中,為了確保事務的永續性和一致性,都是建議將這個引數設定為 1 。出廠預設值是 1,也是最安全的設定。

當innodb_flush_log_at_trx_commit和sync_binlog 都為 1 時是最安全的,在mysqld 服務崩潰或者伺服器主機crash的情況下,binary log 只有可能丟失最多乙個語句 或者乙個事務。

但是這種情況下,會導致頻繁的io操作,因此該模式也是最慢的一種方式。當innodb_flush_log_at_trx_commit設定為0,mysqld程序的崩潰會導致上一秒鐘所有事務資料的丟失。

當innodb_flush_log_at_trx_commit設定為2,只有在作業系統崩潰或者系統掉電的情況下,上一秒鐘所有事務資料才可能丟失。

針對同乙個表通過c#**按照系統業務流程進行批量插入,效能比較如下所示:(a.相同條件下:innodb_flush_log_at_trx_commit=0,插入50w行資料所花時間25.08秒;

(b.相同條件下:innodb_flush_log_at_trx_commit=1,插入50w行資料所花時間17分21.91秒;

(c.相同條件下:innodb_flush_log_at_trx_commit=2,插入50w行資料所花時間1分0.35秒。

結論:設定為0的情況下,資料寫入是最快的,能迅速提公升資料庫的寫入效能, 但有可能丟失上1秒的資料。

(2) temp_table_size,heap_table_size

這兩個引數主要影響臨時表temporary table 以及記憶體資料庫引擎memory engine表的寫入,設定太小,甚至會出現table is full的報錯資訊.

要根據實際業務情況設定大於需要寫入的資料量占用空間大小才行。

(3) max_allowed_packet=256m,net_buffer_length=16m,set autocommit=0

備份和恢復時如果設定好這三個引數,可以讓你的備份恢復速度飛起來哦!

(4) innodb_data_file_path=ibdata1:1g;ibdata2:64m:autoextend

很顯然表空間後面的autoextend就是讓表空間自動擴充套件,不夠預設情況下只有10m,而在大批量資料寫入的場景,不妨把這個引數調大;

讓表空間增長時一次盡可能分配更多的表空間,避免在大批量寫入時頻繁的進行檔案擴容

(5) innodb_log_file_size,innodb_log_files_in_group,innodb_log_buffer_size

設定事務日誌的大小,日誌組數,以及日誌快取。預設值很小,innodb_log_file_size預設值才幾十m,innodb_log_files_in_group預設為2。

然而在innodb中,資料通常都是先寫快取,再寫事務日誌,再寫入資料檔案。設定太小,在大批量資料寫入的場景,必然會導致頻繁的觸發資料庫的檢查點,去把 日誌中的資料寫入磁碟資料檔案。頻繁的重新整理buffer以及切換日誌,就會導致大批量寫入資料效能的降低。

當然,也不宜設定過大。過大會導致資料庫異常宕機時,資料庫重啟時會去讀取日誌中未寫入資料檔案的髒資料,進行redo,恢復資料庫,太大就會導致恢復的時間變的更長。當恢復時間遠遠超出使用者的預期接受的恢復時間,必然會引起使用者的抱怨。

這方面的設定倒可以參考華為雲的資料庫預設設定,在華為雲2核4g的環境,貌似預設配置的buffer:16m,log_file_size:1g----差不多按照mysql官方建議達到總記憶體的25%了;而日誌組files_in_group則設定為4組。

2核4g這麼低的硬體配置,由於引數設定的合理性,已經能抗住每秒數千次,每分鐘8萬多次的讀寫請求了。

而假如在寫入資料量遠大於讀的場景,或者說方便隨便改動引數的場景,可以針對大批量的資料匯入,再做調整,把log_file_size調整的更大,可以達到innodb_buffer_pool_size的25%~100%。

(6) innodb_buffer_pool_size設定mysql innodb的可用快取大小。理論上最大可以設定為伺服器總記憶體的80%.

設定越大的值,當然比設定小的值的寫入效能更好。比如上面的引數innodb_log_file_size就是參考innodb_buffer_pool_size的大小來設定的。

(7) innodb_thread_concurrency=16

故名思意,控制併發執行緒數,理論上線程數越多當然會寫入越快。當然也不能設定過大官方建議是cpu核數的兩倍左右最合適。

(8) write_buffer_size

控制單個會話單次寫入的快取大小,預設值4k左右,一般可以不用調整。然而在頻繁大批量寫入場景,可以嘗試調整為2m,你會發現寫入速度會有一定的提公升。

(9) innodb_buffer_pool_instance

預設為1,主要設定記憶體緩衝池的個數,簡單一點來說,是控制併發讀寫innodb_buffer_pool的個數。

在大批量寫入的場景,同樣可以調大該引數,也會帶來顯著的效能提公升。

(10) bin_log

Mysql日誌 寫入機制

事務執行過程中,先把日誌寫到binlog cache,事務提交的時候,再把binlog cache寫到binlog檔案中。乙個事務的binlog是不能被拆開的,因此不論這個事務多大,也要確保一次性寫入。系統給binlog cache分配了一片記憶體,每個執行緒乙個,引數 binlog cache s...

MYSQL中文寫入報錯

一些關於檢視和修改字符集的mysql知識 檢視mysql的字符集 show variables where variable name like char 檢視某乙個資料庫字符集 show create database enterprises 注 enterprises為資料庫 檢視某乙個資料表字...

mysql寫入中文亂碼

亂碼可謂是程式猿的常見問題了,下面就大致介紹幾種常見的情況。常見於頁面 前台到後台傳值 寫入到資料庫這三個方面。頁面相對是最為容易解決的,往往是在相應的jsp頁面或者html頁面設定相關的字符集即可。如 在傳值過程中,也是亂碼出現的頻繁地。先不說到底是什麼場景了,通常常用的方案有如下幾個 配置指定的...