控制mysqldump導出的SQL文件的事務大小

背景

今天羣裏有人問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 均爲小事務便可。性能

下面,咱們來探討一下如下問題:測試

  1. 什麼是大事務?
  2. 那麼 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

相關文章
相關標籤/搜索