MySQL全面優(yōu)化

優(yōu)化介紹

準備一臺MySQL的虛擬機環(huán)境,最好修改為4G內(nèi)存,4核CPU

image

啟動3306節(jié)點的 mysql,并導入t100w的庫

t100w庫 共享地址 提取密碼:999

環(huán)境準備

cpu:4 , mem:8G , mysql:5.7.26全新環(huán)境

壓力測試準備

 /etc/init.d/mysqld start
mysql < t100w.sql
mysqladmin -uroot -p password 123

mysqlslap --defaults-file=/etc/my.cnf \
--concurrency=100 --iterations=1 --create-schema='test' \
--query="select * from test.t100w where k2='FGCD'" engine=innodb \
--number-of-queries=2000 -uroot -p123 -verbose

image

優(yōu)化哲學

為什么

`為了獲得成就感?
為了證實比系統(tǒng)設(shè)計者更懂數(shù)據(jù)庫?
為了從優(yōu)化成果來證實優(yōu)化者更有價值?
NO!NO!NO!NO!NO!NO!

但通常事實證實的結(jié)果往往會和您期待相反!
優(yōu)化有風險,涉足需謹慎!`

優(yōu)化風險

優(yōu)化不總是對一個單純的環(huán)境進行!還很可能是一個復雜的已投產(chǎn)的系統(tǒng)。
優(yōu)化手段本來就有很大的風險,只不過你沒能力意識到和預(yù)見到!
任何的技術(shù)可以解決一個問題,但必然存在帶來一個問題的風險!
對于優(yōu)化來說解決問題而帶來的問題控制在可接受的范圍內(nèi)才是有成果。
保持現(xiàn)狀或出現(xiàn)更差的情況都是失??!
穩(wěn)定性和業(yè)務(wù)可持續(xù)性通常比性能更重要!
優(yōu)化不可避免涉及到變更,變更就有風險!
優(yōu)化使性能變好,維持和變差是等概率事件!
優(yōu)化不能只是數(shù)據(jù)庫管理員擔當風險,但會所有的人分享優(yōu)化成果!
所以優(yōu)化工作是由業(yè)務(wù)需要驅(qū)使的?。?!

誰參與

DBA—數(shù)據(jù)庫管理員(系統(tǒng),硬件,網(wǎng)路,存儲,代碼,架構(gòu)思維)
數(shù)據(jù)庫管理員
業(yè)務(wù)部門代表
應(yīng)用程序架構(gòu)師
應(yīng)用程序設(shè)計人員
應(yīng)用程序開發(fā)人員
硬件及系統(tǒng)管理員
存儲管理員

優(yōu)化的方向

安全方向優(yōu)化(業(yè)務(wù)持續(xù)性)
性能方向優(yōu)化(業(yè)務(wù)高效性)


優(yōu)化的范圍及思路

優(yōu)化范圍:

存儲、主機和操作系統(tǒng):
主機架構(gòu)穩(wěn)定性
I/O規(guī)劃及配置
Swap
OS內(nèi)核參數(shù)
網(wǎng)絡(luò)問題
應(yīng)用程序:(Index,lock,session)
應(yīng)用程序穩(wěn)定性和性能
SQL語句性能
串行訪問資源
性能欠佳會話管理
數(shù)據(jù)庫優(yōu)化:(內(nèi)存、數(shù)據(jù)庫設(shè)計、參數(shù))
內(nèi)存
數(shù)據(jù)庫結(jié)構(gòu)(物理&邏輯)
實例配置
架構(gòu)設(shè)計 :
性能 : 讀寫分離,分布式
安全 : 主備,多活
安全&性能 : 分布式,NewSQL

image

優(yōu)化工具和命令

系統(tǒng)層面

CPU:top
top命令:
%CPU   %MEM     COMMAND                                                
400.0  4.3      mysqld  

%Cpu(s): 99.0 us,  1.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

按1鍵 展開:
%Cpu0  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

%Cpu(s):  99.0 us,  1.0 sy,  0.0 id,  0.0 wa
0.0 id : CPU空閑的百分比
5% 以上,還是有空閑的.

99.0 us : 用戶程序占用的CPU百分比
          對于mysql程序,處理數(shù)據(jù).

1.0  sy : 內(nèi)核程序占用的CPU百分比
          資源管理,資源調(diào)度等,計算.
sys過高:  鎖,并發(fā)連接數(shù)較高,數(shù)據(jù)處理分析應(yīng)用

0.0 wa : 花在等待的CPU時間
IO方面出了問題
          鎖.大事務(wù)
          IO本身: IOPS達到峰值

[root@db01 ~]# top -H -p 9846

MEM

Swap:  1560568 total,  1560568 free,  0 used.  7386000 avail Mem 

IO: 
[root@db01 ~]# iostat -dk 1
Linux 3.10.0-957.el7.x86_64 (db01)  08/23/2019  _x86_64_    (4 CPU)

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               1.65        36.24       115.44     223266     711168

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.00         0.00         0.00          0          0

數(shù)據(jù)庫層面

基礎(chǔ)優(yōu)化:
    show status  
    show variables 
    show index  
    show processlist 
    show slave status
    show engine innodb status 
    desc /explain 
    slowlog
擴展類深度優(yōu)化:
    pt系列
    mysqlslap 
    sysbench 
    information_schema 
    performance_schema
    sys

優(yōu)化思路分解

硬件優(yōu)化

真實的硬件(PC Server): DELL R系列 ,華為,浪潮,HP,聯(lián)想
云產(chǎn)品:ECS、數(shù)據(jù)庫RDS、DRDS
IBM 小型機 P6 570 595 P7 720 750 780 P8

CPU根據(jù)數(shù)據(jù)庫類型

OLTP
OLAP
IO密集型:線上系統(tǒng),OLTP主要是IO密集型的業(yè)務(wù),高并發(fā)
CPU密集型:數(shù)據(jù)分析數(shù)據(jù)處理,OLAP,cpu密集型的,需要CPU高計算能力(i系列,IBM power系列)
CPU密集型: I 系列的,主頻很高,核心少
IO密集型: E系列(至強),主頻相對低,核心數(shù)量多

內(nèi)存

建議2-3倍cpu核心數(shù)量 (ECC)

磁盤選擇

SATA-III   SAS    Fc    SSD(sata) pci-e  ssd  Flash
主機 RAID卡的BBU(Battery Backup Unit)關(guān)閉

存儲

根據(jù)存儲數(shù)據(jù)種類的不同,選擇不同的存儲設(shè)備
配置合理的RAID級別(raid5、raid10、熱備盤)   
r0 :條帶化 ,性能高
r1 :鏡像,安全
r5 :校驗+條帶化,安全較高+性能較高(讀),寫性能較低 (適合于讀多寫少)
r10:安全+性能都很高,最少四塊盤,浪費一半的空間(高IO要求)

HDS     
EMC2(DELL)     
IBM 
DELL   華為 

網(wǎng)絡(luò)

1、硬件買好的(單卡單口)
2、網(wǎng)卡綁定(bonding),交換機堆疊
    主備模式: mode=1
    負載均衡: mode=0
    注意: 多交換機要做堆疊.
以上問題,提前規(guī)避掉。

操作系統(tǒng)優(yōu)化

Swap調(diào)整
cat /proc/sys/vm/swappiness

臨時
echo 0 >/proc/sys/vm/swappiness
永久
vim /etc/sysctl.conf
vm.swappiness=0
sysctl -p

這個參數(shù)決定了Linux是傾向于使用swap,還是傾向于釋放文件系統(tǒng)cache。在內(nèi)存緊張的情況下,數(shù)值越低越傾向于釋放文件系統(tǒng)cache。
當然,這個參數(shù)只能減少使用swap的概率,并不能避免Linux使用swap。

修改MySQL的配置參數(shù)innodb_flush_method,開啟O_DIRECT模式
這種情況下,InnoDB的buffer pool會直接繞過文件系統(tǒng)cache來訪問磁盤,但是redo log依舊會使用文件系統(tǒng)cache。值得注意的是,Redo log是覆寫模式的,即使使用了文件系統(tǒng)的cache,也不會占用太多

IO調(diào)度策略

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

#臨時修改為deadline(centos6)
echo deadline >/sys/block/sda/queue/scheduler 
vi /boot/grub/grub.conf
更改到如下內(nèi)容:
kernel /boot/vmlinuz-2.6.18-8.el5 ro root=LABEL=/ elevator=deadline rhgb quiet

IO :
    raid
    no lvm
    ext4或xfs
    ssd
    IO調(diào)度策略
提前規(guī)劃好以上所有問題,減輕MySQL優(yōu)化的難度。

應(yīng)用端

  1. 開發(fā)過程規(guī)范,標準
  2. 減少爛SQL:不走索引,復雜邏輯,切割大事務(wù).
  3. 避免業(yè)務(wù)邏輯錯誤,避免鎖爭用.
    這個階段,需要我們DBA深入業(yè)務(wù),或者要和開發(fā)人員\業(yè)務(wù)人員配合實現(xiàn)

優(yōu)化,最根本的是"優(yōu)化"人.
----oldguo

MySQL參數(shù)優(yōu)化測試

虛擬機vm12.5,OS centos 6.9(系統(tǒng)已優(yōu)化),cpu4(I5 4440 3.1GHZ),MEM4GB ,HardDisk:SSD


參數(shù)優(yōu)化細節(jié):

max_connections                   最大連接數(shù)
key_buffer_size                   臨時表         
innodb_flush_log_at_trx_commit    雙一:redo log的刷寫策略,每次事務(wù)提交時,首先刷寫os buffer,立即刷寫到磁盤.
innodb_buffer_pool_size           數(shù)據(jù)緩沖區(qū)大小,建議不要超過物理內(nèi)存80%
max_allowed_packet                允許最大數(shù)據(jù)包的大小
sync_binlog                       雙一:二進制日志的刷寫策略,每次事務(wù)提交理解刷寫二進制日志
innodb_flush_method               
刷寫策略:
O_DIRECT : 
        刷寫buffer pool 繞過OS buffer ,直接刷磁盤
        刷寫redo buffer 先到OS buffer ,再到磁盤

Max_connections *****

(1)簡介
Mysql的最大連接數(shù),如果服務(wù)器的并發(fā)請求量比較大,可以調(diào)高這個值,當然這是要建立在機器能夠支撐的情況下,因為如果連接數(shù)越來越多,mysql會為每個連接提供緩沖區(qū),就會開銷的越多的內(nèi)存,所以需要適當?shù)恼{(diào)整該值,不能隨便去提高設(shè)值。
(2)判斷依據(jù)
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.開啟數(shù)據(jù)庫時,我們可以臨時設(shè)置一個比較大的測試值
    2.觀察show status like 'Max_used_connections';變化
    3.如果max_used_connections跟max_connections相同,
    那么就是max_connections設(shè)置過低或者超過服務(wù)器的負載上限了,
    低于10%則設(shè)置過大. 

back_log ***

(1)簡介
mysql能暫存的連接數(shù)量,當主要mysql線程在一個很短時間內(nèi)得到非常多的連接請求時候它就會起作用,如果mysql的連接數(shù)據(jù)達到max_connections時候,新來的請求將會被存在堆棧中,等待某一連接釋放資源,該推棧的數(shù)量及back_log,如果等待連接的數(shù)量超過back_log,將不被授予連接資源。
back_log值指出在mysql暫時停止回答新請求之前的短時間內(nèi)有多少個請求可以被存在推棧中,只有如果期望在一個短時間內(nèi)有很多連接的時候需要增加它
(2)判斷依據(jù)
show full processlist
發(fā)現(xiàn)大量的待連接進程時,就需要加大back_log或者加大max_connections的值
(3)修改方式舉例
vim /etc/my.cnf 
back_log=1024

wait_timeout和interactive_timeout ****

(1)簡介
wait_timeout:指的是mysql在關(guān)閉一個非交互的連接之前所要等待的秒數(shù)
interactive_timeout:指的是mysql在關(guān)閉一個交互的連接之前所需要等待的秒數(shù),比如我們在終端上進行mysql管理,使用的即使交互的連接,這時候,如果沒有操作的時間超過了interactive_time設(shè)置的時間就會自動的斷開,默認的是28800,可調(diào)優(yōu)為7200。
wait_timeout:如果設(shè)置太小,那么連接關(guān)閉的就很快,從而使一些持久的連接不起作用

(2)設(shè)置建議
如果設(shè)置太大,容易造成連接打開時間過長,在show processlist時候,能看到很多的連接 ,一般希望wait_timeout盡可能低

(3)修改方式舉例
wait_timeout=60
interactive_timeout=7200

長連接的應(yīng)用,為了不去反復的回收和分配資源,降低額外的開銷。
一般我們會將wait_timeout設(shè)定比較小,interactive_timeout要和應(yīng)用開發(fā)人員溝通長鏈接的應(yīng)用是否很多。如果他需要長鏈接,那么這個值可以不需要調(diào)整。
另外還可以使用類外的參數(shù)彌補。

key_buffer_size *****

(1)簡介
key_buffer_size指定索引緩沖區(qū)的大小,它決定索引處理的速度,尤其是索引讀的速度
《1》此參數(shù)與myisam表的索引有關(guān)
《2》內(nèi)存臨時表的創(chuàng)建有關(guān)(多表鏈接、子查詢中、union)
     在有以上查詢語句出現(xiàn)的時候,需要創(chuàng)建臨時表,用完之后會被丟棄
     臨時表有兩種創(chuàng)建方式:
                        內(nèi)存中------->key_buffer_size
                        磁盤上------->ibdata1(5.6)
                                      ibtmp1 (5.7)                                    
(2)設(shè)置依據(jù)
通過key_read_requests和key_reads可以直到key_baffer_size設(shè)置是否合理。
mysql> show variables like "key_buffer_size%";
+-----------------+---------+
| Variable_name   | Value   |
+-----------------+---------+
| key_buffer_size | 8388608 |
+-----------------+---------+
1 row in set (0.00 sec)

mysql> 
mysql> show status like "key_read%";
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Key_read_requests | 10    |
| Key_reads         | 2     |
+-------------------+-------+
2 rows in set (0.00 sec)

mysql> 
一共有10個索引讀取請求,有2個請求在內(nèi)存中沒有找到直接從硬盤中讀取索引
控制在 5%以內(nèi) 。
注:key_buffer_size只對myisam表起作用,即使不使用myisam表,但是內(nèi)部的臨時磁盤表是myisam表,也要使用該值。
可以使用檢查狀態(tài)值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) 

或者已各自的一個時段內(nèi)的差額計算,來判斷基于內(nèi)存的臨時表利用率。所以,我們會比較關(guān)注 Created_tmp_disk_tables 是否過多,從而認定當前服務(wù)器運行狀況的優(yōu)劣。
Created_tmp_disk_tables/(Created_tmp_disk_tables + Created_tmp_tables) 
控制在5%-10%以內(nèi)

參數(shù)優(yōu)化結(jié)果

vim /etc/my.cnf
[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=2048M
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

鎖的監(jiān)控及處理

鎖等待模擬

概念:
Record Lock 
Next Lock 
GAP Lock
X 
IX
S 
IS

tx1:
USE oldboy
UPDATE t_100w SET k1='av' WHERE id=10;
## tx2:
USE oldboy 
UPDATE  t_100w SET k1='az' WHERE id=10;

監(jiān)控鎖狀態(tài)

vim /etc/my.cnf
innodb_lock_wait_timeout=28800

image

看有沒有鎖等待

SHOW  STATUS LIKE 'innodb_row_lock%';

查看哪個事務(wù)在等待(被阻塞了)

USE information_schema
SELECT * FROM information_schema.INNODB_TRX WHERE trx_state='LOCK WAIT';
trx_query : 被阻塞的語句是誰 
trx_mysql_thread_id: 被阻塞的會話ID

查看鎖源,誰鎖的我!

SELECT * FROM sys.innodb_lock_waits;     ## ====>被鎖的和鎖定它的之間關(guān)系
## waiting_pid   : 等待的會話線程號
## waiting_query : 等待的語句 
## blocking_pid  : 鎖源的線程號 :2
## sql_kill_blocking_query : 處理建議
## sql_kill_blocking_connection: 處理建議

找到鎖源的thread_id

SELECT * FROM performance_schema.threads WHERE processlist_id=2;
## THREAD_ID = 27

找到鎖源的SQL語句

-- 當前在執(zhí)行的語句
SELECT * FROM performance_schema.`events_statements_current` WHERE thread_id=27;

主從優(yōu)化:

## 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


索引
簡單SQL語句

max_connections                   最大連接數(shù)
key_buffer_size                   臨時表         
innodb_flush_log_at_trx_commit    雙一:redo log的刷寫策略,每次事務(wù)提交時,首先刷寫os buffer,立即刷寫到磁盤.
innodb_buffer_pool_size           數(shù)據(jù)緩沖區(qū)大小,建議不要超過物理內(nèi)存80%
max_allowed_packet                允許最大數(shù)據(jù)包的大小
sync_binlog                       雙一:二進制日志的刷寫策略,每次事務(wù)提交理解刷寫二進制日志
innodb_flush_method               
O_DIRECT : 
刷寫buffer pool 繞過OS buffer ,直接刷磁盤
刷寫redo buffer 先到OS buffer ,再到磁盤

優(yōu)化項目:鎖的監(jiān)控及處理

背景:

硬件環(huán)境: DELL R720,E系列16核,48G MEM,SAS900G6,RAID10
在例行巡檢時,發(fā)現(xiàn)9-11點時間段的CPU壓力非常高(80-90%)

項目的職責

>1.通過top詳細排查,發(fā)現(xiàn)mysqld進程占比達到了700-800%
2.其中有量的CPU是被用作的SYS和WAIT,us處于正常
3.懷疑是MySQL 鎖 或者SQL語句出了問題
4.經(jīng)過排查slowlog及鎖等待情況,發(fā)現(xiàn)有大量鎖等待及少量慢語句    
(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,說明歷史上發(fā)生過的鎖等待很多
5 查看那個事務(wù)在等待(被阻塞了)
6 查看鎖源事務(wù)信息(誰鎖的我)
7 找到鎖源的thread_id 
8 找到鎖源的SQL語句

找到語句之后,和應(yīng)用開發(fā)人員進行協(xié)商

>(1)開發(fā)人員描述,此語句是事務(wù)掛起導致
我們提出建議是臨時kill 會話,最終解決問題
(2) 
開發(fā)人員查看后,發(fā)現(xiàn)是業(yè)務(wù)邏輯問題導致的死鎖,產(chǎn)生了大量鎖等待
臨時解決方案,將阻塞事務(wù)的會話kill掉.
最終解決方案,修改代碼中的業(yè)務(wù)邏輯

項目結(jié)果:

經(jīng)過排查處理,鎖等待的個數(shù)減少80%.解決了CPU持續(xù)峰值的問題.

鎖監(jiān)控設(shè)計到的命令:

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;

死鎖監(jiān)控

show engine innodb status\G
show variables like '%deadlock%';
vim /etc/my.cnf 
innodb_print_all_deadlocks = 1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容