本文由云+社区发表mysql
做者:工程师小熊sql
摘要:咱们在使用mariadb的时候发现有时候不能启动起来,在使用过程当中mariadb占用的内存很大,在这里学习下mariadb与内存相关的配置项,对mariadb进行调优。缓存
使用如下命令能够知道mysql的配置使用多少 RAM服务器
SELECT ( @@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
)
) / (1024 * 1024 * 1024) AS MAX_MEMORY_GB;
复制代码
可使用mysql计算器来计算内存使用数据结构
下面是理论,能够直接到推荐配置并发
指定索引缓冲区的大小,它决定索引处理的速度,尤为是索引读的速度。为了最小化磁盘的 I/O , MyISAM 存储引擎的表使用键高速缓存来缓存索引,这个键高速缓存的大小则经过 key-buffer-size 参数来设置。若是应用系统中使用的表以 MyISAM 存储引擎为主,则应该适当增长该参数的值,以便尽量的缓存索引,提升访问的速度。oracle
show global status like 'key_read%';
+------------------------+-------------+
| Variable_name | Value |
+------------------------+-------------+
| Key_read_requests | 27813678764 |
| Key_reads | 6798830 |
---------------------
复制代码
show global status like '%created_tmp_disk_tables%';
复制代码
另外一个参考以下socket
show global status like 'key_blocks_u%';
+------------------------+-------------+
| Variable_name | Value |
+------------------------+-------------+
| Key_blocks_unused | 0 |
| Key_blocks_used | 413543 |
+------------------------+-------------+
复制代码
Key_blocks_unused表示未使用的缓存簇(blocks)数,Key_blocks_used表示曾经用到的最大的blocks数,好比这台服务器,全部的缓存都用到了,要么增长key_buffer_size,要么就是过渡索引了,把缓存占满了。比较理想的设置:性能
Key_blocks_used / (Key_blocks_unused + Key_blocks_used) * 100% ≈ 80%
show engines;
复制代码
这个参数和MyISAM的
key_buffer_size
有类似之处,但也是有差异的。这个参数主要缓存innodb表的索引,数据,插入数据时的缓冲。为Innodb加速优化首要参数。 学习
该参数分配内存的原则:这个参数默认分配只有8M,能够说是很是小的一个值。
缓存机制简单的说就是缓存sql文本及查询结果,若是运行相同的sql,服务器直接从缓存中取到结果,而不须要再去解析和执行sql。若是表更改了,那么使用这个表的全部缓冲查询将再也不有效,查询缓存值的相关条目被清空。更改指的是表中任何数据或是结构的改变,包括INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE等,也包括那些映射到改变了的表的使用MERGE表的查询。显然,这对于频繁更新的表,查询缓存是不适合的,而对于一些不常改变数据且有大量相同sql查询的表,查询缓存会节约很大的性能。
先设置成这样跑一段时间
query_cache_size=128M
query_cache_type=1
复制代码
看看命中结果来进行进一步的判断
mysql> show status like '%Qcache%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 669 |
| Qcache_free_memory | 132519160 |
| Qcache_hits | 1158 |
| Qcache_inserts | 284824 |
| Qcache_lowmem_prunes | 2741 |
| Qcache_not_cached | 1755767 |
| Qcache_queries_in_cache | 579 |
| Qcache_total_blocks | 1853 |
+-------------------------+-----------+
8 rows in set (0.00 sec)
复制代码
Qcache_free_blocks:表示查询缓存中目前还有多少剩余的blocks,若是该值显示较大,则说明查询缓存中的内存碎片过多了,可能在必定的时间进行整理。
Qcache_free_memory:查询缓存的内存大小,经过这个参数能够很清晰的知道当前系统的查询内存是否够用,是多了,仍是不够用,DBA能够根据实际状况作出调整。
Qcache_hits:表示有多少次命中缓存。咱们主要能够经过该值来验证咱们的查询缓存的效果。数字越大,缓存效果越理想。
Qcache_inserts: 表示多少次未命中而后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,执行查询处理后把结果insert到查询缓存中。这样的状况的次数,次数越多,表示查询缓存应用到的比较少,效果也就不理想。固然系统刚启动后,查询缓存是空的,这很正常。
Qcache_lowmem_prunes:该参数记录有多少条查询由于内存不足而被移除出查询缓存。经过这个值,用户能够适当的调整缓存大小。
Qcache_not_cached: 表示由于query_cache_type的设置而没有被缓存的查询数量。
Qcache_queries_in_cache:当前缓存中缓存的查询数量。
Qcache_total_blocks:当前缓存的block数量。
InnoDB 字典信息缓存主要用来存放 InnoDB 存储引擎的字典信息以及一些 internal 的共享数据结构信息,也就是存放Innodb的内部目录,因此其大小也与系统中所使用的 InnoDB 存储引擎表的数量有较大关系。
这个值不用分配太大,一般设置16M够用了,默认8M,若是设置的内存大小不够,InnoDB 会自动申请更多的内存,并在 MySQL 的 Error Log 中记录警告信息。
表示InnoDB写入到磁盘上的日志文件时使用的缓冲区的字节数,默认值为16M。一个大的日志缓冲区容许大量的事务在提交以前不用写日志到磁盘,因此若是有更新,插入或删除许多行的事务,则使日志缓冲区更大一些能够节省磁盘IO
一般最大设为64M足够
MySQL的max_connections参数用来设置最大链接(用户)数。每一个链接MySQL的用户均算做一个链接,max_connections的默认值为100。
mysql> show variables like '%max_connect%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| extra_max_connections | 1 |
| max_connect_errors | 100 |
| max_connections | 2048 |
+-----------------------+-------+
3 rows in set (0.00 sec)
mysql> show status like 'Threads%';
+-------------------+---------+
| Variable_name | Value |
+-------------------+---------+
| Threads_cached | 0 |
| Threads_connected | 1 |
| Threads_created | 9626717 |
| Threads_running | 1 |
+-------------------+---------+
4 rows in set (0.00 sec)
复制代码
能够看到此时的并发数也就是Threads_connected=1,还远远达不到2048
mysql> show variables like 'open_files_limit';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| open_files_limit | 65535 |
+------------------+-------+
1 row in set (0.00 sec)
复制代码
max_connections 还取决于操做系统对单进程容许打开最大文件数的限制
也就是说若是操做系统限制单个进程最大能够打开100个文件
那么 max_connections 设置为200也没什么用
MySQL 的 open_files_limit 参数值是在MySQL启动时记录的操做系统对单进程打开最大文件数限制的值
可使用 show variables like 'open_files_limit'; 查看 open_files_limit 值
ulimit -n
65535
复制代码
或者直接在 Linux 下经过ulimit -n命令查看操做系统对单进程打开最大文件数限制 ( 默认为1024 )
connection级参数,是在每一个connection第一次须要使用这个buffer的时候,一次性分配设置的内存。
mysql对于排序,使用了两个变量来控制sort_buffer_size和 max_length_for_sort_data, 不象oracle使用SGA控制. 这种方式的缺点是要单独控制,容易出现排序性能问题.
mysql> SHOW GLOBAL STATUS like '%sort%';
+---------------------------+--------+
| Variable_name | Value |
+---------------------------+--------+
| Sort_merge_passes | 0 |
| Sort_priority_queue_sorts | 1409 |
| Sort_range | 0 |
| Sort_rows | 843479 |
| Sort_scan | 13053 |
+---------------------------+--------+
5 rows in set (0.00 sec)
复制代码
Sort_merge_passes
的值比较大,你能够考虑增长sort_buffer_size
来加速ORDER BY 或者GROUP BY 操做,不能经过查询或者索引优化的。咱们这为0,那就不必设置那么大。read_buffer_size = 128K(默认128K)为须要全表扫描的MYISAM数据表线程指定缓存
read_rnd_buffer_size = 4M:(默认256K)首先,该变量能够被任何存储引擎使用,当从一个已经排序的键值表中读取行时,会先从该缓冲区中获取而再也不从磁盘上获取。
mysql> show global status like 'binlog_cache%';
+-----------------------+----------+
| Variable_name | Value |
+-----------------------+----------+
| Binlog_cache_disk_use | 220840 |
| Binlog_cache_use | 67604667 |
+-----------------------+----------+
2 rows in set (0.00 sec)
复制代码
若是应用中,不多出现join语句,则能够不用太在意join_buffer_size参数的设置大小。
若是join语句不是不多的话,我的建议能够适当增大join_buffer_size到1MB左右,若是内存充足能够设置为2MB。
Thread_stack:每一个链接线程被建立时,MySQL给它分配的内存大小。当MySQL建立一个新的链接线程时,须要给它分配必定大小的内存堆栈空间,以便存放客户端的请求的Query及自身的各类状态和处理信息。
mysql> show status like '%threads%';
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Delayed_insert_threads | 0 |
| Slow_launch_threads | 0 |
| Threadpool_idle_threads | 0 |
| Threadpool_threads | 0 |
| Threads_cached | 0 |
| Threads_connected | 1 |
| Threads_created | 9649301 |
| Threads_running | 1 |
+-------------------------+---------+
8 rows in set (0.00 sec)
mysql> show status like 'connections';
+---------------+---------+
| Variable_name | Value |
+---------------+---------+
| Connections | 9649311 |
+---------------+---------+
1 row in set (0.00 sec)
复制代码
如上:系统启动到如今共接受到客户端的链接9649311次,共建立了9649301个链接线程,当前有1个链接线程处于和客户端链接的状态。而在Thread Cache池中共缓存了0个链接线程(Threads_cached)。
Thread Cache 命中率:
Thread_Cache_Hit = (Connections - Threads_created) / Connections * 100%;
复制代码
通常在系统稳定运行一段时间后,Thread Cache命中率应该保持在90%左右才算正常。
tmp_table_size 控制内存临时表的最大值,超过限值后就往硬盘写,写的位置由变量 tmpdir 决定
max_heap_table_size 用户能够建立的内存表(memory table)的大小.这个值用来计算内存表的最大行数值。
Order By 或者Group By操做多的话,加大这两个值,默认16M
mysql> show status like 'Created_tmp_%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 0 |
| Created_tmp_files | 626 |
| Created_tmp_tables | 3 |
+-------------------------+-------+
3 rows in set (0.00 sec)
复制代码
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
default-storage-engine=INNODB
character-set-server=utf8
collation-server=utf8_general_ci
user=mysql
symbolic-links=0
# global settings
table_cache=65535
table_definition_cache=65535
max_allowed_packet=4M
net_buffer_length=1M
bulk_insert_buffer_size=16M
query_cache_type=0 #是否使用查询缓冲,0关闭
query_cache_size=0 #0关闭,由于改表操做多,命中低,开启消耗cpu
# shared
key_buffer_size=8M #保持8M MyISAM索引用
innodb_buffer_pool_size=4G #DB专用mem*50%,非DB专用mem*15%到25%
myisam_sort_buffer_size=32M
max_heap_table_size=16M #最大中间表大小
tmp_table_size=16M #中间表大小
# per-thread
sort_buffer_size=256K #加速排序缓存大小
read_buffer_size=128k #为须要全表扫描的MYISAM数据表线程指定缓存
read_rnd_buffer_size=4M #已排序的表读取时缓存,若是比较大内存就到6M
join_buffer_size=1M #join语句多时加大,1-2M
thread_stack=256k #线程空间,256K or 512K
binlog_cache_size=64K #大事务binlog
# big-tables
innodb_file_per_table = 1
skip-external-locking
max_connections=2048 #最大链接数
skip-name-resolve
# slow_query_log
slow_query_log_file = /var/log/mysql-slow.log
long_query_time = 30
group_concat_max_len=65536
# according to tuning-primer.sh
thread_cache_size = 8
thread_concurrency = 16
# set variables
concurrent_insert=2
复制代码
使用如下命令来修改变量
set global {要改的key} = {值}; (当即生效重启后失效)
set @@{要改的key} = {值}; (当即生效重启后失效)
set @@global.{要改的key} = {值}; (当即生效重启后失效)
复制代码
试验
mysql> set @@global.innodb_buffer_pool_size=4294967296;
ERROR 1238 (HY000): Variable 'innodb_buffer_pool_size' is a read only variable
mysql> set @@global.thread_stack=262144;
ERROR 1238 (HY000): Variable 'thread_stack' is a read only variable
mysql> set @@global.binlog_cache_size=65536;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@join_buffer_size=1048576;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@read_rnd_buffer_size=4194304;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@sort_buffer_size=262144;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@read_buffer_size=131072;
Query OK, 0 rows affected (0.00 sec)
mysql> set global key_buffer_size=8388608;
Query OK, 0 rows affected (0.39 sec)
复制代码
innodb_buffer_pool_size
和thread_stack
报错了,他们只能改配置文件,在运行时是只读的。 如下直接复制使用set @@global.binlog_cache_size=65536;
set @@join_buffer_size=1048576;
set @@read_rnd_buffer_size=4194304;
set @@sort_buffer_size=262144;
set @@read_buffer_size=131072;
set global key_buffer_size=8388608;
复制代码
mysql 优化技巧心得一(key_buffer_size设置)
此文已由腾讯云+社区在各渠道发布
获取更多新鲜技术干货,能够关注咱们腾讯云技术社区-云加社区官方号及知乎机构号