select*fromperformance_schema.variables_by_threadwherevariable_name='transaction_isolation';isolation英/aslen/美/aslen/n.隔离,孤立;孤独;绝缘;(尤指对混合物或微生物的)离析静态参数和动态参数mysql的系统参数还可以分为静态参数和动态参数,动态参数可以mysql运行中修改,静态参数在mysql启动后无法修改
如果会话级系统参数设置为default,对应的是全局系统参数值,下面两个设置会话级参数的语句效果是一样的
set@@session.max_join_size=default;set@@session.max_join_size=@@global.max_join_size;持久化参数设置在系统参数设置时,一个容易犯的错误是在mysql运行时修改了参数值,但没有同时修改参数文件里面的配置,当mysql重新启动后,参数文件里的旧值生效,之前的修改丢掉了,在mysql8里,mysql推出了让参数持久化的命令,可以让在联机时修改的系统参数在重新启动后仍然生效
setpersistmax_connections=1000;或set@@persist.max_connections=1000;如果想让系统参数在本次mysql运行时不生效,只在下次启动时生效,可以使用下面的命令:
setpersist_onlyback_log=100;或set@@persist_only.back_log=100;持久化的系统参数以json格式保存持久化的参数以json格式保存在数据目录的mysqld-auto.cnf文件中。
cat/var/lib/mysql/mysql-auto.cnf可以通过resetpersist命令来清除mysql-auto.cnf文件中的所有配置,也可以通过resetpersist接参数名的方式来清除某个指定的配置参数
select variable_name ,variable_sourceassouce ,variable_path ,set_time ,set_userasuser ,set_hostfromperformance_schema.variables_infowherevariable_name='max_connections'orvariable_name='socket'查询参数文件select variable_path ,variable_source, ,count(*)from performance_schema.variables_infowhere length(variable_path)!=0groupby variable_path ,variable_source;计算mysql在负载高峰时占用的总内存select(@@key_buffer_size+@@innodb_buffer_pool_size+@@innodb_log_buffer_size+@@binlog_cache_size+@@max_connections*(@@read_buffer_size+@@read_rnd_buffer_size+@@sort_buffer_size+@@join_buffer_size+@@thread_stack+@@tmp_table_size))/(1024*1024*1024)asmax_memory_gb;在实际工作中,这里算出额数值通常偏大,因为所有的线程都同时用到设定内存分配的最大值的情况不会出现,每个线程如果只是处理简单的工作,大约只需要256kb的内存,通过查询sys.memory_global_total视图可以得到当前mysql实例使用内存的总和
系统参数key_buffer_size从字面上理解是指定索引缓存的大小,需要注意的是它只对myisam表起作用,对innodb表无效。这个参数在字面意思上并没有明确加上myisam,是因为它是在myisam作为mysql默认存储引擎时产生的。由于现在通常用的是innodb表,因此通常不需要调整这个参数
SELECT count(*)asTABLES ,concat(round(sum(table_rows)/1000000,2),'M') num_row, concat(round(sum(data_length)/(1024*1024*1024),2),'G')DATA, concat(round(sum(index_length)/(1024*1024*1024),2),'G')idx, concat(round(sum(data_length+index_length)/(1024*1024*1024),2),'G')total_sizeFROM information_schema.TABLESWHERE engine='InnoDB';把参数innodb_buffer_pool_size设置成超过innodb的总数据量是没有意义的,通常设置到能容纳innodb的活跃数据就够了。
两个mysql的状态参数可以计算出它的命中率:(MySQL8才有)
(1)innodb_buffer_pool_read_resquests:表示想innodb缓冲池进行逻辑读的次数
(2)innodb_buffer_pool_reads:表示物理磁盘中读取数据的次数
innodb缓冲池的命中率的计算公式如下:
InnoDB缓存池的命中率=(Innodb_buffer_pool_read_requests-Innodb_buffer_pool_reads)/Innodb_buffer_pool_read_requests*100%
代表mysql不能从innodb缓冲池读到需要的数据而不得不从硬盘中进行读的次数,使用下面的命令查询mysql每秒从磁盘读的次数:
mysqladminextended-status-ri1|grepinnodb_buffer_pool_reads把这个值和硬盘的I/O能力进行对比,如果接近了硬盘处理I/O的上限,那么从操作系统层查看到的CPU用于等
瓶颈,增大InnoDB缓存池可能会减少MySQL访问硬盘的次数,提高数据库的性能。
早期调整innodb_pool_size需要重新启动mysql,从mysql5.7后,这个参数可以动态进行调整,例如
mysqld-h10.72.1.230-P3307-uroot-p123456--innodb_buffer_pool_instances=8日志innodb日志保存着已经提交得数据变化,用于在奔溃恢复时把数据库的变化恢复到数据文件,除了系统奔溃,其他时候都不会读日志文件。向日志文件写数据的方式是顺序的,这笔离散写的效率要高很多,而向数据文件写数据通常是离散写的比较多。
日志缓冲区是一个内存缓冲区,innodb使用它来缓冲重做日志事件,然后在将器写入磁盘,日志缓冲区的大小由系统参数innodb_log_buffer_size控制,默认是16M,在大多数情况下是够用的。如果有大型事务或大量较小的并发事务,可以考虑增大innodb_log_buffer_size,这个参数在mysql8中可以动态设置
默认在datadir下有两个48M的日志文件ib_logfile0和ib_logfile1
#使用下面的命令可以激活这些计量:setglobalinnodb_monitor_enable='log_lsn_%';#激活后,一个查询结果的列子如下:selectname,count,statusfrominformation_schema.innodb_metricswherenamelike'log_lsn%';#这里的log_lsn_checkpoint_age是当前日志量减去最近一次检查点的日志量,等于log_lsn_current减去log_lsn_checkpoint,也就是日志文件的使用量,因为对日志文件的写入是循环覆盖的,检查点之前的日志都已经写入数据文件了,不再需要了,可以被覆盖了,这里看到的日志文件是使用量大约是17MBlsn(logsequencdnumber)使用showengineinnodbstatus查询日志产生量showengineinnodbstatus\G这里的lsn是425640652,最近一次检查点的lsn是406841423,计算出当前日志文件的使用量是这两个值之差:
logsequencenumber=425640625lastcheckpoint=406841432selectround((425640625-406841432)/1024/1024)logsize_MB;设置日志文件大小考虑MySQL默认在数据目录下有两个48MB的日志文件,ib_logfile0和ib_logfile1,对于繁忙的数据库,这样的日志文件通常太小了,因为当日志文件写满时,会触发检查点,大内存中的数据写入磁盘,小的日志文件会频繁的触发检查点,增加写磁盘的频率,引起系统性能下降
大的日志文件内容的数据变化很大,会造成数据库在奔溃恢复时耗时较长,但是新的mysql版本奔溃恢复速度已经很快了,因此把日志文件设置大一些通常会不错,甚至可以设置的和innodb缓冲池一样大
另外一些备份工具要备份在备份过程中产生的重做日志,如果日志文件过小,备份工具备份日志的数据跟不上日志产生的速度时,需要备份的日志可能已经覆盖了,例如XtraBackup工具可能会遇到下面的错误:
xtrabackup:error:itlookslikeInnoDBloghaswrappedaroundbeforextrabackupcould
processallrecordsduetoeitherlogcopyingbeingtooslow,orlogfilesbeingtoosmall.
一个合理大小的日志文件应该可以容纳数据库在高峰时1到2小时的数据变化,下面的例子是查询一分钟产生的日志量:
#设置pager只显示lsnpagergrepsequence#查询当前的lsnshowengineinnodbstatus\G#休眠一分钟selectsleep(60)#再次查询当前的lsnshowengineinnodbstatus\G#取消设置的pagernopager#根据一分钟的采样,可以计算出一个小时的日志量:selectround((1455007613-1439955157)*60/1024/1024)"1hourlog(MB)";决定日志文件的两个参数日志文件的大小有两个参数决定:
(1)innodb_log_file_in_group:表示一个组里有多少个文件,默认2
(2)innodb_log_file_size:表示单个日志文件的大小,默认为48MB
因此如果保持innodb_log_files_group为2不变,把innodb_log_file_size设置为860M,可以容纳高峰期两个小时的日志
修改日志文件大小的方法很简单,只需要修改参数文件中的innodb_log_file_size的设置,然后重启MySQL即可,不要删除当前的日志文件,在启动过程中,mysql会发现参数值和当前日志文件的大小不一样,然后自动删除旧的日志文件,并创建新的日志文件。
mysql8中引入一个参数innodb_dedicated_server,这个参数的默认设置是off,就像这个参数名所建议的一样,当mysql独占当前服务器资源的时候,可以把这个参数这个为on,这时MySQL会自动探测当前服务器的内存大小并设置下面4个参数
(1)innodb_buffer_pool_size
(2)innodb_log_file_size
(3)innodb_log_files_in_group
(4)innodb_flush_method
其中前面三个参数是根据当前服务器的内存大小计算出来的,这样对运维在虚拟机上或者云上运行的mysql很方便,当调整了内存的大小后,mysql会在启动时,自动调整这3个参数,省去每次手工修改参数的工作
innodb_log_file_size和innodb_log_file_in_group两个参数是根据innodb_buffer_pool_size计算出来的
当参数innodb_dedicated_server为ON时,如果还显示设置了这些参数,则显示设置的这些参数会优先生效。
显示指定某一个值,并不会影响另外3个参数值的自动设定。
当参数innodb_dedicated_server为ON时,mysql每次启动时会自动探测服务器内存并自动调整上述几个参数值,在任何时候MySQL都不会将自适应值保存在持久配置中,利用这个参数就可以保证服务器(包括虚拟机或者容器)扩展以后,MySQL能“自动适应”,以尽量利用更多的服务器资源
硬盘的读写通常对数据库性能影响最大的因素之一。
innodb_flush_log_trx_commit参数控制事务提交时写重做日志的行为方式,它有3个值:
0和2都是每秒进行一次文件系统到磁盘的同步,因此这两种方式的性能都差不多,当系统奔溃时,最多丢失1秒的数据。但是0和2还有细微的不同,当设置为2时,每次事务提交都写日志文件,因此数据已经从MySQL的日志缓存刷新到了操作系统的文件缓存中,如果只是MySQL崩溃,而操作系统没有崩溃,将不会丢失数据,因此0和2比较起来,通常设置为2比较好。
sync_binlog参数控制事务提交时写二进制的行为方式,它有三个值:0、1和N
写二进制的成本比写重做日志的成本要高得很多,因为重做日志的大小和文件名是固定的,重做日志循环写入日志文件,而每次写二进制时,文件都会进行扩展,如果写满了还要新建文件,这样每次写二进制文件不但要写数据,还要修改二进制文件的元数据,因此sync_binlog设置成1把innodb_log_trx_commit设置成1对性能负面影响还要大得多
innodb_flush_method参数控制MySQL将数据刷新到Innodb的数据文件和日志文件的动作,在windows系统上有两个选项,unbuffered是默认和推荐的选择,另一个是normal,linux系统上常用的选项有以下几种:
通常对于硬盘性能好的服务器,可以设置成O_DIRECT,这样避免在innodb缓存和操作系统缓存中存有两份数据,而且innodb缓存比操作系统缓存效率高,因为innodb缓存专门针对为innodb的数据设计的,而操作系统缓存是为了通用的数据设计的
设置成O_DIRECT_NO_FSYNC时,因为写磁盘时不执行fsync(),速度可能会快,但是突然断电时可能会丢失数据
对于读操作大大多于写操作的应用,设置成fsync会比设置成O_DIRECT性能略好
但如何选择这些参数最终需要经过测试才能确定,测试时要注意观察状态参数innodb_data_fsync,它记录着调用fsync()的次数,通常fsync()和O_DIRECT调用fsync()的次数差不多,O_DIRECT_NO_FSYNC的次数最少。
innodb后台线程会进行一些I/O操作,例如把缓冲池中的脏页刷新到磁盘,或者将更改从更改缓冲区写入到对应的二级索引。innodb试图以不影响服务器正常工作的方式执行这些I/O操作,这需要它直到系统的I/O的处理能力,它根据参数innodb_io_capacity评估系统的I/O带宽。参数innodb_io_capacity_max值定义了系统的I/O能力的上限,防止I/O的峰值时消耗服务器的全部I/O带宽
showvaribaleslike'innodb_io_capacity%';这两个参数的设定是基于系统的每秒能处理的I/O数量(IOPS),可以把innodb_io_capacity_max设置成极
限的IOPS,innodb_io_capacity设置成它的一半左右。目前业界有很多I/O测试软件可以测出系统的IOPS,
也可以通过硬盘配置进行估算,例如一块15K转速的传统硬盘的IOPS的参考值大约是200,高端SSD盘可以达
到60万
状态参数innodb_data_fsyncs记录着数据刷新到磁盘得次数,把innodb_io_capacity调大后,可以看到这个状态参数也相应得增加了。
showstatuslike'max_used%';+---------------------------+---------------------+|Variable_name|Value|+---------------------------+---------------------+|Max_used_connections|229||Max_used_connections_time|2022-03-0507:58:01|+---------------------------+---------------------+binlog_order_commits系统参数binlog_order_commits默认是ON,如果把这个参数设置为off将不能保证事务的提交顺序和写入二进制日志的顺序一致,这不会影响到数据的一致性,在高并发场景下还能提升一定的吞吐量。
40162[Warning][MY-010055][Server]IPaddress'192.168.87.178'couldnotberesolved:Nameorservicenotknown把这个参数设置成on也有弊端,就是只能使用ip进行grant赋权,不能使用主机名,通常主机名不会变,而ip改变的可能比主机名大,因此在一个生产主机上把skip_name_resolve从off改成on要小心,因为原来用主机名服务的权限不能再使用了
MySQL8中引入了资源组(resourcegroup)的概念,它可以设定某一类SQL语句所允许使用的资源(目前只包括cpu),在高并发的系统中,资源组可以保证关键交易的性能,例如可以设定市场统计类的交易在白天使用较少的资源,以免影响客户的交易,在晚上可以使用较多的资源。
#在information_schema.resource_groups视图中可以查询资源组中的信息,默认有两个资源组select*frminformation_schema.resource_groups\G创建资源组使用createresourcegroup语句可以创建资源组,创建一个batch用户资源组的列子如下:
selectthread_id,resource_groupfromperformance_schema.threadswherethread_id=10054;+-----------+----------------+|thread_id|resource_group|+-----------+----------------+|10054 |Batch |+-----------+----------------+资源组的限制资源组目前在使用中还是一些限制:
\1.如果安装了线程池插件,则资源组不可用。
\2.资源组在macOS上不可用,因为它不提供用于将CPU绑定到线程的API。
\3.在FreeBSD和Solaris上,忽略资源组线程优先级,尝试更改优先级会导致警告。实际上,所有线程都以优先级0运行。
\4.在Linux上,需要对mysqld进程设置CAP_SYS_NICE功能,否则将忽略资源组线程优先级。
####在Linux上设置cap_sys_nice功能
cap_sys_nice可以使用setcap命令手动设置该功能,使用getcap检查功能,相应的命令和输出结果如下:
setcapcap_sys_nice+ep/usr/sbin/mysqldgetcap/usr/sbin/mysqld/usr/sbin/mysqld=cap_sys_nice+ep#或者使用sudosystemctleditmysql在MySQL服务里增加加下面的内容[Service]AmbientCapabilities=CAP_SYS_NICE#然后重启MySQL服务,设置线程优先级才能生效Windows平台上的线程的优先级线程优先级范围Windows优先级-20到-10thread_priority_highest-9到-1thread_priority_above_normal0thread_priority_normal1到10thread_priority_below_normal10到19thread_priority_lowest找出topsql当要对MySQL进行优化时,找到topsql语句通常是第一步
top-HPIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND#然后在mysql数据库中对pid进行查询select*fromperformationce_schema.threadswherethread_os_id=PID\G#查询的结果有thread_idprocesslist_id#如果有必要,可以使用processlist_id字段指定的线程好杀死这个线程或者正在执行的sql,不能使用thread_id字段执行kill命令,不能可能会杀错线程:killquery32;或者kill32;慢查询日志开启慢查询日志
Usage:mysqldumpslow[OPTS...][LOGS...]--后跟参数以及log文件的绝对地址;-swhattosortby(al,at,ar,c,l,r,t),'at'isdefaultal:averagelocktimear:averagerowssentat:averagequerytimec:countl:locktimer:rowssentt:querytime-rreversethesortorder(largestlastinsteadoffirst)-tNUMjustshowthetopnqueries-adon'tabstractallnumberstoNandstringsto'S'-nNUMabstractnumberswithatleastndigitswithinnames-gPATTERNgrep:onlyconsiderstmtsthatincludethisstring-hHOSTNAMEhostnameofdbserverfor*-slow.logfilename(canbewildcard),defaultis'*',i.e.matchall-iNAMEnameofserverinstance(ifusingmysql.serverstartupscript)-ldon'tsubtractlocktimefromtotaltime