MySQL 事務的 ACID 特性中,D 表明持久性(Durability):在使用 InnoDB 引擎時,當返回客戶端一個成功完成事務的確認時, InnoDB 就會保證數據的一致性,即便該數據在此時尚未寫入磁盤,由於 InnoDB 引擎的重作日誌已經連續地記錄了已完成的事務。InnoDB 不是在事務執行的時候直接將數據寫入磁盤,即不會當即將更新的數據寫入磁盤,而是由 InnoDB 存儲引擎的後臺 worker 線程負責執行。能夠根據在配置文件中的配置來設置日誌寫入磁盤的頻率,默認狀況下是每次事務會刷寫到磁盤一次。php
不一樣的持久性設置會對數據庫的性能產生很大的影響,默認狀況下配置文件 my.ini 或 my.cnf 中 innodb_flush_log_at_trx_commit 的值爲 1:mysql
mysql> select @@global.innodb_flush_log_at_trx_commit; +-----------------------------------------+ | @@global.innodb_flush_log_at_trx_commit | +-----------------------------------------+ | 1 | +-----------------------------------------+
不一樣的設置會改變 InnoDB 的持久性和性能,該選項有 3 個值:sql
1(默認) | 對於每一個事務日誌,InnoDB 都會把日誌寫入(write)並刷寫(flush)到磁盤。速度最慢,可是最持久 |
2 | InnoDB 將全部發生的事務日誌寫入(write)磁盤,而且每秒對這些數據刷寫(flush)一次 |
0 | InnoDB將最近一秒中所發生的全部事務日誌寫入(write)磁盤,而後將這些日誌刷寫(flush)到磁盤。 |
(寫日誌在 write 時發生 ,寫入數據文件到磁盤在操做系統 flush buffer 時發生)數據庫
在一些場景下能夠經過破壞真正的持久性來顯著提升性能。性能
測試一下 MyISAM 引擎、 InnoDB 引擎(不一樣持久性下)的插入速度。測試
測試環境:ui
CentOS6.6 64-bit/2Gspa
MySQL 5.6.29操作系統
mysql> select version(); +------------+ | version() | +------------+ | 5.6.29-log | +------------+
PHP 7.0.7線程
[root@localhost test]# php -v PHP 7.0.7 (cli) (built: Feb 11 2017 16:47:30) ( NTS ) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
表結構:
MyISAM
CREATE TABLE `m` ( `id` int(10) NOT NULL AUTO_INCREMENT, `number` int(10) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1
InnoDB
CREATE TABLE `i` ( `id` int(10) NOT NULL AUTO_INCREMENT, `number` int(10) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1
PHP 文件:
<?php set_time_limit(0); $host = 'localhost'; $user = 'root'; $pwd = 'root'; $database = 'test'; $mysqli = new mysqli($host, $user, $pwd, $database); if($mysqli->connect_error) { die('Connect Error: '.$mysqli->connect_error); } $table_name = 'example_myisam'; // $table_name = 'example_innodb'; $times = 10000; $sql_truncate = "TRUNCATE TABLE {$table_name}"; $mysqli->query($sql_truncate); $time = -microtime(true); for($i = 0; $i < $times; $i++) { $sql = "INSERT INTO {$table_name} (`number`) VALUES ({$i})"; if(false === $mysqli->query($sql)) { die('ERROR: '.$mysqli->error); } } $time += microtime(true); echo '用時',$time,'秒';
分別測試 1w 條數據和 10w 條數據不一樣狀況下所耗費的時間:
MyISAM | InnoDB.innodb_flush_log_at_trx_commit =1 | InnoDB.innodb_flush_log_at_trx_commit =2 | InnoDB.innodb_flush_log_at_trx_commit =0 | |||||||||||||
第1次 | 第2次 | 第3次 | 平均 | 第1次 | 第2次 | 第3次 | 平均 | 第1次 | 第2次 | 第3次 | 平均 | 第1次 | 第2次 | 第3次 | 平均 | |
1w | 0.697s | 0.722s | 0.822s | 0.747s | 18.204s | 19.012s | 17.173s | 18.130s | 0.842s | 0.871s | 1.058s | 0.924s | 0.796s | 0.795s | 0.966s | 0.852s |
10w | 6.579s | 6.421s | 6.703s | 6.568s | 201.111s | 198.429s | 140.926s | 180.155s | 9.208s | 9.566s | 9.068s | 9.281s | 8.022s | 7.838s | 7.918s | 7.926s |