Linux学习-MySQL-week04

MySQL存储引擎及参数优化

  1. 简介
    MySQL 存储引擎是一种插件式的模式存在。类似于Linux 文件系统。组织和存储数据。

  2. 类型
    mysql> show engines;
    +--------------------+
    | Engine |
    +--------------------+
    | MRG_MYISAM |
    | CSV |
    | MyISAM |
    | BLACKHOLE |
    | PERFORMANCE_SCHEMA |
    | InnoDB |
    | ARCHIVE |
    | MEMORY |
    | FEDERATED |
    +--------------------+
    MySQL 5.5 之前,使用MyISAM引擎作为模式引擎。用户数据、系统表数据都是在MyISAM。
    MySQL 5.5 版本,将InnoDB引擎作为默认的存储引擎。存储用户表数据,系统相关表有部分是MyISAM

数据组织方式:
MyISAM: user.frm user.MYD user.MYI
InnoDB: city.ibd city.frm

其他种类:
Tokudb引擎: Percona MairaDB 默认支持的。
insert性能高、压缩比都比较高。

应用场景:
2000+ 监控系统 MariaDB 5.5 +Zabbix ---> tokudb (Percona 5.7,Mariadb 10.x)
历史数据、归档数据。

Tokudb特性:
Additional features unique to TokuDB include:
Up to 25x Data Compression
Fast Inserts
Eliminates Slave Lag with Read Free Replication
Hot Schema Changes
Hot Index Creation - TokuDB tables support insertions, deletions and queries with no down time while indexes are being added to that table
Hot column addition, deletion, expansion, and rename - TokuDB tables support insertions, deletions and queries without down-time when an alter table adds, deletes, expands, or renames columns
On-line Backup

参考内容:
https://www.jianshu.com/p/898d2e4bd3a7
https://mariadb.com/kb/en/installing-tokudb/
https://www.percona.com/doc/percona-server/5.7/tokudb/tokudb_installation.html

  1. InnoDB存储引擎的核心特性
    InnoDB支持事务,MyISAM不支持
    InnoDB支持行锁,MyISAM表锁
    InnoDB支持MVCC。
    InnoDB支持聚簇索引。
    InnoDB热备份。
    InnoDB支持自动故障恢复。
    InnoDB DoubleWrite buffer 双写机制。
    InnoDB多缓冲区支持(IBP\ILB\AHI\CHB)。
    主从中的高级特性。
  1. InnoDB 体系结构
    https://dev.mysql.com/doc/refman/5.7/en/innodb-architecture.html

4.1 On-disk
4.1.1 表空间(TableSpace)

1. System tablespace (共享表空间、系统表空间)

存储方式:
数据路径下:ibdataN
存储内容:
5.5 版本: 系统数据(全局数据字典、DWB(2M)、change buffer 、UNDO回滚日志信息、临时表)、用户数据(数据行和索引)
5.6 版本: 只存储系统数据(全局数据字典、DWB(2M)、change buffer 、UNDO回滚日志信息、临时表),用户数据独立
5.7 版本: 在5.6基础上,默认将临时表独立,也可以手工将undo独立 ,只存储系统数据(全局数据字典、DWB(2M)、change buffer )
8.0.20之前:数据字典取消。只剩(DWB(2M)、change buffer )
8.0.20之后:只剩change buffer
管理:
(1)初始化时设置共享表空间:
mysql> select @@innodb_data_file_path;
+---------------------------------------------------+
| @@innodb_data_file_path |
+---------------------------------------------------+
| ibdata1:100M;ibdata2:100M;ibdata3:100M:autoextend |
+---------------------------------------------------+

vim /etc/my.cnf
innodb_data_file_path=ibdata1:50M;ibdata2:50M;ibdata3:50M:autoextend

生产建议: 512M-1G 2-3个

重新初始化数据,生效。

(2)后设置
例如:
采用了模式值: innodb_data_file_path=ibdata1:12M:autoextend
扩容注意:
innodb_data_file_path=ibdata1:实际大小M;ibdata2:50M;ibdata3:50M:autoextend

2. File-Per-Table Tablespaces(独立表空间)

介绍

在5.6之后,默认用来存储用户数据。
存储方式:
city.ibd --->
段 : 一张表就是一个段。由1-N区组成
区(簇) : 连续64个页,默认大小是1M。保证数据连续存储。
页 (page) : 默认16KB,连续4个OS Block。
配置:
mysql> select @@innodb_file_per_table;
+-------------------------+
| @@innodb_file_per_table |
+-------------------------+
| 1 |
+-------------------------+

表空间迁移

模拟:

3306

mysql> create table t1(id int)charset utf8mb4;
mysql> insert into t1 values(1),(2),(3);
mysql> commit;
mysql> lock table t1 read;

3307

mysql> use test;
mysql> create table t1(id int)charset utf8mb4;
mysql> alter table t1 discard tablespace;
[root@db01 test]# cp -a /data/3306/data/world/t1.ibd /data/3307/data/test/
mysql> alter table t1 import tablespace;

3. Undo Tablespaces

介绍: 用来存储回滚日志信息,撤销操作
存储方式:
undo001
undo002
undo003

结构:
128 回滚段 , 96个 undo表空间中,32个在ibtmpN中。
每个段1024 slot槽位。

管理:
5.7 默认存储在ibdata中,生产建议进行独立。

将undo独立设置:

注: undo独立只能初始化时进行设置。
++++++++++++++
Important
The number of undo tablespaces can only be configured when initializing a MySQL instance and is fixed for the life of the instance.
++++++++++++++

查看:
SELECT @@innodb_undo_tablespaces; ---->3-5个 #打开独立undo模式,并设置undo的个数。
SELECT @@innodb_max_undo_log_size; #undo日志的大小,默认1G。
SELECT @@innodb_undo_log_truncate; #开启undo自动回收的机制(undo_purge线程)。
SELECT @@innodb_purge_rseg_truncate_frequency; #触发自动回收的条件,单位是检测次数。

设定方法:
innodb_undo_tablespaces=3
innodb_max_undo_log_size=128M
innodb_undo_log_truncate=ON
innodb_purge_rseg_truncate_frequency=32

4. The Temporary Tablespace 临时表空间

innodb_temp_data_file_path=ibtmp1:12M;ibtmp2:128M:autoextend:max:500M

4.1.2 事务日志

1. redo 重做日志

作用: 记录内存数据页的变化。提供“前进”功能。
存储方式:
ib_logfileN ,轮序使用方式。

管理:
mysql> show variables like '%innodb_log_file%';
+---------------------------+----------+
| Variable_name | Value |
+---------------------------+----------+
| innodb_log_file_size | 50331648 |
| innodb_log_files_in_group | 2 |
+---------------------------+----------+
生产建议: 1-4G , 2-3个

vim /etc/my.cnf
innodb_log_file_size=100M
innodb_log_files_in_group=3

重启生效。

undo

4.1.3 其他结构

ib_buffer_pool 预热文件

保存热点数据。重启起到预热功能。

4.1 In-Memory

4.1.1 Buffer Pool
作用 : 缓冲区池,全局共享内存区域。缓冲数据页和索引。
管理:
生产建议:物理内存的50-80%
mysql> select @@innodb_buffer_pool_size;
mysql> set global innodb_buffer_pool_size=512M;

4.1.2 log buffer
查询:
mysql> select @@innodb_log_buffer_size;
默认大小:16M
生产建议:和innodb_log_file_size有关,1-N倍
设置方式 :
vim /etc/my.cnf
innodb_log_buffer_size=33554432
重启生效:
[root@db01 data]# /etc/init.d/mysqld restart

4.1.3 AHI 自适应的HASH索引
作用: 内存hash表,缓冲buffer pool中热点的索引页。索引的索引。

4.1.4 CHB change buffer
作用: 索引一种自优化能力。发生数据修改时,索引结构不会立即更改,将索引的变化临时放到CHB。需要使用数据时,在内存中进行自动merge.

  1. InnoDB中的事务支持
    5.1 介绍
    Transaction : 交易。事务功能就是在MySQL中发生交易业务时的“和谐”

5.2 事务的ACID特性
A : 原子性:
同一个事务中的所有操作,作为一个整体完成,要么全成功要么全失败。
C : 一致性
不管宕机与否,事务操作的数据,最终保持一致。

I : 隔离性
事务工作期间不互相影响。

D : 持久性
一旦事务完成(提交),一定保证事务操作的数据落地。

5.3 事务生命周期管理

5.3.1 标准的事务控制语句
begin; # 开启事务
commit; # 提交事务
rollback; # 回滚事务

mysql> begin;
mysql> select * from t1;
mysql> update t1 set id=10 where id=1;
mysql> rollback;
mysql> select * from t1;
mysql> begin;
mysql> update t1 set id=10 where id=1;
mysql> commit;

mysql> select * from t1;
+------+
| id |
+------+
| 10 |
| 2 |
| 3 |
+------+
mysql> rollback;
mysql> select * from t1;
+------+
| id |
+------+
| 10 |
| 2 |
| 3 |
+------+

5.3.2 自动提交机制
mysql> select @@autocommit;
触发条件: 当我们没有显示触发begin操作。发生任何DML语句时,逐条提交。
mysql> set global autocommit=0;

5.3.3 隐式提交
begin
a
b
begin

SET AUTOCOMMIT = 1
导致提交的非事务语句:
DDL语句: (ALTER、CREATE 和 DROP)
DCL语句: (GRANT、REVOKE 和 SET PASSWORD)
锁定语句:(LOCK TABLES 和 UNLOCK TABLES)
导致隐式提交的语句示例:
TRUNCATE TABLE
LOAD DATA INFILE
SELECT FOR UPDATE

5.3.4 隐式回滚
会话窗口被关闭。
数据库关闭 。
出现事务冲突(死锁)。

  1. 事务ACID特性是如何保证的?
    6.0 专业名词介绍
    6.0.1 数据部分

表空间 :

独立表空间 :t1.ibd ---> 段 ----> 区 ----> page(16KB)

buffer pool :

缓冲数据页的内存区域。

6.0.2 日志部分

redo : 记录buffer pool中数据页变化日志

## redo log :ib_logfileN
## redo log buffer: 缓冲redolog

undo

undo00N

6.0.3 LSN 日志序列号(版本号)
生成方式:根据日志生成的字节量,进行增长号码。
LSN类型:
磁盘数据页的LSN: Checkpoint LSN , 数据页陆地时的LSN
redo buffer LSN: current LSN , 当前最新的LSN
redo 日志 LSN: redo flush LSN ,落地到redo log LSN
6.0.4 脏页 Dirty Page
buffer pool中被修改过的数据页。

6.05 Checkpoint 检查点
将buffer pool中数据页刷写到表空间的操作。

6.0.6 事务ID : DB_TRX_ID 6字节 。
存在于脏数据页头部。当前事务ID。

6.0.7 回滚指针: DB_ROLL_PTR 7字节
存在于脏数据页头部。用来找undo回滚信息的。

6.1 redo log
主要实现:
ACID中的D特性。对A和C也有相应的保证。
redo是量级比数据页要小。
redo是连续的磁盘空间。数据页是离散分布的。
持久化时,将redo buffer 中日志落地磁盘。
redo log在CR中提供前滚的功能。
宕机恢复时,InnoDB对比数据页LSN=1000和redolog中的LSN=1100.
1000-1100

6.2 undo log
主要实现:
ACID中的A的特性。对于C和I相应的保证。
记录的是逻辑日志,事务的逆操作。

6.3 自动故障恢复和DWB ---》
在ACID中,主要保证C的特性。
ACR : REDO和UNDO共同保证。先redo前滚,构造脏页,再恢复通过undo未提交事务回滚。
DWB : DoubleWrite buffer 双写机制。在数据页出现部分写入时 ,通过DWB恢复坏的数据页。

6.4 ACID中的隔离性保证
6.4.1 隔离级别
作用: 实现“读”的隔离
RU : 读未提交。
隔离性差,会出现的问题: 脏读、不可重复读、幻读。
RC :读已提交。
隔离性一般,会出现的问题: 不可重复读、幻读。
RR :可重复读。
隔离性良好,有可能出现:幻读*,配合GAP和next lock防止幻读问题。
SE :可串行化。
隔离性最好。事务串行工作。

6.4.2 事务锁机制
作用:提供“写”隔离。
row lock:
record lock : 所有隔离级别。针对聚簇索引加锁。
GAP LoCK :RR级别。针对辅助索引范围加锁。
Next Lock :RR级别。Record+GAP。范围加锁。

6.4.3 MVCC 多版本并发控制
介绍: 通过 undo快照技术。
功能: 利用了乐观锁的机制。非锁定读取。提高了事务的并发程度。

  1. 其他参数优化细节
    7.1 Max_connections *****

(1)简介
Mysql的最大连接数,如果服务器的并发请求量比较大,可以调高这个值,当然这是要建立在机器能够支撑的情况下,因为如果连接数越来越多,mysql会为每个连接提供缓冲区,就会开销的越多的内存,所以需要适当的调整该值,不能随便去提高设值。
(2)判断依据
show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
show status like 'Max_used_connections';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| Max_used_connections | 101 |
+----------------------+-------+

(3)修改方式举例
vim /etc/my.cnf
max_connections=1024

案例1:
连接数设置不生效的问题,214问题。
/etc/security/limits.conf
*  soft  nofile  65536
*  hard  nofile  65536

5.2 back_log ***
(1)简介
mysql能暂存的连接数量,当主要mysql线程在一个很短时间内得到非常多的连接请求时候它就会起作用,如果mysql的连接数据达到max_connections时候,新来的请求将会被存在堆栈中,等待某一连接释放资源,该推栈的数量及back_log,如果等待连接的数量超过back_log,将不被授予连接资源。
back_log值指出在mysql暂时停止回答新请求之前的短时间内有多少个请求可以被存在推栈中,只有如果期望在一个短时间内有很多连接的时候需要增加它
(2)判断依据
show full processlist
发现大量的待连接进程时,就需要加大back_log或者加大max_connections的值
(3)修改方式举例
vim /etc/my.cnf
back_log=1024

5.3 wait_timeout和interactive_timeout *****
(1)简介
wait_timeout:指的是mysql在关闭一个非交互的连接之前所要等待的秒数
interactive_timeout:指的是mysql在关闭一个交互的连接之前所需要等待的秒数,比如我们在终端上进行mysql管理,使用的即使交互的连接,这时候,如果没有操作的时间超过了interactive_time设置的时间就会自动的断开,默认的是28800,可调优为7200。
wait_timeout:如果设置太小,那么连接关闭的就很快,从而使一些持久的连接不起作用
(2)设置建议
如果设置太大,容易造成连接打开时间过长,在show processlist时候,能看到很多的连接 ,一般希望wait_timeout尽可能低
(3)修改方式举例
wait_timeout=120
interactive_timeout=7200

长连接的应用,为了不去反复的回收和分配资源,降低额外的开销。
一般我们会将wait_timeout设定比较小,interactive_timeout要和应用开发人员沟通长链接的应用是否很多。如果他需要长链接,那么这个值可以不需要调整。
另外还可以使用类外的参数弥补。

案例2:MySQL 连接长时间(7200和1200秒)无法释放
场景: MySQL 5.7 , DELL730 E5-2650 96G内存 1主2从
Keepalive + LVS + 1主 2从

处理方法:
ipvsadmin -l -timeout
Timeout (tcp tcpfin udp ): 90 120 300
net.ipv4.tcp_keepalive_time = 60

5.4 key_buffer_size *****
(1)简介
key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度
《1》此参数与myisam表的索引有关
《2》临时表的创建有关(多表链接、子查询中、union)
在有以上查询语句出现的时候,需要创建临时表,用完之后会被丢弃
临时表有两种创建方式:
内存中------->key_buffer_size
磁盘上------->ibdata1(5.6)
ibtmp1 (5.7)

注:key_buffer_size只对myisam表起作用,即使不使用myisam表,但是内部的临时磁盘表是myisam表,也要使用该值。
可以使用检查状态值created_tmp_disk_tables得知:

mysql> show status like "created_tmp%";
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 0 |
| Created_tmp_files | 6 |
| Created_tmp_tables | 1 |
+-------------------------+-------+
3 rows in set (0.00 sec)

mysql>
通常地,我们习惯以
Created_tmp_tables/(Created_tmp_disk_tables + Created_tmp_tables)
Created_tmp_disk_tables/(Created_tmp_disk_tables + Created_tmp_tables)

或者已各自的一个时段内的差额计算,来判断基于内存的临时表利用率。所以,我们会比较关注 Created_tmp_disk_tables 是否过多,从而认定当前服务器运行状况的优劣。
Created_tmp_disk_tables/(Created_tmp_disk_tables + Created_tmp_tables)
控制在5%-10%以内

看以下例子:
在调用mysqldump备份数据时,大概执行步骤如下:
180322 17:39:33 7 Connect root@localhost on
7 Query /*!40100 SET @@SQL_MODE='' /
7 Init DB guo
7 Query SHOW TABLES LIKE 'guo'
7 Query LOCK TABLES guo READ /
!32311 LOCAL /
7 Query SET OPTION SQL_QUOTE_SHOW_CREATE=1
7 Query show create table guo
7 Query show fields from guo
7 Query show table status like 'guo'
7 Query SELECT /
!40001 SQL_NO_CACHE */ * FROM guo
7 Query UNLOCK TABLES
7 Quit

其中,有一步是:show fields from guo。从slow query记录的执行计划中,可以知道它也产生了 Tmp_table_on_disk。
所以说,以上公式并不能真正反映到mysql里临时表的利用率,有些情况下产生的 Tmp_table_on_disk 我们完全不用担心,因此没必要过分关注 Created_tmp_disk_tables,但如果它的值大的离谱的话,那就好好查一下,你的服务器到底都在执行什么查询了。

(3)配置方法
key_buffer_size=64M

5.5 query_cache_size ***

(1)简介:
查询缓存简称QC,主要缓存SQL语句hash值+执行结果。
10条语句,经常做查询。

案例3 : 开QC ,导致性能降低。 QPS ,TPS降低。
没开起的时候。QPS 2000 TPS 500
开了之后直接降低到 800,200

为什么呢?
分区表。Query Cache 不支持。
select * from city where id=10

5.6 sort_buffer_size ***
(1)简介:
每个需要进行排序的线程分配该大小的一个缓冲区。增加这值加速
ORDER BY
GROUP BY
distinct
union
(2)配置依据
Sort_Buffer_Size并不是越大越好,由于是connection级的参数,过大的设置+高并发可能会耗尽系统内存资源。
列如:500个连接将会消耗500*sort_buffer_size(2M)=1G内存

(3)配置方法
修改/etc/my.cnf文件,在[mysqld]下面添加如下:
sort_buffer_size=1M

建议: 尽量排序能够使用索引更好。

5.7 max_allowed_packet *****
(1)简介:
mysql根据配置文件会限制,server接受的数据包大小。
(2)配置依据:
有时候大的插入和更新会受max_allowed_packet参数限制,导致写入或者更新失败,更大值是1GB,必须设置1024的倍数
(3)配置方法:
max_allowed_packet=32M

案例: mysqldump备份报错,超出数据包大小。
mysqldump --max_allowed_packet=64M

5.8 join_buffer_size ***
select a.name,b.name from a join b on a.id=b.id where xxxx

用于表间关联缓存的大小,和sort_buffer_size一样,该参数对应的分配内存也是每个连接独享。
尽量在SQL与方面进行优化,效果较为明显。
优化的方法:在on条件列加索引,至少应当是有MUL索引

建议: 尽量能够使用索引优化更好。

5.9 thread_cache_size = 16 *****
(1)简介
服务器线程缓存,这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时,那么客户端的线程将被放到缓存中以响应下一个客户而不是销毁(前提是缓存数未达上限),如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能.

(2)配置依据
通过比较 Connections 和 Threads_created 状态的变量,可以看到这个变量的作用。
设置规则如下:1GB 内存配置为8,2GB配置为16,3GB配置为32,4GB或更高内存,可配置更大。
服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)

试图连接到MySQL(不管是否连接成功)的连接数
mysql> show status like 'threads_%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 8 |
| Threads_connected | 2 |
| Threads_created | 4783 |
| Threads_running | 1 |
+-------------------+-------+
4 rows in set (0.00 sec)

Threads_cached :代表当前此时此刻线程缓存中有多少空闲线程。
Threads_connected:代表当前已建立连接的数量,因为一个连接就需要一个线程,所以也可以看成当前被使用的线程数。
Threads_created:代表从最近一次服务启动,已创建线程的数量,如果发现Threads_created值过大的话,表明MySQL服务器一直在创建线程,这也是比较耗cpu SYS资源,可以适当增加配置文件中thread_cache_size值。
Threads_running :代表当前激活的(非睡眠状态)线程数。并不是代表正在使用的线程数,有时候连接已建立,但是连接处于sleep状态。

(3)配置方法:
thread_cache_size=32

整理:
Threads_created :一般在架构设计阶段,会设置一个测试值,做压力测试。
结合zabbix监控,看一段时间内此状态的变化。
如果在一段时间内,Threads_created趋于平稳,说明对应参数设定是OK。
如果一直陡峭的增长,或者出现大量峰值,那么继续增加此值的大小,在系统资源够用的情况下(内存)

5.10 innodb_buffer_pool_size *****
(1)简介
对于InnoDB表来说,innodb_buffer_pool_size的作用就相当于key_buffer_size对于MyISAM表的作用一样。
(2)配置依据:
InnoDB使用该参数指定大小的内存来缓冲数据和索引。
对于单独的MySQL数据库服务器,最大可以把该值设置成物理内存的80%,一般我们建议不要超过物理内存的70%。
(3)配置方法
innodb_buffer_pool_size=2048M

5.11 innodb_flush_log_at_trx_commit ******
(1)简介
主要控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为0、1、2三个。
0,表示当事务提交时,不做日志写入操作,而是每秒钟将log buffer中的数据写入日志文件并flush磁盘一次;
1,
每次事务的提交都会引起redo日志文件写入、flush磁盘的操作,确保了事务的ACID;
2,每次事务提交引起写入日志文件的动作,但每秒钟完成一次flush磁盘操作。

(2)配置依据
实际测试发现,该值对插入数据的速度影响非常大,设置为2时插入10000条记录只需要2秒,设置为0时只需要1秒,而设置为1时则需要229秒。因此,MySQL手册也建议尽量将插入操作合并成一个事务,这样可以大幅提高速度。
根据MySQL官方文档,在允许丢失最近部分事务的危险的前提下,可以把该值设为0或2。
(3)配置方法
innodb_flush_log_at_trx_commit=1
双1标准中的一个1

5.12 innodb_thread_concurrency ***
(1)简介
此参数用来设置innodb线程的并发数量,默认值为0表示不限制。
(2)配置依据
在官方doc上,对于innodb_thread_concurrency的使用,也给出了一些建议,如下:
如果一个工作负载中,并发用户线程的数量小于64,建议设置innodb_thread_concurrency=0;
如果工作负载一直较为严重甚至偶尔达到顶峰,建议先设置innodb_thread_concurrency=128,
并通过不断的降低这个参数,96, 80, 64等等,直到发现能够提供最佳性能的线程数,
例如,假设系统通常有40到50个用户,但定期的数量增加至60,70,甚至200。你会发现,
性能在80个并发用户设置时表现稳定,如果高于这个数,性能反而下降。在这种情况下,
建议设置innodb_thread_concurrency参数为80,以避免影响性能。
如果你不希望InnoDB使用的虚拟CPU数量比用户线程使用的虚拟CPU更多(比如20个虚拟CPU),
建议通过设置innodb_thread_concurrency 参数为这个值(也可能更低,这取决于性能体现),
如果你的目标是将MySQL与其他应用隔离,你可以l考虑绑定mysqld进程到专有的虚拟CPU。
但是需 要注意的是,这种绑定,在myslqd进程一直不是很忙的情况下,可能会导致非最优的硬件使用率。在这种情况下,
你可能会设置mysqld进程绑定的虚拟 CPU,允许其他应用程序使用虚拟CPU的一部分或全部。
在某些情况下,最佳的innodb_thread_concurrency参数设置可以比虚拟CPU的数量小。
定期检测和分析系统,负载量、用户数或者工作环境的改变可能都需要对innodb_thread_concurrency参数的设置进行调整。

128 -----> top cpu

设置标准:
1、当前系统cpu使用情况,均不均匀
top

2、当前的连接数,有没有达到顶峰
show status like 'threads_%';
show processlist;

(3)配置方法:
innodb_thread_concurrency=8

方法:
1. 看top ,观察每个cpu的各自的负载情况
2. 发现不平均,先设置参数为cpu个数,然后不断增加(一倍)这个数值
3. 一直观察top状态,直到达到比较均匀时,说明已经到位了.

5.1.3 innodb_log_buffer_size
此参数确定些日志文件所用的内存大小,以M为单位。缓冲区更大能提高性能,对于较大的事务,可以增大缓存大小。
innodb_log_buffer_size=128M

设定依据:
1、大事务: 存储过程调用 CALL
2、多事务

5.14 innodb_log_file_size = 100M *****
设置 ib_logfile0 ib_logfile1
此参数确定数据日志文件的大小,以M为单位,更大的设置可以提高性能.
innodb_log_file_size = 100M
innodb_log_files_in_group = 3 *****

为提高性能,MySQL可以以循环方式将日志文件写到多个文件。推荐设置为3

read_buffer_size = 1M **
MySql读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql会为它分配一段内存缓冲区。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能。和 sort_buffer_size一样,该参数对应的分配内存也是每个连接独享

read_rnd_buffer_size = 1M **
MySql的随机读(查询操作)缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySql会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
注:顺序读是指根据索引的叶节点数据就能顺序地读取所需要的行数据。随机读是指一般需要根据辅助索引叶节点中的主键寻找实际行数据,而辅助索引和主键所在的数据段不同,因此访问方式是随机的。

bulk_insert_buffer_size = 8M **

change_buffer_size=8M

批量插入数据缓存大小,可以有效提高插入效率,默认为8M
tokuDB percona
myrocks
RocksDB
TiDB
MongoDB
HBASE

5.15 binary log *****
双1标准(基于安全的控制):
sync_binlog=1 什么时候刷新binlog到磁盘,每次事务commit
innodb_flush_log_at_trx_commit=1

5.16 安全参数 *****
Innodb_flush_method=(O_DIRECT, fsync)

1、fsync :
(1)在数据页需要持久化时,首先将数据写入OS buffer中,然后由os决定什么时候写入磁盘
(2)在redo buffuer需要持久化时,首先将数据写入OS buffer中,然后由os决定什么时候写入磁盘
但,如果innodb_flush_log_at_trx_commit=1的话,日志还是直接每次commit直接写入磁盘

2、 Innodb_flush_method=O_DIRECT
(1)在数据页需要持久化时,直接写入磁盘
(2)在redo buffuer需要持久化时,首先将数据写入OS buffer中,然后由os决定什么时候写入磁盘
但,如果innodb_flush_log_at_trx_commit=1的话,日志还是直接每次commit直接写入磁盘

最安全模式:
innodb_flush_log_at_trx_commit=1
innodb_flush_method=O_DIRECT

最高性能模式:
innodb_flush_log_at_trx_commit=0
innodb_flush_method=fsync

一般情况下,我们更偏向于安全。
“双一标准”
innodb_flush_log_at_trx_commit=1 ***************
sync_binlog=1 ***************
innodb_flush_method=O_DIRECT
一般情况下,我们更偏向于性能的话。
innodb_flush_log_at_trx_commit=0 ***************
sync_binlog=0 ***************
innodb_flush_method=fsync

  1. 参数优化结果
    [mysqld]
    basedir=/data/mysql
    datadir=/data/mysql/data
    socket=/tmp/mysql.sock
    log-error=/var/log/mysql.log
    log_bin=/data/binlog/mysql-bin
    binlog_format=row
    skip-name-resolve
    server-id=52
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    relay_log_purge=0
    max_connections=1024
    back_log=128
    wait_timeout=60
    interactive_timeout=7200
    key_buffer_size=16M
    query_cache_size=64M
    query_cache_type=1
    query_cache_limit=50M
    max_connect_errors=20
    sort_buffer_size=2M
    max_allowed_packet=32M
    join_buffer_size=2M
    thread_cache_size=200
    innodb_buffer_pool_size=4096M
    innodb_flush_log_at_trx_commit=1
    innodb_log_buffer_size=32M
    innodb_log_file_size=128M
    innodb_log_files_in_group=3
    binlog_cache_size=2M
    max_binlog_cache_size=8M
    max_binlog_size=512M
    expire_logs_days=7
    read_buffer_size=2M
    read_rnd_buffer_size=2M
    bulk_insert_buffer_size=8M
    [client]
    socket=/tmp/mysql.sock

再次压力测试 :
mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='oldboy' --query="select * from oldboy.t_100w where k2='FGCD'" engine=innodb --number-of-queries=200000 -uroot -p123 -verbose

  1. 锁的监控及处理 *****

7.1 锁等待模拟

tx1:

USE test
UPDATE t100w SET k1='av' WHERE id=10;

tx2:

USE test
UPDATE t100w SET k1='az' WHERE id=10;

监控锁状态:

1. 看有没有锁等待

SHOW STATUS LIKE 'innodb_row_lock%';

2. 查看哪个事务在等待(被阻塞了)

USE information_schema
SELECT * FROM information_schema.INNODB_TRX WHERE trx_state='LOCK WAIT';

trx_id : 事务ID号
trx_state : 当前事务的状态
trx_mysql_thread_id:连接层的,连接线程ID(SHOW PROCESSLIST ===>Id或trx_id )
trx_query : 当前被阻塞的操作(一般是要丢给开发的)

7.3.查看锁源,谁锁的我!
SELECT * FROM sys.innodb_lock_waits; ## ====>被锁的和锁定它的之间关系

locked_table : 哪张表出现的等待
waiting_trx_id: 等待的事务(与上个视图trx_id 对应)
waiting_pid : 等待的线程号(与上个视图trx_mysql_thread_id)
blocking_trx_id : 锁源的事务ID
blocking_pid : 锁源的线程号

7.4. 找到锁源的thread_id
SELECT * FROM performance_schema.threads WHERE processlist_id=3;
====> 28
7.5. 找到锁源的SQL语句
-- 当前在执行的语句
SELECT * FROM performance_schema.events_statements_current WHERE thread_id=28;
-- 执行语句的历史
SELECT * FROM performance_schema.events_statements_history WHERE thread_id=28;

得出结果,丢给开发
表信息
被阻塞的
锁源SQL

练习:
一键获得以上信息,请写出具体的SQL语句
7.6 优化项目:锁的监控及处理

  1. 背景:
    硬件环境: DELL R720,E系列16核,48G MEM,SAS900G6,RAID10
    在例行巡检时,发现9-11点时间段的CPU压力非常高(80-90%)

  2. 项目的职责
    2.1 通过top详细排查,发现mysqld进程占比达到了700-800%
    2.2 其中有量的CPU是被用作的SYS和WAIT,us处于正常
    2.3 怀疑是MySQL 锁 或者SQL语句出了问题
    2.4 经过排查slowlog及锁等待情况,发现有大量锁等待及少量慢语句
    (1) pt-query-diagest 查看慢日志
    (2) 锁等待有没有?
    db03 [(none)]>show status like 'innodb_row_lock%';
    +-------------------------------+-------+
    | Variable_name | Value |
    +-------------------------------+-------+
    | Innodb_row_lock_current_waits | 0 |
    | Innodb_row_lock_time | 0 |
    | Innodb_row_lock_time_avg | 0 |
    | Innodb_row_lock_time_max | 0 |
    | Innodb_row_lock_waits | 0 |
    +-------------------------------+-------+
    情况一:
    有100多个current_waits,说明当前很多锁等待情况
    情况二:
    1000多个lock_waits,说明历史上发生过的锁等待很多
    2.5 查看那个事务在等待(被阻塞了)
    2.6 查看锁源事务信息(谁锁的我)
    2.7 找到锁源的thread_id
    2.8 找到锁源的SQL语句

  3. 找到语句之后,和应用开发人员进行协商
    (1)
    开发人员描述,此语句是事务挂起导致
    我们提出建议是临时kill 会话,最终解决问题
    (2)
    开发人员查看后,发现是业务逻辑问题导致的死锁,产生了大量锁等待
    临时解决方案,将阻塞事务的会话kill掉.
    最终解决方案,修改代码中的业务逻辑
    项目结果:
    经过排查处理,锁等待的个数减少80%.解决了CPU持续峰值的问题.

锁监控设计到的命令:
show status like 'innodb_rows_lock%'
select * from information_schema.innodb_trx;
select * from sys.innodb_lock_waits;
select * from performance_schema.threads;
select * from performance_schema.events_statements_current;
select * from performance_schema.events_statements_history;

  1. 主从优化:

5.7 从库多线程MTS

基本要求:
5.7以上的版本(忘记小版本)
必须开启GTID
binlog必须是row模式

gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

5.7 :
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=8

cpu核心数作为标准

CHANGE MASTER TO
MASTER_HOST='10.0.0.128',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3307,
MASTER_AUTO_POSITION=1;
start slave;

  1. 分页优化
    select * from t where limit 8000000,10

普通优化:
select * from (select id from t limit limit 8000000,5000) b t a where a.id=b.id;

业务优化:
select* from t where id>last_id order by id desc limit 10

  1. TPS和QPS指标
    一、tps计算
    tps = (Com_commit + Com_rollback) / Uptime
    其中Com_commit是已提交事务数目,Com_rollback是回滚的事务数目,Uptime是运行时间。

获取方式:
show global status like "Com_commit";
show global status like 'uptime';
eg:通过查看show global status得到commit为132842, rollback为435, Uptime为364,则:
tps = (132842 + 435) / 364 = 366.14560439560439560440

二、qps计算
两种计算方式
1、基于Questions计算
qps = Questions / Uptime
eg:通过查看show global status得到Questions为2417815,Uptime为364,则:
qps = 2417815 / 364 = 6642.34890109890109890110

注意到mysql的status里面还有个Queries: 2417824,比Questions大一点,这两个的区别:
Queries:这个状态变量表示,mysql系统接收的查询的次数,包括存储过程内部的查询
Questions:这个状态变量表示,mysql系统接收查询的次数,但是不包括存储过程内部的查询
所以用Questions而不是Queries

你可能感兴趣的:(Linux学习-MySQL-week04)