• mysql实战优化之七:数据库侧配置优化


    对于功能,我们可能知道必须改进什么;但对于性能问题,有时我们可能无从下手。其实,任何计算机应用系统最终队可以归结为:

    1. cpu消耗

    2. 内存使用

    3. 对磁盘,网络或其他I/O设备的输入/输出(I/O)操作。

    但我们遇到性能问题时,要判断的第一点就是“在这三种资源中,是否有哪一种资源达到了有问题的程度”,因为这一点能指导我们搞清楚“需要优化重构什么”和“如何优化重构它”。

    本文目的

    了解一下MySQL优化的一些基础,MySQL的优化分为两个部分,一是服务器物理硬件的优化,二是MySQL自身(my.cnf)的优化,达到合理利用服务器现有资源,最大合理的提高MySQL性能。

    一、服务器硬件对MySQL性能的影响

     
    ① 磁盘寻道能力(磁盘I/O),以目前高转速SCSI硬盘(7200转/秒)为例,这种硬盘理论上每秒寻道7200次,这是物理特性决定的,没有办法改变。 MySQL每秒钟都在进行大量、复杂的查询操作,对磁盘的读写量可想而知。所以,通常认为磁盘I/O是制约MySQL性能的最大因素之一,对于日均访问量 在100万PV以上的Discuz!论坛,由于磁盘I/O的制约,MySQL的性能会非常低下!解决这一制约因素可以考虑以下几种解决方案:  使用RAID-0+1磁盘阵列,注意不要尝试使用RAID-5,MySQL在RAID-5磁盘阵列上的效率不会像你期待的那样快。
     
    ②CPU 对于MySQL应用,推荐使用S.M.P.架构的多路对称CPU,例如:可以使用两颗Intel Xeon 3.6GHz的CPU,现在我较推荐用4U的服务器来专门做数据库服务器,不仅仅是针对于mysql。
     
    ③物理内存对于一台使用MySQL的Database Server来说,服务器内存建议不要小于2GB,推荐使用4GB以上的物理内存,不过内存对于现在的服务器而言可以说是一个可以忽略的问题,工作中遇到了高端服务器基本上内存都超过了16G。
     

    二、 MySQL配置

      当解决了上述服务器硬件制约因素后,让我们看看MySQL自身的优化是如何操作的。对MySQL自身的优化主要是对其配置文件 my.cnf中的各项参数进行优化调整。下面我们介绍一些对性能影响较大的参数。  由于my.cnf文件的优化设置是与服务器硬件配置息息相关的,因而我们指定一个假想的服务器硬件环境:
     
    下面,我们根据以上硬件配置结合一份已经优化好的my.cnf进行说明:
    #vim /etc/my.cnf以下只列出my.cnf文件中[mysqld]段落中的内容,其他段落内容对MySQL运行性能影响甚微,因而姑且忽略。
    [mysqld]
    port = 3306
    serverid = 1
    socket = /tmp/mysql.sock
    skip-locking
    #避免MySQL的外部锁定,减少出错几率增强稳定性。
    skip-name-resolve
    #禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间。但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求!
    back_log = 384
    #back_log 参数的值指出在MySQL暂时停止响应新请求之前的短时间内多少个请求可以被存在堆栈中。  如果系统在一个短时间内有很多连接,则需要增大该参数的值,该参数值指定到来的TCP/IP连接的侦听队列的大小。不同的操作系统在这个队列大小上有它自 己的限制。 试图设定back_log高于你的操作系统的限制将是无效的。默认值为50。对于Linux系统推荐设置为小于512的整数。
    key_buffer_size = 256M
    #key_buffer_size指定用于索引的缓冲区大小,增加它可得到更好的索引处理性能。对于内存在4GB左右的服务器该参数可设置为256M或384M。注意:该参数值设置的过大反而会是服务器整体效率降低!
    max_allowed_packet = 4M
    thread_stack = 256K
    table_cache = 128K
    sort_buffer_size = 6M
    #查询排序时所能使用的缓冲区大小。注意:该参数对应的分配内存是每连接独占,如果有100个连接,那么实际分配的总共排序缓冲区大小为100 × 6 = 600MB。所以,对于内存在4GB左右的服务器推荐设置为6-8M。
    read_buffer_size = 4M
    #读查询操作所能使用的缓冲区大小。和sort_buffer_size一样,该参数对应的分配内存也是每连接独享。
    join_buffer_size = 8M
    #联合查询操作所能使用的缓冲区大小,和sort_buffer_size一样,该参数对应的分配内存也是每连接独享。
    myisam_sort_buffer_size = 64M
    table_cache = 512
    thread_cache_size = 64
    query_cache_size = 64M
    # 指定MySQL查询缓冲区的大小。可以通过在MySQL控制台观察,如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲不够的 情况;如果Qcache_hits的值非常大,则表明查询缓冲使用非常频繁,如果该值较小反而会影响效率,那么可以考虑不用查询缓 冲;Qcache_free_blocks,如果该值非常大,则表明缓冲区中碎片很多。
    tmp_table_size = 256M
    max_connections = 768
    #指定MySQL允许的最大连接进程数。如果在访问论坛时经常出现Too Many Connections的错误提 示,则需要增大该参数值。
    max_connect_errors = 10000000
    wait_timeout = 10
    #指定一个请求的最大连接时间,对于4GB左右内存的服务器可以设置为5-10。
    thread_concurrency = 8
    #该参数取值为服务器逻辑CPU数量*2,在本例中,服务器有2颗物理CPU,而每颗物理CPU又支持H.T超线程,所以实际取值为4*2=8
    skip-networking
    #开启该选项可以彻底关闭MySQL的TCP/IP连接方式,如果WEB服务器是以远程连接的方式访问MySQL数据库服务器则不要开启该选项!否则将无法正常连接!
    table_cache=1024
    #物理内存越大,设置就越大.默认为2402,调到512-1024最佳
    innodb_additional_mem_pool_size=4M
    #默认为2M
    innodb_flush_log_at_trx_commit=1
    #设置为0就是等到innodb_log_buffer_size列队满后再统一储存,默认为1
    innodb_log_buffer_size=2M
    #默认为1M
    innodb_thread_concurrency=8
    #你的服务器CPU有几个就设置为几,建议用默认一般为8
    key_buffer_size=256M
    #默认为218,调到128最佳
    tmp_table_size=64M
    #默认为16M,调到64-256最挂
    read_buffer_size=4M
    #默认为64K
    read_rnd_buffer_size=16M
    #默认为256K
    sort_buffer_size=32M
    #默认为256K
    thread_cache_size=120
    #默认为60
    query_cache_size=32M
    MyISAM和InnoDB优化:
    key_buffer_size – 这对MyISAM表来说非常重要。如果只是使用MyISAM表,可以把它设置为可用内存的 30-40%。合理的值取决于索引大小、数据量以及负载 — 记住,MyISAM表会使用操作系统的缓存来缓存数据,因此需要留出部分内存给它们,很多情况下数据比索引大多了。尽管如此,需要总是检查是否所有的 key_buffer 都被利用了 — .MYI 文件只有 1GB,而 key_buffer 却设置为 4GB 的情况是非常少的。这么做太浪费了。如果你很少使用MyISAM表,那么也保留低于 16-32MB 的 key_buffer_size 以适应给予磁盘的临时表索引所需。

    三、InnoDB优化

    1、内存利用方面

    innodb_buffer_pool_size:这个参数和MyISAM的key_buffer_size有相似之处,但也是有差别的。Innodb相比MyISAM表对缓冲更为敏感。这个参数主要缓存innodb表的索引,数据,插入数据时的缓冲。为Innodb加速优化首要参数。

      该参数分配内存的原则:这个参数默认分配只有8M,可以说是非常小的一个值。如果是一个专用DB服务器,那么他可以占到内存的70%-80%。这个参数不能动态更改,所以分配需多考虑。分配过大,会使Swap占用过多,致使Mysql的查询特慢。如果你的数据比较小,那么可分配是你的数据大小+10%左右做为这个参数的值。例如:数据大小为50M,那么给这个值分配innodb_buffer_pool_size=64M
    设置方法:
    innodb_buffer_pool_size=4G

    如果您只运行 InnoDB 存储引擎,那么您通常可以分配 80% 左右的内存给该缓冲池。而如果您要运行非常复杂的查询或者您有大量的并发数据库连接,亦或您有非常大的数据表的情况,那么就可能需要将此值下调一个等级,以便为其他的调用分配更多的内存。
    您在设置 InnoDB 缓冲池大小的时候,要确保其设置既不要过大,也不要频繁引起交换(swapping),因为这些绝对会降低您的数据库性能。有一个简单的检查方法就是在"Percona 监控和管理"。

     

    如图所示,如果你看到有大于 1MB 每秒的持续交换活动的话,您就需要减少缓冲池的大小了,或者使用其他的内存。

    如果您一开始并没有将 innodb_buffer_pool_size 的值设置正确,也不必担心。从 MySQL5.7 开始,您可以动态地改变 InnoDB 缓冲池的大小,而不需要重新启动数据库服务器了。 

    innodb_additional_mem_pool_size作用:用来存放Innodb的内部目录
    这个值不用分配太大,系统可以自动调。不用设置太高。通常比较大数据设置16M够用了,如果表比较多,可以适当的增大。如果这个值自动增加,会在error log有中显示的。

    设置方法:
    innodb_additional_mem_pool=16M

     

    table_cache是一个非常重要的MySQL性能参数,它在5.1.3之后的版本中叫做table_open_cache。table_cache主要用于设置table高速缓存的数量。由于每个客户端连接都会至少访问一个表,因此此参数的值与max_connections有关。

    缓存机制

    当某一连接访问一个表时,MySQL会检查当前已缓存表的数量。如果该表已经在缓存中打开,则会直接访问缓存中的表已加快查询速度;如果该表未被缓存,则会将当前的表添加进缓存并进行查询。

    在执行缓存操作之前,table_cache用于限制缓存表的最大数目:如果当前已经缓存的表未达到table_cache,则会将新表添加进来;若已经达到此值,MySQL将根据缓存表的最后查询时间、查询率等规则释放之前的缓存。

    参数调优

    一般来说,查看Open_tables与Opened_tables的值,也可以执行

    show global status like 'open%_tables';

    查看当前的open_tables情况,

    mysql> SHOW GLOBAL STATUS LIKE 'open%_tables';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | Open_tables   | 380   |
    | Opened_tables | 548   |
    +---------------+-------+
    2 rows in set (0.00 sec)
    
    mysql> 

    来查看这两个参数的值。其中Open_tables是当前正在打开表的数量,Opened_tables是所有已经打开表的数量。

    如果Open_tables的值已经接近table_cache的值,且Opened_tables还在不断变大,则说明mysql正在将缓存的表释放以容纳新的表,此时可能需要加大table_cache的值。对于大多数情况,

    比较适合的值:

    Open_tables / Opened_tables >= 0.85
    Open_tables / table_cache <= 0.95

    如果对此参数的把握不是很准,VPS管理百科给出一个很保守的设置建议:把MySQL数据库放在生产环境中试运行一段时间,然后把参数的值调整得比Opened_tables的数值大一些,并且保证在比较高负载的极端条件下依然比Opened_tables略大。

    清空缓存:命令将会清空当前所有缓存的表。

    mysql > flush tables;

    sort_buffer_size

    含义:为每个需要进行排序的线程分配该大小的一个缓冲区。(connection级别)

    影响:增加这值加速ORDER BY或GROUP BY操作。不过该参数对应的分配内存是每连接独占的,如果有100个连接,那么实际分配的总共排序缓冲区大小为100×sort_buffer_size。

    建议:一般设置为2M观察变化再调整。

    read_buffer_size

    含义:顺序查询操作所能使用的缓冲区大小。(connection级别)

    影响:和sort_buffer_size一样,该参数对应的分配内存也是每连接独享。

    建议:一般设置为2M再观察变化。

    read_rnd_buffer_size

    含义:随机查询操作所能使用的缓冲区大小。

    影响:每个线程独享。

    建议:一般设置为2M再观察变化。

     

    2、日志

    整体的日志文件大小受控于innodb_log_file_size和innodb_log_files_in_group两个参数,这对写性能非常重要。日志文件的总大小是每个文件的大小之和。要确定理想的日志文件大小,必须权衡正常数据变更的开销和崩溃恢复需要的时间,如果日志太小,InnoDB必然将做更多的检查点,导致更多的日志写。如果日志太大,在崩溃恢复时InnoDB可能不得不做大量的工作
     
    innodb_log_file_size 在指定日志的大小。
    分配原则:几个日值成员大小加起来差不多和你的innodb_buffer_pool_size相等。上限为每个日志上限大小为4G.一般控制在几个log文件相加大小在2G以内为佳。具体情况还需要看你的事务大小,数据大小为依据。
    说明:这个值分配的大小和数据库的写入速度,事务大小,异常重启后的恢复有很大的关系。高写入负载尤其是大数据集的情况下很重要。这个值越大则性能相对越高,但是要注意到可能会增加恢复时间。我经常设置为 64-512MB,跟据服务器大小而异。

    设置 innodb_log_file_size 的值是很值得推敲的:如果分配了较大的重做空间,那么对于写入密集型的工作负载来说性能会越好。但如果您的系统遭受到断电或其他问题导致崩溃的时候,那么其恢复时间则会越长。

    您可能会问:怎么才能知道自己的 MySQL 性能是否受限于当前的 InnoDB 日志文件大小呢?您可以通过查看未实际使用的重做日志空间大小来判定。最简单的方法就是查看“Percona 监控和管理”的 InnoDB 指标仪表板。

    在下图中,InnoDB 的日志文件不够大,使用空间已经屡屡接近于可用的重做日志空间了,如红线所示:

    设置方法:
    innodb_log_file_size=256M
    innodb_log_files_in_group指定你有几个日志组。分配原则: 一般我们可以用2-3个日值组。默认为两个。
    设置方法:
    innodb_log_files_in_group=3
     

    innodb_log_buffer_size:日志缓冲区大小(事务在内存中的缓冲)。分配原则:控制在2-8M.这个值不用太多的。他里面的内存一般一秒钟写到磁盘一次。具体写入方式和你的事务提交方式有关。在Oracle等数据库了解这个,一般最大指定为3M比较合适。
    参考:Innodb_os_log_written(show global status 可以拿到)
    如果这个值增长过快,可以适当的增加innodb_log_buffer_size
    另外如果你需要处理大理的TEXT,或是BLOB字段,可以考虑增加这个参数的值。
    设置方法:
    innodb_log_buffer_size=3M

    innodb_flush_logs_at_trx_commit控制事务的提交方式。分配原则:这个参数只有3个值,0,1,2请确认一下自已能接受的级别。默认为1,主库请不要更改了。性能更高的可以设置为0或是2,但会丢失一秒钟的事务。
    说明:
    这个参数的设置对innodb的性能有很大的影响,所以在这里给多说明一下。
    当这个值为1时:innodb 的事务LOG在每次提交后写入日志文件,并对日值做刷新到磁盘。这个可以做到不丢任何一个事务。
    当这个值为2时:在每个提交,日志缓冲被写到文件,但不对日志文件做到磁盘操作的刷新,在对日志文件的刷新在值为2的情况也每秒发生一次。但需要注意的是,由于进程调用方面的问题,并不能保证每秒100%的发生。从而在性能上是最快的。但操作系统崩溃或掉电才会删除最后一秒的事务。
    当这个值为0时:日志缓冲每秒一次地被写到日志文件,并且对日志文件做到磁盘操作的刷新,但是在一个事务提交不做任何操作。mysqld进程的崩溃会删除崩溃前最后一秒的事务。

    从以上分析,当这个值不为1时,可以取得较好的性能,但遇到异常会有损失,所以需要根据自已的情况去衡量。

    设置方法:
    innodb_flush_logs_at_trx_commit=1

    3、文件IO分配,空间占用方面

    innodb_file_per_table使每个Innodb的表,有自已独立的表空间。如删除文件后可以回收那部分空间。

    分配原则:只有使用不使用。但DB还需要有一个公共的表空间。1:为打开独立表空间,0:关闭独享表空间。
    设置方法:
    innodb_file_per_table=1

    补充独立表空间的优缺点

    优点:

    1.  每个表都有自已独立的表空间。
    2.  每个表的数据和索引都会存在自已的表空间中。
    3.  可以实现单表在不同的数据库中移动。
    4.  空间可以回收(除drop table操作处,表空不能自已回收)

    a)         Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过:alter table TableName engine=innodb;回缩不用的空间。

    b)         对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。

    c)         对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。

    缺点:

    单表增加过大,如超过100个G。

    结论:

    共享表空间在Insert操作上少有优势。其它都没独立表空间表现好。当启用独立表空间时,请合理调整一 下:innodb_open_files 。

    InnoDB Hot Backup(冷备)的表空间cp不会面对很多无用的copy了。而且利用innodb hot backup及表空间的管理命令可以实现单现移动。

    innodb_file_io_threads:InnoDB 中的文件 I/O 线程。 通常设置为 4,这个参数只在Windows上起作用。在LINUX上只会等于4。
    设置方法:
    innodb_file_io_threads=4

    innodb_open_files在InnoDB中,这个选项仅与你使用多表空间时有关。它指定InnoDB一次可以保持打开的.ibd文件的最大数目。最小值是10。默认值300。对.ibd文件的文件描述符是仅对InnoDB的。它们独立于那些由--open-files-limit服务器选项指定的描述符,且不影响表缓存的操作。
    分配原则:如果库里的表特别多的情况,请增加这个。这个值默认是300。
    设置方法:
    innodb_open_files=800 
    请适当的增加table_cache

    4、最大连接(用户)数

    MySQL的max_connections参数用来设置最大连接(用户)数。每个连接MySQL的用户均算作一个连接,max_connections的默认值为100。本文将讲解此参数的详细作用与性能影响。

    max_connections有关的特性

    MySQL无论如何都会保留一个用于管理员(SUPER)登陆的连接,用于管理员连接数据库进行维护操作,即使当前连接数已经达到了max_connections。因此MySQL的实际最大可连接数为max_connections+1;这个参数实际起作用的最大值(实际最大可连接数)为16384,即该参数最大值不能超过16384,即使超过也以16384为准;增加max_connections参数的值,不会占用太多系统资源。系统资源(CPU、内存)的占用主要取决于查询的密度、效率等;

    该参数设置过小的最明显特征是出现”Too many connections”错误;

    我们先来看下如何查看当前mysql的max_connections的值:

    mysql> show variables like "max_connections";
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | max_connections | 800   |
    +-----------------+-------+
    1 row in set (0.00 sec)
    
    mysql> 

    可以通过下面的sql语句将max_connections的值设置为200,当然前提是当前登录的用户有足够的权限:

    set global max_connections = 1000;

    这个设置会马上生效,但是当mysql重启时这个设置会失效,更好的办法是修改mysql的ini配置文件my.ini

    找到mysqld块,修改或者添加下面的设置:

    max_connections=1000

    这样修改之后,即便重启mysql也会默认载入这个配置了。

    幸运的是,MySQL 能够在峰值操作时轻易地获悉所用到的连接数量。通常,您需要确保在应用程序所使用到的最大连接数和可用的最大连接数之间至少有 30% 的差额。查看这些数字的一个简单方法是:在“Percona 监控和管理”的系统概述界面中查看使用 MySQL 连接图。下图显示了一个健康的系统,它有着足够数量的可用额外连接。

    还有一点需要记住:如果您的应用程序所创建的连接数量过多,通常会导致数据库运行缓慢。在这种情况下,您应该在数据库性能上做文章,而不是简单地允许建立更多的连接。更多的连接会使得潜在的性能问题更加恶化。

    或者:一旦有了对特定使用情况的准确估计,请将该比率乘以Web服务器的最大连接数。例如,如果Web服务器配置为最多为256个客户端提供服务,MySQL请求与Web请求的比率为1/8,则最好将最大数据库连接数设置为32。还要考虑留有安全余量,把这个数乘以2,得到最终的数量。只有在基础设施支持的情况下,才能尝试将数据库连接数的最大数量与Web服务器的客户端限制相匹配。在大多数情况下,最好保持接近32。

    5、线程相关

    MySQL里面为了提高客户端请求创建连接过程的性能,提供了一个连接池也就是 Thread_Cache池,将空闲的连接线程放在连接池中,而不是立即销毁.这样的好处就是,当又有一个新的请求的时候,mysql不会立即去创建连接 线程,而是先去Thread_Cache中去查找空闲的连接线程,如果存在则直接使用,不存在才创建新的连接线程。

    有关Thread_Cache在MySQL有几个重要的参数,简单介绍如下:

    thread_cache_size

    Thread_Cache 中存放的最大连接线程数.在短连接的应用中Thread_Cache的功效非常明显,因为在应用中数据库的连接和创建是非常频繁的,如果不使用 Thread_Cache那么消耗的资源是非常可观的!在长连接中虽然带来的改善没有短连接的那么明显,但是好处是显而易见的.但并不是越大越好大了反而 浪费资源这个的确定一般认为和物理内存有一定关系,如下:

    1G —> 8
    2G —> 16
    3G —> 32
    > 3G —> 64

    如果短连接多的话可以适当加大。

    thread_stack

    每个连接被创建的时候,mysql分配给它的内存.这个值一般认为默认就可以应用于大部分场景了,除非必要非则不要动它。

    thread_handing

    运用Thread_Cache处理连接的方式,5.1.19添加的新特性.有两个值可选[no-threads|one-thread-per-connection] 看字面意思大家也该猜出八九分了,呵呵,no-threads 服务器使用一个线程,one-thread-per-connection 服务器为每个客户端请求使用一个线程.原手册中提到,no-threads是在Linux下调试用的。

    mysql> show variables like 'thread%';
    +--------------------+---------------------------+
    | Variable_name      | Value                     |
    +--------------------+---------------------------+
    | thread_cache_size  | 51                        |
    | thread_concurrency | 10                        |
    | thread_handling    | one-thread-per-connection |
    | thread_stack       | 262144                    |
    +--------------------+---------------------------+
    4 rows in set (0.00 sec)
    
    mysql> show status like '%connections%';
    +-----------------------------------+-------+
    | Variable_name                     | Value |
    +-----------------------------------+-------+
    | Connection_errors_max_connections | 0     |
    | Connections                       | 3837  |
    | Max_used_connections              | 92    |
    +-----------------------------------+-------+
    3 rows in set (0.00 sec)
    
    mysql> show status like '%thread%';
    +------------------------------------------+-------+
    | Variable_name                            | Value |
    +------------------------------------------+-------+
    | Delayed_insert_threads                   | 0     |
    | Performance_schema_thread_classes_lost   | 0     |
    | Performance_schema_thread_instances_lost | 0     |
    | Slow_launch_threads                      | 0     |
    | Threads_cached                           | 34    |
    | Threads_connected                        | 50    |
    | Threads_created                          | 116   |
    | Threads_running                          | 1     |
    +------------------------------------------+-------+
    8 rows in set (0.00 sec)
    
    mysql> 

    通过以上3个命令,可以看到服务器的 thread_cache池中最多可以存放51个连接线程,为每个客户端球使用一个线程.为每个连接的线程分配262144/1024=256k的内存空间.

    服务器总共有3837次连接,最大并发连接数为92,当前在thread_cashe池中的连接数为34个,连接数为50个,处于活跃状态的有1个,共创建 了116次连接.显然这里以短连接为主.可以算出thread_cache命中率,公式为:

    Thread_Cache_Hit=(Connections-Thread_created)/Connections*100%

    当前服务器的Thread_cache命中率约为96.97%这个结果我还是比较满意的。但是可以看出 thread_cache_size有点多余改成48或32更合理一些。

    6、 其它相关参数

    这里说明一个比较重要的参数:

    innodb_flush_method这个参数控制着innodb数据文件及redo log的打开、刷写模式,对于这个参数,文档上是这样描述的,有三个值:fdatasync(默认),O_DSYNC,O_DIRECT

    • 默认是fdatasync,调用fsync()去刷数据文件与redo log的buffer
    • 为O_DSYNC时,innodb会使用O_SYNC方式打开和刷写redo log,使用fsync()刷写数据文件
    • 为O_DIRECT时,innodb使用O_DIRECT打开数据文件,使用fsync()刷写数据文件跟redo log

    首先文件的写操作包括三步:open,write,flush
    上面最常提到的fsync(int fd)函数,该函数作用是flush时将与fd文件描述符所指文件有关的buffer刷写到磁盘,并且flush完元数据信息(比如修改日期、创建日期等)才算flush成功。
    使用O_SYNC方式打开redo文件表示当write日志时,数据都write到磁盘,并且元数据也需要更新,才返回成功
    O_DIRECT则表示我们的write操作是从mysql innodb buffer里直接向磁盘上写

    至此我再总结一下三者写数据方式:

    • fdatasync模式:写数据时,write这一步并不需要真正写到磁盘才算完成(可能写入到操作系统buffer中就会返回完成),真正完成是flush操作,buffer交给操作系统去flush,并且文件的元数据信息也都需要更新到磁盘。
    • O_DSYNC模式:写日志操作是在write这步完成,而数据文件的写入是在flush这步通过fsync完成
    • O_DIRECT模式:数据文件的写入操作是直接从mysql innodb buffer到磁盘的,并不用通过操作系统的缓冲,而真正的完成也是在flush这步,日志还是要经过OS缓冲

    注:在类unix操作系统中,文件的打开方式为O_DIRECT会最小化缓冲对io的影响,该文件的io是直接在用户空间的buffer上操作的,并且io操作是同步的,因此不管是read()系统调用还是write()系统调用,数据都保证是从磁盘上读取的;O_SYNC方式表示以同步io的方式打开文件,任何写操作都将阻塞到数据写入物理磁盘后才返回。fsync(int filedes)函数只对由文件描述符filedes指定的单一文件起作用,并且等待写磁盘操作结束,然后返回。fdatasync(int filedes)函数类似于fsync,但它只影响文件的数据部分。而除数据外,fsync还会同步更新文件的元信息到磁盘。 

    设置方法:
    innodb_flush_method=O_DIRECT

    innodb_max_dirty_pages_pct作用:控制Innodb的脏页在缓冲中在那个百分比之下,值在范围1-100,默认为90。
    这个参数的另一个用处:当Innodb的内存分配过大,致使Swap占用严重时,可以适当的减小调整这个值,使达到Swap空间释放出来。建义:这个值最大在90%,最小在15%。太大,缓存中每次更新需要致换数据页太多,太小,放的数据页太小,更新操作太慢。
    设置方法:
    innodb_max_dirty_pages_pct=90
    动态更改需要有super权限:
    set global innodb_max_dirty_pages_pct=50;

     
     

    7、为临时表分配足够的内存

    在某些情况下,服务器在处理语句时会创建内部临时表。临时表用于内部操作如GROUP BY和distinct,还有一些ORDER BY查询以及UNION和FROM子句(派生表)中的子查询。这些都是在内存中创建的内存表。内存中临时表的最大大小由tmp_table_size和max_heap_table_size中较小的值确定。如果临时表的大小超过这个阈值,则将其转换为磁盘上的InnoDB或MyISAM表。此外,如果查询涉及BLOB或TEXT列,而这些列不能存储在内存表中,临时表总是直接指向磁盘。

    这种转换的代价很大,所以考虑增加max_heap_table_size和tmp_table_size变量的大小来帮助减少在磁盘上创建临时表的数量。请记住,这将需要大量内存,因为内存中临时表的大小是基于“最坏情况”的。例如,内存表总是使用固定长度的列,所以字符列使用VARCHAR(255)。这可以使内存中的临时表比想象的要大得多—事实上,这比查询表的总大小要大很多倍!当增加max_heap_table_size和tmp_table_sizevariables的大小时,一定要监视服务器的内存使用情况,因为内存中的临时表可能会增加达到服务器内存容量的风险。

    一般来说,32M到64M是建议值,从这两个变量开始并根据需要进行调优。

    在Monyog中的临时表监测

    临时表的监测是许多预定义的Monyog监测之一。它提供了一些临时表使用的指标,包括:

    • 允许的最大值:显示tmp_table_size服务器变量的值,它定义了在内存中创建的临时表的最大大小。与max_heap_table_size一起,这个值定义了可以在内存中创建的临时表的最大大小。如果内存临时表大于此大小,则将其存储在磁盘上。

    • 内存表的最大大小:显示max_heap_table_size服务器变量的值,该值定义了显式创建的MEMORY存储引擎表的最大大小。

    • 创建的临时表总数:显示created_tmp_tables服务器变量的值,它定义了在内存中创建的临时表的数量。

    • 在磁盘上创建的临时表:显示created_tmp_disk_tables服务器变量的值,该变量定义了在磁盘上创建的临时表的数量。如果这个值很高,则应该考虑增加tmp_table_size和max_heap_table_size的值,以便增加创建内存临时表的数量,从而减少在磁盘上创建临时表的数量。

    • 磁盘:总比率:基于created_tmp_disk_tables除以created_tmp_tables的计算值。由于tmp_table_size或max_heap_table_size不足而在磁盘上创建的临时表的百分比。Monyog将这个数字显示为一个进度条和百分比,以便快速确定有多少磁盘用于临时表,而不是内存。

     8、MySQL查询缓存

     见《MySQL查询缓存总结

  • 相关阅读:
    css修炼宝典
    衡量优秀的卓越的前端工程师
    Bootstrap 快速人门案例——前端最火的插件
    前端开发小白必学技能—非关系数据库又像关系数据库的MongoDB快速入门命令(2)
    前端开发必学技能之一———非关系数据库又像关系数据库的MongoDB快速入门第一步下载与安装
    小米路由器未授权访问漏洞
    linux下更改ssh登录前的banner信息
    centos下编译安装Openssl
    S2-032代码执行
    SSRF漏洞学习
  • 原文地址:https://www.cnblogs.com/duanxz/p/5121027.html
Copyright © 2020-2023  润新知