最近,发现数据库中偶尔会发现丢失数据的问题,为了解决此问题,查询了很多资料,最终优化mysql。
查看项目log,发现丢失数据的时间点报错1205,通过查询mysql官方错误代码对照表得知,1205是数据库发生阻塞。经过分析发现,项目中某些表会不断的进行写操作,而读操作却很少,写操作意味着排它锁(写锁),如果线程太多,某个线程进行写操作,同时会锁表,其他线程只能处于等待状态,MySQL的系统参数innodb_lock_wait_timeout为锁等待时间,默认为50s,如果其他某个线程等待时间超过50s,那么这么线程不会进行往下执行,报1205阻塞的错误。
将innodb_lock_wait_timeout的值调大,可以保证数据丢失的会少点,但是这样可能会引起更多的线程等待,mysql的性能会降低。
最后做出的决定还是在mysql的执行效率的找解决办法,对于系统参数进行调整,让mysql提升SQL的执行速度。
sort_buffer_size = 4M
#默认为256KB
# Sort_Buffer_Size 是一个connection级参数,在每个connection(session)第一次需要使用这个buffer的时候,一次性分配设置的内存。
#Sort_Buffer_Size 并不是越大越好,由于是connection级的参数,过大的设置+高并发可能会耗尽系统内存资源。例如:500个连接将会消耗 500*sort_buffer_size(8M)=4G内存
#Sort_Buffer_Size 超过2KB的时候,就会使用mmap() 而不是 malloc() 来进行内存分配,导致效率降低。
join_buffer_size = 2M
#默认为256K
#用于表间关联缓存的大小,和sort_buffer_size一样,该参数对应的分配内存也是每个连接独享。
#如果应用中,很少出现join语句,则可以不用太在乎join_buffer_size参数的设置大小。
#如果join语句不是很少的话,个人建议可以适当增大join_buffer_size到1MB左右,如果内存充足可以设置为2MB
thread_cache_size = 512
默认为18
query_cache_size = 32M
默认值为1M
query_cache_limit = 2M
#默认1M
innodb_autoextend_increment = 256
#默认是8M
#当自动扩展表空间被填满之时,为扩展而增加的尺寸(MB为单位)
# mysql 5.6.5版本之前默认值是8Mb,从5.6.6版本之后默认为64Mb,最小值为1Mb最大值为1000Mb。
#这个参数受到innodb_file_per_table参数的影响
max_allowed_packet = 100M
#默认4M
innodb_table_locks = 0
#使用LOCK TABLES虽然可以给InnoDB加表级锁,但必须说明的是,表锁不是由InnoDB存储引擎层管理的,而是由其上一层──MySQL Server负责的,仅当autocommit=0、innodb_table_locks=1(默认设置)InnoDB层才能知道MySQL加的表锁,MySQL Server也才能感知InnoDB加的行锁,这种情况下,InnoDB才能自动识别涉及表级锁的死锁;否则,InnoDB将无法自动检测并处理这种死锁。
#如果autocommit=1,Innodb的内部表锁可能会导致deadlock,可以通过设置innodb_table_locks=0来解决这个问题
innodb_buffer_pool_size = 16G(此参数为解决问题的关键,最初有的统计报表打开需要十几秒,此参数调整后,最多两三秒就打开了)
#默认为8M
#InnoDB 用来高速缓冲数据和索引内存缓冲大小
#InnoDB最重要的设置,对InnoDB性能有决定性的影响
#可以设置60-80%的内存
innodb_additional_mem_pool_size = 20M
#默认值为1MB
#InnoDB 用来存储数据字典(data dictionary)信息和其它内部数据结构(internal data structures)的存储器组合(memory pool)大小
#参数对系统整体性能并无太大的影响,只要能存放需要的数据就好,否则只会浪费内存
#几百个Innodb 表的,推荐20M以内就足以了。
#此参数在5.7中已经移除
https://dev.mysql.com/worklog/task/?id=7628
innodb_read_io_threads = 6
#读线程数
innodb_write_io_threads = 6
#写线程数
innodb_log_buffer_size = 48M
#默认为16M
#当事务提交时,保存脏数据到内存中,后续再刷新保存到磁盘
#适当调整此参数大小,可以减少磁盘I/O
查找相关资料进行调整后执行效率提升了,查看一些操作的执行时间,都是在1秒内完成,可以满足本公司的业务需求,不会造成数据丢失。
刚开始有点想不通,为啥mysql官方的版本不给个优化好的安装包,后来想了半天,可能是考虑到某些用户的电脑配置问题吧,或者因为mysql免费,如果想进行优化,那就自己想办法吧。
此文章的优化方案,只是对单机版的mysql进行优化,不是SQL优化。如果想实现高并发高可用的mysql解决方案,建议采用:读写分离、分库分表等解决方案吧。