注:个人经验分享,转载请注明出处
优化配置文件my.ini文件中的配置
第一个重要指标:innodb_flush_log_at_trx_commit=2
可选值有0,1,2 mysql默认配置的是1
这里引用mysql官方解释这个指标:
# If set to 1, InnoDB will flush (fsynct同步) the transaction logs to the
# disk at each commit, which offers full ACID behavior. If you are
# willing to compromise this safety, and you are running small
# transactions, you may set this to 0 or 2 to reduce disk I/O to the
# logs. Value 0 means that the log is only written to the log file and
# the log file flushed to disk approximately(大约) once per second. Value 2
# means the log is written to the log file at each commit, but the log
# file is only flushed to disk approximately(大约) once per second.
innodb_flush_log_at_trx_commit=2
翻译下来就是:
innodb_flush_log_at_trx_commit = 0,Innodb 中的Log Thread 没隔1 秒钟会将log buffer中的数据写入到文件,同时还会通知文件系统进行文件同步的flush 操作,保证数据确实已经写入到磁盘上面的物理文件。但是,每次事务的结束(commit 或者是rollback)并不会触发Log Thread 将log buffer 中的数据写入文件。所以,当设置为0 的时候,当MySQL Crash 和OS Crash 或者主机断电之后,最极端的情况是丢失1 秒时间的数据变更。
innodb_flush_log_at_trx_commit = 1,这也是Innodb 的默认设置。我们每次事务的结束都会触发Log Thread 将log buffer 中的数据写入文件并通知文件系统同步文件。这个设置是最安全的设置,能够保证不论是MySQL Crash 还是OS Crash 或者是主机断电都不会丢失任何已经提交的数据。
innodb_flush_log_at_trx_commit = 2,当我们设置为2 的时候,Log Thread 会在我们每次事务结束的时候将数据写入事务日志,但是这里的写入仅仅是调用了文件系统的文件写入操作。而我们的文件系统都是有缓存机制的,所以Log Thread 的这个写入并不能保证内容真的已经写入到物理磁盘上面完成持久化的动作。文件系统什么时候会将缓存中的这个数据同步到物理磁盘文件Log Thread 就完全不知道了。所以,当设置为2 的时候,MySQL Crash 并不会造成数据的丢失,但是OS Crash 或者是主机断电后可能丢失的数据量就完全控制在文件系统上了。各种文件系统对于自己缓存的刷新机制各不一样,
综上所述:0是最不安全的,如果断电会丢失mysql缓存,文件系统缓存中将近一秒的数据。
1是最安全的,怎么都不会丢失数据,但是也是性能最差的。
2是居于中间。
通常优化的时候把该值设置为2可大约提升百分之200到300的性能。
下面针对该配置进行测试:
sql语句:
DROP TABLE IF EXISTS `supan`;
CREATE TABLE `supan` (
`name` varchar(30) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`grade` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
java程序:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class InsertTestData
{
public static void main(String[] args)
{
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://127.0.0.1:3306/test";
String user = "root";
String password = "root";
try
{
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, password);
//故意设置自动提交为false
conn.setAutoCommit(false);
PreparedStatement pst = (PreparedStatement) conn.prepareStatement("insert into supan(name,grade) values(?,?)");
//记录开始时间
Long startTime = System.currentTimeMillis();
for (long i = 0; i < 1000000; i++) {
pst.setString(1, "张三");
pst.setLong(2,i);;
pst.addBatch();
pst.executeBatch();
//故意每次都提交一个sql语句,增加事务的开启和关闭
conn.commit();
pst.clearBatch();
}
// 语句执行完毕,提交本事务
Long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
conn.close();
} catch (Exception e)
{
System.out.println("Sorry,can`t find the Driver!");
e.printStackTrace();
}
}
}
上面测试代码插入一百万数据:在配置为1的情况下执行时间为:1337496
在配置为2的情况下执行时间为:434137
效率提升整200%