简介:
数据库的东西,往往一个参数就牵涉N多知识点。所以简单的说一下。大家都知道innodb是支持事务的存储引擎。事务的四个特性ACID即原子性(atomicity),一致性(consistency),隔离性(isolation),持久性(durability)。其中原子性,一致性,持久性通过redo log 和 undo来实现。redo log称为重做日志,用来保证事务的原子性和持久性。undo log用来保证事务的一致性。 当事务提交时,必须先将该事务的所有日志写入到重做日志文件(redo log)进行持久化(当然先写到日志缓冲区,而不是直接写文件,关于什么时候刷新到磁盘文件,是一个比较复杂的问题,同学们自行查阅资料),待事务提交操作才算完成。innodb的redo log是顺序I/O,所以设置合适的值能够大大提高数据库性能。那么是不是设置的越大越好呢?
设置的太小:当一个日志文件写满后,innodb会自动切换到另外一个日志文件,而且会触发数据库的检查点(Checkpoint),这会导致innodb缓存脏页的小批量刷新,会明显降低innodb的性能。
设置的太大:设置很大以后减少了checkpoint,并且由于redo log是顺序I/O,大大提高了I/O性能。但是如果数据库意外出现了问题,比如意外宕机,那么需要重放日志并且恢复已经提交的事务,如果日志很大,那么将会导致恢复时间很长。甚至到我们不能接受的程度。
那么我们如何估算log file该设置为多大?通常我们可以通过观察show status中innodb_os_log_written状态变量来查看innodb对日志文件写出了多少数据。一个好用的经验是,查看10-100秒间隔的数字,然后记录峰值。可以用这个判断日志缓冲是否设置的正好。例如,若看到峰值是每秒写100kb数据到日志,那么1MB的日志缓冲已经足够了。也可以使用这个衡量标准来决定日志文件设置多大会比较好。如果峰值是100KB/s,那么256M的日志文件足够存储至少2560秒的日志记录。一般来说,日志文件的全部大小,应该足够容纳服务器一个小时的活动内容。
下面看实际的测试(由于是虚拟机,所以使用sysbench模拟据量写入,生产环境选择数据库最繁忙的时候测试):
[root@yayun-mysql-server ~]# sysbench --test=oltp --oltp-table-size=100000 --oltp-read-only=off --init-rng=on --num-threads=16 --max-requests=0 --oltp-dist-type=uniform --max-time=180 --mysql-user=root --mysql-socket=/tmp/mysqld.sock --mysql-password=123456 --db-driver=mysql --mysql-table-engine=innodb --oltp-test-mode=complex prepare
1.首先计算innodb每分钟产生的日志量:
(root@yayun-mysql-server) [(none)]>pager grep sequence PAGER set to ‘grep sequence‘ (root@yayun-mysql-server) [(none)]>show engine innodb status\G select sleep(60); show engine innodb status\G Log sequence number 6377275259 1 row in set (0.00 sec) 1 row in set (1 min 0.00 sec) Log sequence number 6403945555 1 row in set (0.00 sec) (root@yayun-mysql-server) [(none)]>nopager PAGER set to stdout (root@yayun-mysql-server) [(none)]>select (6403945555 - 6377275259) / 1024 / 1024 as MB_per_min; +-------------+ | MB_per_min | +-------------+ | 25.43477631 | +-------------+ 1 row in set (0.02 sec) (root@yayun-mysql-server) [(none)]>
注意Log sequence number,这是写入事务日志的总字节数。所以,现在你可以看到每分钟有多少MB日志写入(这里的技术适用于所有版本的MySQL,在5.0及更高版本,你可以从SHOW GLOBAL STATUS的输出看Innodb_os_log_written的值) 。
通过计算后得到每分钟有25M的日志写入。
根据经验法则。通常我们设置redo log size足够大,能够容纳1个小时的日志写入量。
1小时日志写入量=25M * 60=1500M,大约等于1.5G。由于默认有两个日志重做日志文件ib_logfile0和ib_logfile1。在日志组中的每个重做日志文件的大小一致,并以循环的方式写入。innodb存储引擎先写重做日志文件0,当达到文件的最后时,会切换到重做日志1,并checkpoint。以此循环。
所以我们可以大约设置innodb_log_file_size=800M。注意:在innodb1.2.x版本之前,重做日志文件总的大小不得大于等于4G,而1.2.x版本将该限制扩大到了521G。
innodb_log_file_size = 800M
[root@yayun-mysql-server mysql]# du -sh ib_logfile* 801M ib_logfile0 801M ib_logfile1 [root@yayun-mysql-server mysql]#
对于innodb 1.2.x版本之前如果设置大于4G则报错
[root@yayun-mysql-server mysql]# tail -n 10 yayun-mysql-server.err 140511 1:01:15 InnoDB: Completed initialization of buffer pool 140511 1:01:15 InnoDB: Error: combined size of log files must be < 4 GB 140511 1:01:15 [ERROR] Plugin ‘InnoDB‘ init function returned error. 140511 1:01:15 [ERROR] Plugin ‘InnoDB‘ registration as a STORAGE ENGINE failed. 140511 1:01:15 [ERROR] Failed to initialize plugins. 140511 1:01:15 [ERROR] Aborting 140511 1:01:15 [Note] /usr/local/mysql/bin/mysqld: Shutdown complete 140511 01:01:15 mysqld_safe mysqld from pid file /data/mysql/yayun-mysql-server.pid ended [root@yayun-mysql-server mysql]#
而innodb 1.2.x以后版本则不会:
[root@yayun-mysql-server mysql5.6]# tail -f yayun-mysql-server.err 2014-05-11 01:06:47 5205 [Note] InnoDB: Using Linux native AIO 2014-05-11 01:06:47 5205 [Note] InnoDB: Initializing buffer pool, size = 128.0M 2014-05-11 01:06:47 5205 [Note] InnoDB: Completed initialization of buffer pool 2014-05-11 01:06:47 5205 [Note] InnoDB: Highest supported file format is Barracuda. 2014-05-11 01:06:47 5205 [Warning] InnoDB: Resizing redo log from 2*3072 to 2*327680 pages, LSN=1085681253 2014-05-11 01:06:47 5205 [Warning] InnoDB: Starting to delete and rewrite log files. 2014-05-11 01:06:47 5205 [Note] InnoDB: Setting log file ./ib_logfile101 size to 5120 MB InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 3100 3200 3300 3400 3500 3600 3700 3800 3900 4000 4100 4200 4300 4400 4500 4600 4700 4800 4900 5000 5100 2014-05-11 01:12:40 5205 [Note] InnoDB: Setting log file ./ib_logfile1 size to 5120 MB InnoDB: Progress in MB: 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 3100
参考资料
http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/