006、MySQL的全面优化
本文最后更新于 257 天前,其中的信息可能已经过时,如有错误请发送邮件到wuxianglongblog@163.com

MySQL的全面优化

一.硬件层面优化

1 硬件选配

DELL、HP、IBM、华为、浪潮。

CPU:I系列(适合CPU密集型,适合在线分析的系统)、E系列(适合IO密集型,核心数偏多,并发性较高)

内存:带有ECC功能的内存。

IO : SAS HHD、 pci-e SSD 、 Nvme flash(非易失性内存快速)

raid卡:Raid10, RAID 0

网卡: 单卡单口  bonding  + 交换机堆叠

云服务器: ECS 、RDS 、TDSQL、PolarxDB

2.关闭NUMA[了解即可]

(1)bios级别:
    在bios层面numa关闭时,无论os层面的numa是否打开,都不会影响性能。 

    # numactl --hardware
    available: 1 nodes (0)       #如果是2或多个nodes就说明numa没关掉

(2)OS grub级别:
    vi /boot/grub2/grub.cfg
    #/* Copyright 2010, Oracle. All rights reserved. */

    default=0
    timeout=5
    hiddenmenu
    foreground=000000
    background=ffffff
    splashimage=(hd0,0)/boot/grub/oracle.xpm.gz

    title Trying_C0D0_as_HD0
    root (hd0,0)
    kernel /boot/vmlinuz-2.6.18-128.1.16.0.1.el5 root=LABEL=DBSYS ro bootarea=dbsys rhgb quiet console=ttyS0,115200n8 console=tty1 crashkernel=128M@16M numa=off
    initrd /boot/initrd-2.6.18-128.1.16.0.1.el5.img

    温馨提示:
        在os层numa关闭时,打开bios层的numa会影响性能,QPS会下降15-30%。

(3)数据库级别:
    mysql> SHOW VARIABLES LIKE '%numa%';
    +------------------------+-------+
    | Variable_name          | Value |
    +------------------------+-------+
    | innodb_numa_interleave | OFF   |
    +------------------------+-------+

    或者: 
    vi /etc/init.d/mysqld
    找到如下行
    # Give extra arguments to mysqld with the my.cnf file. This script
    # may be overwritten at next upgrade.
    $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &

    wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?
    将$bindir/mysqld_safe --datadir="$datadir"这一行修改为:

    /usr/bin/numactl --interleave all $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
    wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?

3.阵列卡配置建议

raid10(推荐),raid 0.

SSD或者PCI-E或者Flash

强制回写(Force WriteBack)

BBU 电池:
    如果没电会有较大性能影响、定期充放电。
    如果有UPS、多路电源、发电机。可以关闭。

关闭预读:
    有可能的话开启Cache(如果UPS、多路电源、发电机。)

4.网卡绑定

bonding技术,业务数据库服务器都要配置bonding继续。建议是主备模式。交换机一定要堆叠。

5.存储多路径

使用独立存储设备的话,需要配置多路径。
linux 自带 : multipath
厂商提供    : 

二.系统层面优化

1.内核优化-更改文件句柄和进程数

(1)/etc/sysctl.conf
    vm.swappiness = 0  # 直接禁用SWAP
    net.ipv6.conf.all.disable_ipv6 = 1  #禁用IPV6
    vm.dirty_ratio = 20
    vm.dirty_background_ratio = 10
    net.ipv4.tcp_max_syn_backlog = 819200
    net.core.netdev_max_backlog = 400000
    net.core.somaxconn = 4096
    net.ipv4.tcp_tw_reuse=1
    net.ipv4.tcp_tw_recycle=0

(2)limits.conf 
    nofile 63000

2.防火墙

禁用selinux : /etc/sysconfig/selinux 更改SELINUX=disabled.

iptables如果不使用可以关闭。可是需要打开MySQL需要的端口号

3.文件系统优化

(1)推荐使用XFS文件系统
(2)MySQL数据分区独立 ,例如挂载点为: /data
(3)mount参数 defaults, noatime, nodiratime, nobarrier 

如/etc/fstab:
/dev/sdb /data    xfs     defaults,noatime,nodiratime,nobarrier        1 2

4.不使用LVM

因为LVM会需要创建一个软件层,并不会直接使用磁盘设备,会造成一定性能的影响。

5.关闭THP

vi /etc/rc.local
在文件末尾添加如下指令:
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
   echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
   echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

[root@master ~]# cat /sys/kernel/mm/transparent_hugepage/enabled 
always madvise [never]
[root@master ~]# cat  /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]

6.io调度

SAS :      deadline
SSD&PCI-E: noop

centos 7 默认是deadline
cat   /sys/block/sda/queue/scheduler

#临时修改为deadline(centos6)
echo deadline >/sys/block/sda/queue/scheduler 

vi /boot/grub/grub.conf
更改到如下内容:
kernel /boot/vmlinuz-2.6.18-8.el5 ro root=LABEL=/ elevator=deadline rhgb quiet

三. 数据库版本选择

(1)稳定版:选择开源的社区版的稳定版GA版本。
(2)选择mysql数据库GA版本发布后6个月-12个月的GA双数版本,大约在15-20个小版本左右。
(3)要选择前后几个月没有大的BUG修复的版本,而不是大量修复BUG的集中版本。
(4)要考虑开发人员开发程序使用的版本是否兼容你选的版本。
(5)作为内部开发测试数据库环境,跑大概3-6个月的时间。
(6)优先企业非核心业务采用新版本的数据库GA版本软件。
(7)向DBA高手请教,或者在技术氛围好的群里和大家一起交流,使用真正的高手们用过的好用的GA版本产品。

最终建议: 8.0.20是一个不错的版本选择。向后可以选择双数版。

四.数据库三层结构及核心参数优化

1.连接层

max_connections=1000         #*****
max_connect_errors=999999
wait_timeout=600             #*****
interactive_wait_timeout=3600
net_read_timeout  = 120
net_write_timeout = 120
max_allowed_packet= 64M      #*****

推荐阅读:
    https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html
    https://dev.mysql.com/doc/refman/8.0/en/server-status-variables.html

2.Server层

sql_safe_updates                =1                 # *****
slow_query_log                  =ON
slow_query_log_file             =/data/3307/slow.log   # *****
long_query_time                 =1                  # *****
log_queries_not_using_indexes   =ON                 # *****
log_throttle_queries_not_using_indexes = 10         # *****
sort_buffer                     = 1M
join_buffer                     = 1M
read_buffer                     = 1M
read_rnd_buffer                 = 1M
tmp_table                       = 16M
heap_table                      = 16M
max_execution_time              = 28800
lock_wait_timeout               = 60                 # *****
lower_case_table_names          =1                   # *****            
thread_cache_size               =64                  
log_timestamps                  =SYSTEM              # *****
init_connect                    ="set names utf8"    # *****
event_scheduler                 =OFF
secure-file-priv                =/tmp                # *****
binlog_expire_logs_seconds      =2592000             # *****
sync_binlog                     =1                   # *****
log-bin                         =/data/3307/mysql-bin
log-bin-index                   =/data/3307/mysql-bin.index
max_binlog_size                 =500M
binlog_format                   =ROW

3.存储引擎层

transaction-isolation               ="READ-COMMITTED"    # *****
innodb_data_home_dir                =/xxx
innodb_log_group_home_dir           =/xxx
innodb_log_file_size                =2048M
innodb_log_files_in_group           =3
innodb_flush_log_at_trx_commit      =2                   # *****
innodb_flush_method                 =O_DIRECT            # *****
innodb_io_capacity                  =1000                # *****
innodb_io_capacity_max              =4000         
innodb_buffer_pool_size             =64G                 # *****
innodb_buffer_pool_instances        =4                   # *****
innodb_log_buffer_size              =64M                 # *****
innodb_max_dirty_pages_pct          =85                  # *****
innodb_lock_wait_timeout            =10                  # *****
innodb_open_files                   =63000               # *****
innodb_page_cleaners                =4
innodb_sort_buffer_size             =64M
innodb_print_all_deadlocks          =1                   #
innodb_rollback_on_timeout          =ON
innodb_deadlock_detect              =ON

推荐阅读:
    https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html

4.复制

relay_log                       =/opt/log/mysql/blog/relay
relay_log_index                 =/opt/log/mysql/blog/relay.index
max_relay_log_size              =500M
relay_log_recovery              =ON

rpl_semi_sync_master_enabled                =ON
rpl_semi_sync_master_timeout                =1000
rpl_semi_sync_master_trace_level            =32
rpl_semi_sync_master_wait_for_slave_count   =1
rpl_semi_sync_master_wait_no_slave          =ON
rpl_semi_sync_master_wait_point             =AFTER_SYNC
rpl_semi_sync_slave_enabled                 =ON
rpl_semi_sync_slave_trace_level             =32

binlog_group_commit_sync_delay              =1
binlog_group_commit_sync_no_delay_count     =1000

gtid_mode                       =ON
enforce_gtid_consistency        =ON

skip-slave-start                =1
#read_only                      =ON
#super_read_only                =ON
log_slave_updates               =ON
server_id                       =2330602
report_host                     =xxxx
report_port                     =3306
slave_parallel_type                         =LOGICAL_CLOCK
slave_parallel_workers                      =4
master_info_repository                      =TABLE
relay_log_info_repository                   =TABLE

5.其它

客户端配置: 
[mysql]
no-auto-rehash
prompt=db106 [\d]>

五.开发规范

1.字段规范

(1)每个表建议在30个字段以内。
(2)需要存储emoji字符的,则选择utf8mb4字符集。
(3)机密数据,加密后存储。
(4)整型数据,默认加上UNSIGNED。
(5)存储IPV4地址建议用bigINT UNSIGNE,查询时再利用INET_ATON()、INET_NTOA()函数转换。
(6)如果遇到BLOB、TEXT大字段单独存储表或者附件形式存储。如果可以的话,建议使用ES存储!
(7)选择尽可能小的数据类型,用于节省磁盘和内存空间。
(8)存储浮点数,可以放大倍数存储。
(9)每个表必须有主键,INT/BIGINT并且自增做为主键,分布式架构使用sequence序列生成器保存。
(10)每个列使用not null,或增加默认值。

2.SQL语句规范

(1)去掉不必要的括号
    如:      ((a AND b) AND c OR (((a AND b) AND (c AND d)))) 
    修改成    (a AND b AND c) OR (a AND b AND c AND d)

(3)去掉重叠条件
    如:      (a<b AND b=c) AND a=5
    修改成    b>5 AND b=c AND a=5
    如:      (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
    修改成    B=5 OR B=6

(3)避免使用not in、not exists 、<>、like %%

(4)多表连接,小表驱动大表

(5)减少临时表应用,优化order by 、group by、union、distinct、join等

(6)减少语句查询范围,精确查询条件

(7)多条件,符合联合索引最左原则

(8)查询条件减少使用函数、拼接字符等条件、条件隐式转换

(9)union all 替代 union

(10)减少having子句使用

(11)如非必须不使用for update语句

(12)update和delete,开启安全更新参数

(13)减少inset  ... select语句应用

(14)使用load替代insert录入大数据

(15)导入大量数据时,可以禁用索引、增大缓冲区、增大redo文件和buffer、关闭autocommit、RC级别可以提高效率

(16)优化limit,最好业务逻辑中先获取主键ID,再基于ID进行查询 
    limit 5000000,10     limit 10 , 200

(17)DDL执行前要审核

(18)多表连接语句执行前要看执行计划

六.索引优化

(1)非唯一索引按照“i_字段名称_字段名称[_字段名]”进行命名。

(2)唯一索引按照“u_字段名称_字段名称[_字段名]”进行命名。

(3)索引名称使用小写。

(4)索引中的字段数不超过5个。

(5)唯一键由3个以下字段组成,并且字段都是整形时,使用唯一键作为主键。

(6)没有唯一键或者唯一键不符合5中的条件时,使用自增id作为主键。

(7)唯一键不和主键重复。

(8)索引选择度高的列作为联合索引最左条件

(9)ORDER BY,GROUP BY,DISTINCT的字段需要添加在索引的后面。

(10)单张表的索引数量控制在5个以内,若单张表多个字段在查询需求上都要单独用到索引,需要经过DBA评估。
    查询性能问题无法解决的,应从产品设计上进行重构。

(11)使用EXPLAIN判断SQL语句是否合理使用索引,尽量避免extra列出现:Using File Sort,Using Temporary。

(12)UPDATE、DELETE语句需要根据WHERE条件添加索引。

(13)对长度大于50的VARCHAR字段建立索引时,按需求恰当的使用前缀索引,或使用其他方法。

(14)下面的表增加一列url_crc32,然后对url_crc32建立索引,减少索引字段的长度,提高效率。
CREATE TABLE all_url(ID INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
url VARCHAR(255) NOT NULL DEFAULT 0,      
url_crc32 INT UNSIGNED NOT NULL DEFAULT 0,
index idx_url(url_crc32));

(15)合理创建联合索引(避免冗余),(a,b,c) 相当于 (a) 、(a,b) 、(a,b,c)。

(16)合理利用覆盖索引,减少回表。

(17)减少冗余索引和使用率较低的索引
mysql> select * from schema_unused_indexes;
mysql> select * from schema_redundant_indexes\G

七.锁优化

1.全局锁 Global Read lock

(1)介绍
    全局读锁(FTWRL)的加锁方法: 
        flush tables with read lock.
    解锁方法: 
        unlock tables;
    出现场景: 
        mysqldump  --master-data  
        xtrabackup(8.0之前早期版本)等备份时。
    属于类型: 
        MDL(matedatalock)层面锁
    影响情况: 
        加锁期间,阻塞所有事务写入,阻塞所有已有事务commit。
        MDL,等待时间受 lock_wait_timeout=31536000

(2)检测方法
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME = 'wait/lock/metadata/sql/mdl';

mysql> select * from performance_schema.metadata_locks;

mysql> select OBJECT_SCHEMA ,OBJECT_NAME ,LOCK_TYPE,LOCK_DURATION,LOCK_STATUS ,OWNER_THREAD_ID,OWNER_EVENT_ID from performance_schema.metadata_locks;

mysql> show processlist;
mysql> select * from sys.schema_table_lock_waits;

(3).一个经典故障:5.7 xtrabackup/mysqldump备份时数据库出现hang状态,所有查询都不能进行
    session1: 模拟一个大的查询或事务
    mysql> select id,sleep(100)  from city where id<100  for update ;

    session2: 模拟备份时的FTWRL 
    mysql> flush tables with read lock;
    -- 此时发现命令被阻塞

    session3: 发起查询,发现被阻塞
    mysql> select * from world.city where id=1 for update;

    结论: 备份时,一定要选择业务不繁忙期间,否则有可能会阻塞正常业务。

案例2: 
    5.7版本  innobackupex备份全库,进程死了,mysql里就是全库读锁,后边insert 全阻塞了

    show processlist  ---->  select * from performance_schema.metadata_locks;  ---> pending ---->granted ----> OWNER_THREAD_ID: 66---->  select * from threads  \G ----->processlist_Id---->  show processlist ----->  kill processlist_Id 

2.row lock wait

(1)介绍
    record lock 、gap、next lock
    都是基于索引加锁,与事务隔离级别有关。

(2)行锁监控及分析
    # 确认有没有锁等待:
    show status like 'innodb_row_lock%'
    select * from information_schema.innodb_trx;

    # 查询锁等待详细信息
    select * from sys.innodb_lock_waits;   ----> blocking_pid(锁源的连接线程)

    # 通过连接线程找SQL线程
    select * from performance_schema.threads;

    # 通过SQL线程找到 SQL语句
    select * from performance_schema.events_statements_history;

(3)优化方向
    1. 优化索引
    2. 减少事务的更新范围
    3. RC
    4. 拆分语句: 
        例如:  
        update t1 set num=num+10 where k1 <100;  k1 是辅助索引,record lock gap next
        改为:
           select id from t1 where  k1 <100; ---> id: 20,30,50 
           update t1 set num=num+10   where id in (20,30,50);

八.架构优化

高可用架构:
    MHA+ProxySQL+GTID
    MGR\InnoDB Cluster
    PXC 

读写分离: 
    ProxySQL、MySQL-router

NoSQL: 
    Redis+sentinel,Redis Cluster
    MongoDB RS/MongoDB SHARDING Cluster 
    ES

九.安全优化

(1)使用普通nologin用户管理MySQL
(2)合理授权用户、密码复杂度及最小权限、系统表保证只有管理员用户可访问。
(3)删除数据库匿名用户
(4)锁定非活动用户
(5)MySQL尽量不暴露互联网,需要暴露互联网用户需要设置明确白名单、替换MySQL默认端口号、使用ssl连接
(6)优化业务代码,防止SQL注入。
谨此笔记,记录过往。凭君阅览,如能收益,莫大奢望。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇