背景
今天羣裏有人問mysqldump出來的insert語句,是否能夠按每 10 row 一條insert語句的形式組織。html
思考1: 參數--extended-insert
回憶過去所學:mysql
我只知道有一對參數
--extended-insert(默認值)
表示使用長 INSERT ,多 row 在合併一塊兒批量 INSERT,提升導入效率sql
--skip-extended-insert
一行一個的短INSERT數據庫
均不知足羣友需求,沒法控制按每 10 row 一條 insert 語句的形式組織。服務器
思考2: 「避免大事務」
以前一直沒有考慮過這個問題。這個問題的提出,相信主要是爲了「避免大事務」。因此知足 insert 均爲小事務便可。性能
下面,咱們來探討一下如下問題:測試
- 什麼是大事務?
- 那麼 mysqldump 出來的 insert 語句多是大事務嗎?
什麼是大事務?
- 定義:運行時間比較長,操做的數據比較多的事務咱們稱之爲大事務。
- 大事務風險:
- 鎖定太多的數據,形成大量的阻塞和鎖超時,回滾所須要的時間比較長。
- 執行時間長,容易形成主從延遲。
- undo log膨脹
- 避免大事務:我這裏按公司實際場景,規定了,每次操做/獲取數據量應該少於5000條,結果集應該小於2M
mysqldump出來的SQL文件有大事務嗎?
前提,MySQL 默認是自提交的,因此若是沒有明確地開啓事務,一條 SQL 語句就是一條事務。在 mysqldump 裏,就是一條 SQL 語句爲一條事務。this
按照個人「避免大事務」自定義規定,答案是沒有的。url
原來,mysqldump 會按照參數--net-buffer-length,來自動切分 SQL 語句。默認值是 1M。按照咱們前面定義的標準,沒有達到咱們的 2M 的大事務標準。spa
--net-buffer-length 最大可設置爲 16777216,人手設置大於這個值,會自動調整爲 16777216,即 16M。設置 16M,能夠提高導出導入性能。若是爲了不大事務,那就不建議調整這個參數,使用默認值便可。
[root@192-168-199-198 ~]# mysqldump --net-buffer-length=104652800 -uroot -proot -P3306 -h192.168.199.198 test t >16M.sql mysqldump: [Warning] option 'net_buffer_length': unsigned value 104652800 adjusted to 16777216 #設置大於16M,參數被自動調整爲16M
注意,指的是 mysqldump 的參數,而不是 mysqld 的參數。 官方文檔提到: If you increase this variable, ensure that the MySQL server net_buffer_length system variable has a value at least this large.
意思是 mysqldump 增大這個值,mysqld 也得增大這個值,測試結論是不須要的。懷疑官方文檔有誤。
不過,在導入的時候,受到服務器參數 max_allowed_packet 影響,它控制了服務器能接受的數據包的最大大小,默認值是 4194304,即 4M。因此導入數據庫時須要調整參數 max_allowed_packet 的值。
set global max_allowed_packet=16*1024*1024;
不調整的話,會出現如下報錯:
[root@192-168-199-198 ~]# mysql -uroot -proot -P3306 -h192.168.199.198 test <16M.sql mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 2006 (HY000) at line 46: MySQL server has gone away
相關測試
最後,我放出個人相關測試步驟
mysql> select version(); +------------+ | version() | +------------+ | 5.7.26-log | +------------+ 1 row in set (0.00 sec)
造100萬行數據
create database test; use test; CREATE TABLE `t` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, `c` varchar(255) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into t values (1,1,'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyztuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'); insert into t select * from t; #重複執行20次 # 直到出現Records: 524288 Duplicates: 0 Warnings: 0 # 說明數據量達到100多萬條了。 mysql> select count(*) from t; +----------+ | count(*) | +----------+ | 1048576 | +----------+ 1 row in set (1.04 sec)
數據大小以下,有 284MB
[root@192-168-199-198 test]# pwd /data/mysql/mysql3306/data/test [root@192-168-199-198 test]# du -sh t.ibd 284M t.ibd
--net-buffer-length=1M
[root@192-168-199-198 ~]# mysqldump -uroot -proot -S /tmp/mysql3306.sock test t >1M.sql [root@192-168-199-198 ~]# du -sh 1M.sql 225M 1M.sql [root@192-168-199-198 ~]# cat 1M.sql |grep -i insert |wc -l 226
默認 --net-buffer-length=1M 的狀況下,225M 的SQL文件裏有 226 條 insert ,平均下來確實就是每條 insert 的 SQL 大小爲 1M。
--net-buffer-length=16M
[root@192-168-199-198 ~]# mysqldump --net-buffer-length=16M -uroot -proot -S /tmp/mysql3306.sock test t >16M.sql [root@192-168-199-198 ~]# du -sh 16M.sql 225M 16M.sql [root@192-168-199-198 ~]# cat 16M.sql |grep -i insert |wc -l 15
默認--net-buffer-length=16M 的狀況下,225M 的 SQL 文件裏有 15 條 insert,平均下來確實就是每條 insert 的 SQL 大小爲 16M。
因此,這裏證實了 --net-buffer-length 確實可用於拆分 mysqldump 備份文件的SQL大小的。
性能測試
insert 次數越多,交互次數就越多,性能越低。 但鑑於上面例子的 insert 數量差距不大,只有 16 倍,性能差距不會很大(實際測試也是如此)。咱們直接對比 --net-buffer-length=16K 和 --net-buffer-length=16M 的狀況,他們insert次數相差了 1024 倍。
[root@192-168-199-198 ~]# time mysql -uroot -proot -S /tmp/mysql3306.sock test <16K.sql mysql: [Warning] Using a password on the command line interface can be insecure. real 0m10.911s #11秒 user 0m1.273s sys 0m0.677s [root@192-168-199-198 ~]# mysql -uroot -proot -S /tmp/mysql3306.sock -e "reset master"; mysql: [Warning] Using a password on the command line interface can be insecure. [root@192-168-199-198 ~]# time mysql -uroot -proot -S /tmp/mysql3306.sock test <16M.sql mysql: [Warning] Using a password on the command line interface can be insecure. real 0m8.083s #8秒 user 0m1.669s sys 0m0.066s
結果明顯。--net-buffer-length 設置越大,客戶端與數據庫交互次數越少,導入越快。
結論
mysqldump 默認設置下導出的備份文件,符合導入需求,不會形成大事務。性能方面也符合要求,不須要調整參數。
參考: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_net-buffer-length