暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL DBA的自我修养(十一)

记忆乘凉 2016-12-28
579

101:理解 key_buffer_size 以及对应的状态参数。

key_buffer_size是MyISAM存储引擎的参数,指定用于索引的缓冲区大小,增加它可得到更好处理的索引(对所有读和多重写),它直接影响表的存取效率。可以再MySQL的参数文件中设置key_buffer_size的值,对于一般myisam数据库,建议key_buffer设置为物理内存的1/4(针对MyISAM引擎),甚至是物理内存的30%~40%,如果key_buffer_size设置太大,系统就会频繁的换页,降低系统性能。因为MySQL使用操作系统的缓存来缓存数据,所以我们得为系统留够足够的内存;在很多情况下数据要比索引大得多。如果机器性能优越,可以设置多个key_buffer,分别让不同的key_buffer来缓存专门的索引,单个key_buffer的大小不能超过4G,否则会报错。调整Key_reads/Key_read_requests的大小正常情况下得小于0.01

 


102:理解 read buffer size,这个参数主要解决 myisam 表的读取问题。

read_buffer_size:是MySQL读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能。

 


103:学会使用数据字典获取系统的很多信息,例如系统里面有哪些表、这些表的引擎是什么,表的行数是多少,系统里面有哪些列,哪些索引,索引建立在哪些列上。

查看单表数据结构:show createtable t/G;

查看单表上的索引:show index fromt;show keys from t;

use information_schema;

select TABLE_NAME,ENGINE from TABLES ;

表结构:SELECT  a.TABLE_NAME "",   a.COLUMN_NAME"",  a.COLUMN_TYPE "类型",           a.COLUMN_DEFAULT "默认值",  a.IS_NULLABLE"是否为空",  a.CHARACTER_SET_NAME "表字符集",      a.COLLATION_NAME  "校验字符集", CONCAT(a.COLUMN_COMMENT,a.COLUMN_KEY,a.EXTRA) "列备注",      b.TABLE_COMMENT "表备注" ,   b.ENGINE"引擎"FROMinformation_schema.COLUMNS a,information_schema.TABLES b WHEREa.TABLE_SCHEMA=b.TABLE_SCHEMA AND a.TABLE_SCHEMA='test'ANDa.TABLE_NAME=b.TABLE_NAME;

索引信息:

Select TABLE_SCHEMA,TABLE_NAME,NON_UNIQUE,INDEX_NAME,SEQ_IN_INDEX,COLUMN_NAME,INDEX_TYPE,CONCAT(COMMENT,INDEX_COMMENT)    INDEX_COMMENT FROM  INFORMATION_SCHEMA.STATISTICSWHERE  TABLE_SCHEMA = 'test'ORDER BYTABLE_SCHEMA,TABLE_NAME,INDEX_NAME,SEQ_IN_INDEX;



104mysql 内存分配总体思路,buffer pool 总体依据、用户线程总体依据。

mysql> show global variables like '%buffer%';

+-------------------------+------------+

| Variable_name          | Value      |

+-------------------------+------------+

| bulk_insert_buffer_size | 4194304    |

| innodb_buffer_pool_size | 2013265920 |

| innodb_change_buffering | inserts    |

| innodb_log_buffer_size | 8388608    |

| join_buffer_size       | 1048576    |

| key_buffer_size        | 16777216   |

| myisam_sort_buffer_size | 262144     |

| net_buffer_length      | 16384      |

| preload_buffer_size    | 32768      |

| read_buffer_size       | 1048576    |

| read_rnd_buffer_size   | 1048576    |

| sort_buffer_size       | 1048576    |

| sql_buffer_result      | OFF        |

+-------------------------+------------+

13 rows in set (0.01 sec)

 

mysql> show global variables like '%cache%';

+------------------------------+----------------------+

| Variable_name                | Value                |

+------------------------------+----------------------+

| binlog_cache_size            | 1048576              |

| have_query_cache             | YES                  |

| key_cache_age_threshold      | 300                  |

| key_cache_block_size         | 1024                 |

| key_cache_division_limit     | 100                  |

| max_binlog_cache_size        | 18446744073709547520 |

| query_cache_limit            | 1048576              |

| query_cache_min_res_unit     | 4096                 |

| query_cache_size             | 0                    |

| query_cache_type             | ON                   |

| query_cache_wlock_invalidate | OFF                  |

| table_definition_cache       | 256                  |

| table_open_cache             | 100                  |

| thread_cache_size            | 100                  |

+------------------------------+----------------------+

14 rows in set (0.00 sec)

内存的组成:1.线程共享内存  2.线程独享内存

used_Mem =

+ key_buffer_size

+ query_cache_size

+ innodb_buffer_pool_size

+ innodb_additional_mem_pool_size

+ innodb_log_buffer_size

+ max_connections *(

    +read_buffer_size

    +read_rnd_buffer_size

    +sort_buffer_size

    +join_buffer_size

    +binlog_cache_size

    + thread_stack

    +tmp_table_size

    +bulk_insert_buffer_size

)

线程独享内存

1.read_buffer_size 顺序读取数据缓冲区使用内存

这部分内存主要用于当需要顺序读取数据的时候,如无发使用索引的情况下的全表扫描,全索引扫描等。在这种时候,MySQL 按照数据的存储顺序依次读取数据块,每次读取的数据快首先会暂存在read_buffer_size中,当 buffer 空间被写满或者全部数据读取结束后,再将buffer中的数据返回给上层调用者,以提高效率。

2.read_rnd_buffer_size:随机读取数据缓冲区使用内存

和顺序读取相对应,当 MySQL 进行非顺序读取(随机读取)数据块的时候,会利用这个缓冲区暂存读取的数据。如根据索引信息读取表数据,根据排序后的结果集与表进行Join等等。总的来说,就是当数据块的读取需要满足一定的顺序的情况下,MySQL 就需要产生随机读取,进而使用到 read_rnd_buffer_size 参数所设置的内存缓冲区。

3.sort_buffer_size:排序使用内存

MySQL 用此内存区域进行排序操作(filesort),完成客户端的排序请求。当我们设置的排序区缓存大小无法满足排序实际所需内存的时候,MySQL 会将数据写入磁盘文件来完成排序。由于磁盘和内存的读写性能完全不在一个数量级,所以sort_buffer_size参数对排序操作的性能影响绝对不可小视

4.join_buffer_size:连接使用内存

应用程序经常会出现一些两表(或多表)Join的操作需求,MySQL在完成某些 Join 需求的时候(all/index join),为了减少参与Join的“被驱动表”的读取次数以提高性能,需要使用到 Join Buffer 来协助完成 Join操作。 Join Buffer 太小,MySQL 不会将该 Buffer 存入磁盘文件,而是先将Join Buffer中的结果集与需要 Join 的表进行 Join 操作,然后清空 Join Buffer 中的数据,继续将剩余的结果集写入此 Buffer 中,如此往复。这势必会造成被驱动表需要被多次读取,成倍增加 IO 访问,降低效率。

5.thread_stack:线程栈信息使用内存

主要用来存放每一个线程自身的标识信息,如线程id,线程运行时基本信息等等,我们可以通过 thread_stack 参数来设置为每一个线程栈分配多大的内存

6.tmp_table_size:临时表使用内存

当我们进行一些特殊操作如需要使用临时表才能完成的Order ByGroup By 等等,MySQL 可能需要使用到临时表。当我们的临时表较小(小于 tmp_table_size 参数所设置的大小)的时候,MySQL 会将临时表创建成内存临时表,只有当 tmp_table_size 所设置的大小无法装下整个临时表的时候,MySQL 才会将该表创建成 MyISAM 存储引擎的表存放在磁盘上。不过,当另一个系统参数 max_heap_table_size 的大小还小于 tmp_table_size 的时候,MySQL 将使用 max_heap_table_size 参数所设置大小作为最大的内存临时表大小,而忽略 tmp_table_size 所设置的值。而且 tmp_table_size 参数从 MySQL 5.1.2 才开始有,之前一直使用 max_heap_table_size

7.bulk_insert_buffer_size:批量插入暂存使用内存

当我们使用如 insert values(),(),() 的方式进行批量插入的时候,MySQL 会先将提交的数据放如一个缓存空间中,当该缓存空间被写满或者提交完所有数据之后,MySQL 才会一次性将该缓存空间中的数据写入数据库并清空缓存。此外,当我们进行 LOAD DATAINFILE 操作来将文本文件中的数据 Load 进数据库的时候,同样会使用到此缓冲区 

8.binlog_cache_size:二进制日志缓冲使用内存

我们知道InnoDB存储引擎是支持事务的,实现事务需要依赖于日志技术,为了性能,日志编码采用二进制格式。那么,我们如何记日志呢?有日志的时候,就 直接写磁盘?可是磁盘的效率是很低的,如果你用过Nginx,一般Nginx输出access log都是要缓冲输出的。因此,记录二进制日志的时候,我们是否也需要考虑Cache呢?答案是肯定的,但是Cache不是直接持久化,于是面临安全性的 问题——因为系统宕机时,Cache中可能有残余的数据没来得及写入磁盘。因此,Cache要权衡,要恰到好处:既减少磁盘I/O,满足性能要求;又保证 Cache无残留,及时持久化,满足安全要求。

设置太大的话,会比较消耗内存资源;设置太小的话,如果用户提交一个“长事务(long_transaction)”,比如:批量导入数据。那么该事务必然会产生很多binlog,这样 cache可能不够用(默认binlog_cache_size32K),不够用的时候mysql会把uncommitted的部分写入临时文件(临时文件cache的效率必然没有内存cache高),等到committed的时候才会写入正式的持久化日志文件。

 

线程共享内存

1.query_cache_size:查询缓存

查询缓存是 MySQL 比较独特的一个缓存区域,用来缓存特定 Query 的结果集(Result Set)信息,共享给所有客户端。

通过对 Query 语句进行特定的 Hash 计算之后与结果集对应存放在 Query Cache 中,以提高完全相同的 Query 语句的相应速度。

当我们打开 MySQL Query Cache 之后,MySQL 接收到每一个 SELECT 类型的 Query 之后都会首先通过固定的 Hash 算法得到该 Query Hash 值,然后到 Query Cache 中查找是否有对应的 Query Cache。如果有,则直接将 Cache 的结果集返回给客户端。如果没有,再进行后续操作,得到对应的结果集之后将该结果集缓存到 Query Cache 中,再返回给客户端。

当任何一个表的数据发生任何变化之后,与该表相关的所有 Query Cache 全部会失效,所以 Query Cache 对变更比较频繁的表并不是非常适用,但对那些变更较少的表是非常合适的,可以极大程度的提高查询效率,如那些静态资源表,配置表等等。为了尽可能高效的利 Query CacheMySQL 针对 Query Cache 设计了多个 query_cache_type 值和两个 Query HintSQL_CACHE SQL_NO_CACHE

a、当query_cache_type 设置为0(或者 OFF)的时候 不使用 Query Cache

b、当query_cache_type设置为1(或者 ON)的时候,当且仅当 Query 中使用了 SQL_NO_CACHE 的时候 MySQL 会忽略 Query Cache

cquery_cache_type 设置为2(或者DEMAND)的时候,当且仅当Query 中使用了 SQL_CACHE 提示之后,MySQL 才会针对该 Query 使用 Query Cache

可以通过 query_cache_size 来设置可以使用的最大内存空间。

2.binlog_cache_size:二进制日志缓冲区

二进制日志缓冲区主要用来缓存由于各种数据变更操做所产生的 Binary Log 信息。

为了提高系统的性能,MySQL 并不是每次都是将二进制日志直接写入 Log File,而是先将信息写入 Binlog Buffer 中,当满足某些特定的条件(如 sync_binlog参数设置)之后再一次写入 Log File 中。我们可以通过 binlog_cache_size 来设置其可以使用的内存大小,同时通过 max_binlog_cache_size 限制其最大大小(当单个事务过大的时候 MySQL 会申请更多的内存)。当所需内存大于 max_binlog_cache_size 参数设置的时候,MySQL 会报错:“Multi-statement transaction required more than max_binlog_cache_size bytes of storage”。

3.key_buffer_sizeMyISAM索引缓存

The key_buffer_size indicates the size of the key cachethat MySQL uses to store indexes in memory. The cache stores index blocks inmemory to avoid reading the disk repeatedly. The key_buffer_size is one of themost important variables to tune to improve MySQL database performance. The indexblocks of MyISAM tables are stored in the key cache and are accessible to allprocesses which use MySQL globally.

The maximum size of the key_buffer_size variable is 4 GBon 32 bit machines, and larger for 64 bit machines. MySQL recommends that youkeep the key_buffer_size less than or equal to 25% of the RAM on your machine.This also depends on the other processes that use memory on the machine and itis wise to check if you consistently have 25% of free memory using the Linuxcommand free. More on this later.

4.innodb_log_buffer_sizeInnoDB 日志缓冲区

这是 InnoDB 存储引擎的事务日志所使用的缓冲区。类似于 Binlog BufferInnoDB 在写事务日志的时候,为了提高性能,也是先将信息写入 Innofb Log Buffer 中,当满足 innodb_flush_log_trx_commit 参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件(或者同步到磁盘)中。可以通过 innodb_log_buffer_size 参数设置其可以使用的最大内存空间。 

5.innodb_buffer_pool_sizeInnoDB 数据和索引缓存

InnoDB Buffer Pool InnoDB 存储引擎的作用类似于 Key Buffer Cache MyISAM 存储引擎的影响,主要的不同在于 InnoDB Buffer Pool 不仅仅缓存索引数据,还会缓存表的数据,而且完全按照数据文件中的数据快结构信息来缓存,这一点和 Oracle SGA 中的 database buffer cache 非常类似。所以,InnoDB Buffer Pool InnoDB 存储引擎的性能影响之大就可想而知了。可以通过 (Innodb_buffer_pool_read_requests Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100%计算得到 InnoDB Buffer Pool 的命中率。 

6.innodb_additional_mem_pool_sizeInnoDB 字典信息缓存

InnoDB 字典信息缓存主要用来存放 InnoDB 存储引擎的字典信息以及一些 internal 的共享数据结构信息。所以其大小也与系统中所使用的 InnoDB 存储引擎表的数量有较大关系。不过,如果我们通过 innodb_additional_mem_pool_size 参数所设置的内存大小不够,InnoDB 会自动申请更多的内存,并在 MySQL Error Log 中记录警告信息。

 


105:如何在 excel 中画基于横坐标和纵坐标的趋势图。

利用Excel的图表功能,可以通过某些状态值来观察MySQL数据库性能变化。(操作略)

 


106:描述一个select  语句的执行过程,看一下哪些参数影响这个 select 的执行过程。

1.客户端发送一条查询给服务器;(连接,线程相关的参数)

2.服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段;(缓存,刷新,读写相关的参数)

3.服务器段进行SQL解析、预处理,在优化器生成对应的执行计划;

4.mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。(锁、事务相关的参数)

5.将结果返回给客户端。

 


107:写线程为何影响读线程,如何来调整写线程,分别来解决两个问题:总体降低物理写、解决抖动问题。

1.总体降低物理写

      写线程会阻塞读线程,可以调整以下参数:

Innodb_lru_scan_depth 

Innodb_io_capacity

Innodb_max_dirty_pages_pct(90) 

innodb_buffer_pool_pages_flushed

innodb_buffer_pool_pages_dirty/innodb_buffer_pool_pages_data

innodb_buffer_pool_wait_free

2.解决抖动问题


每秒的增值变化大代表性能发生了抖动,这是由于线程高并发引起的,应该适当控制连接数,提高缓存大小。

 


108:日志写线程的工作状态,以及是否影响性能,相应的参数调整。

可以通过以下状态值观察日志写线程的工作状态,如果有等待挂起,代表写被阻塞,这时就会影响应能;具体的做法要根据实际的情况对日志缓冲和日志文件以及刷新机制进行调整,具体参数之前已经提过。

innodb_log_waits

log buffer不足导致等待的次数

innodb_log_writes

平均每秒向日志文件的物理写次数

innodb_os_log_written

平均每秒写入日志文件的字节数

innodb_os_log_fsyncs

平均每秒向日志文件完成的fsync()写数量

innodb_os_log_pending_writes

平均每秒写入日志文件的挂起数量

innodb_os_log_pending_fsyncs

平均每秒向日志文件挂起的fsync()写数量

innodb_log_write_requests

平均每秒日志写请求数

 


109:根据 SQL、事务的工作过程以及每一个过程消耗的资源,来描述如何通过调整参数来让数据库性能达到最佳。

 

不允许出现0时间

要求必须来开启事物,关闭必须commit才能执行

带时间戳的数据类型,带毫秒和时区

会自动填充时间就算不添加t1的数据

允许最大的列的大小16kvarchar后面的数值注意)

 


110:关闭 double write 来调整写性能。

innodb_doublewrite#来控制double write的开关

因为是两次写,所以开启的话会增加1倍的IO,在写性能要求很高的情况下,建议关闭。

详见17


文章转载自记忆乘凉,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论