优化主要是通过调整mysql参数来提高性能,(vi /etc/my.cnf)
下面是一些我认为生产环境需要设置,也是比较重要的参数:
#绑定本机或者局域网ip,生产环境不要开放外网访问
bind-address=127.0.0.1
#数据库的最大连接数,这个值决定数据库最大支持多少并发连接。另外还需要同时设置操作系统的允许进程打开文件数(此处略过)
max_connections=2000
#非交互连接空闲超时时长,单位:秒。一般客户端会释放连接,不会空闲这么长,但不排除某些情况下发生服务端空闲,比如,客户端没有关闭连接却断开了这种情况,这个值默认是8小时,可能会引起超过最大连接数的错误,客户端新的连接会连接不上,所以需要适当调小这个值。另外,客户端的连接池的空闲时长需要小于这个值,否则连接池内可能出现无效连接(可能各种驱动实现不同,表现会不同)
举例:go客户端连接池如果出现无效连接会报错,但会自动重新生成新的连接,不影响使用。其他驱动表现可能会不同。
wait_timeout=30
#表高速缓存的大小。每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。如果发现open_tables等于table_open_cache,并且opened_tables在不断增长,那么就需要增加table_open_cache的值
table_open_cache = 1000
#单位:秒,事务等待获取资源等待的最长时间,超过这个时间还未分配到资源则会返回应用失败。在那些不想因为等待其他事务释放锁而发生错误的场合,需要适当增大这个值
innodb_lock_wait_timeout = 500
#这个参数主要缓存innodb表的索引、数据、插入数据时的缓冲,这个值最为重要,直接影响mysql的性能,在允许的范围内尽量的大
innodb_buffer_pool_size=2G
#redo日志的大小,一般来说,应该足够容纳服务器一个小时的活动内容,这个参数也比较重要。建议innodb_buffer_pool_size/innodb_log_file_in_group,这个值太小,日志切换会频繁,影响性能,太大的话有时意外宕机后恢复时间过长。如果对 Innodb 数据表有大量的写入操作,应该适当增大 innodb_log_file_size
innodb_log_file_size=200M
#redo buff,缓存还未提交的事务的缓冲区的大小。一般默认值16MB是够用的,但如果事务之中含有blog/text等大字段,这个缓冲区会被很快填满会引起额外的IO负载
innodb_log_buffer_size=50M
#当 innodb_flush_log_at_trx_commit 取值为 0 的时候,log buffer 会 每秒写入到日志文件并刷写(flush)到磁盘。但每次事务提交不会有任何影响,也就是 log buffer 的刷写操作和事务提交操作没有关系。在这种情况下,MySQL性能最好,但如果 mysqld 进程崩溃,通常会导致最后 1s 的日志丢失。当取值为 1 时,每次事务提交时,log buffer 会被写入到日志文件并刷写到磁盘。这也是默认值。这是最安全的配置,但由于每次事务都需要进行磁盘I/O,所以也最慢。当取值为 2 时,每次事务提交会写入日志文件,但并不会立即刷写到磁盘,日志文件会每秒刷写一次到磁盘。这时如果 mysqld 进程崩溃,由于日志已经写入到系统缓存,所以并不会丢失数据;在操作系统崩溃的情况下,通常会导致最后 1s 的日志丢失。如果对于准确性要求不是非常高,比如日志系统,建议设置为2,能非常高的提高写性能。如果对准确性要求较高,建议使用默认值1
innodb_flush_log_at_trx_commit=2
#sync_binlog=0,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。如果sync_binlog>0,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失1个事务的数据。但是binlog虽然是顺序IO,但是设置sync_binlog=1,多个事务同时提交,同样很大的影响MySQL和IO性能。虽然可以通过group commit的补丁缓解,但是刷新的频率过高对IO的影响也非常大。对于高并发事务的系统来说,“sync_binlog”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。
sync_binlog=10
#线程池缓存大小,当客户端断开连接后 将当前线程缓存起来 当在接到新的连接请求时快速响应 无需创建新的线程.。(这个参数对性能影响不是很大,可以不做优化)
thread_cache_size=512
总结:
在实际项目中我使用过以上优化参数,把一次几十万条插入的大事务从2分钟加速到几秒钟。
优化的宗旨就是在条件允许的情况下想办法减少磁盘io操作,尽量使用内存,提高性能。所以上述最重要的三个参数是
innodb_buffer_pool_size、innodb_flush_log_at_trx_commit、sync_binlog
根据项目实际情况,在稳定性和性能之间做一个适当取舍。
除此之外,mysql还有一些其他的局部优化策略,比如分表,sql写法等,尤其分表,跟实际业务有关,不过会增加系统复杂性,下次有空再总结。按照上述方法调整参数已经能满足大部分项目需要。
下面列出关于索引的,我觉得比较重要的2点,对性能有明显影响,同时操作起来比较容易:
1)关于读取数据时sql写法,根据我的经验,主要是要尽量使用索引,
避免全表扫描,就不会出现太大的性能问题。可以使用explain来查看是否使用到了索引。其他的sql优化性价比低,只有当需要极致提高性能才有必要研究一下。
2)去掉不是很必要的索引,将会极大提高插入性能。索引越多插入越慢,因为每次插入都需要重建所有索引。插入和删除多的表尽量减少索引,读取多,插入和删除少的表适当增加索引。越大的表索引尽量少。