事务性表的性能
MySQL 中的 Innodb 除了支持行锁定外,还支持事务,这往往也是使用 Innodb 的另一个原因。在一些特定的应用中,程序依赖于数据库提供的事务操作(如 rollback 或者 commit),这给应用程序带来了不少方便。
当然,如果你并没有在应用程序中使用事务操作的打算,而只是看中了 Innodb 的其它特性,比如行锁定、外键以及易于修复等,你仍然可以使用它。虽然人们一提到 Innodb 就会联想到事务,但是大多数的站点使用 Innodb 都不是冲着事务,而是为了理想中的性能,事实上大多数的站点都不需要事务级别的保障。
也许行锁定正符合你的站点应用类型,而且由于行锁定带来的其它问题你都可以统统搞定,那么,对于一个事务性表,我们需要注意哪些呢?
预写日志方式(WAL),这也是 Innodb 实现事务的方法。当有事务提交时,Innodb 首先将它写到内存中的事务日志缓冲区,随后当事务日志写入磁盘时, Innodb 才更新实际数据和索引。这里有一个关键点,那就是事务日志何时写入磁盘。
为此,MySQL 提供了一个配置选项,它有3个可选的值:
innodb_flush_log_at_trx_commit = 1
表示事务提交时立即将事务日志写入磁盘,同时数据和索引也立即更新。这符合事务的持久性原则。
innodb_flush_log_at_trx_commit = 0
表示事务提交时不立即将事务日志写入磁盘,而是每隔1秒写入磁盘文件一次,并且刷新到磁盘,同时更新数据和索引。这样一来,如果 mysqld 奔溃,那么在内存中事务日志缓存区最近 1 秒的数据将会丢失,这些更新将永远无法恢复。
innodb_flush_log_at_trx_commit = 2
表示事务提交时立即写入磁盘文件,但是不立即刷新到磁盘,而是每隔1秒刷新到磁盘一次,同时更新数据和索引。在这种情况下,即使 mysqld 奔溃后,位于内核缓冲区的事务日志仍然不会丢失,只有当操作系统奔溃的时候才会丢失最后 1 秒的数据。
上面提到的“写入磁盘文件”和“刷新到磁盘”,它们的区别在于前者只是将数据写入位于物理内存中的内核缓冲区,而后者是将内核缓冲区中的数据真正写入磁盘。
显然,将 innodb_flush_log_at_trx_commit 设置为 0 可以获得最佳性能,同时它的数据丢失可能性也最大。
另一个重要的配置选项是 Innodb 数据和索引的内存缓冲池大小,MySQL 提供了 innodb_buffer_pool_size 选项来设置这个数值,如果你在 MySQL 中大量使用 Innodb 类型表,则可以将缓冲池大小设置为物理内存的 80%,并持续关注它的使用率。
另外,可以这样设置 innodb_flush_method 选项:
innodb_flush_method = O_DIRECT
这样一来,innodb 将可以跳过文件系统缓冲区,提高 I/O 性能,同时凭借自身的缓冲池更加高效地工作。