MySQL優化總結
優化有風險,涉足需謹慎!
一、優化可能帶來的問題?
- 優化不總是對一個單純的環境進行,還很可能是一個複雜已投產的系統環境;
- 優化手段本身就有很大的風險,只不過我們可能沒有能力意識到和預見到;
- 任何的技術可以解決一個問題,但必然存在帶來一個問題的風險;
- 對於優化來說解決問題而帶來的問題,控制在可接受的範圍內才是有效果的,保持現狀或出現更差的情況都是失敗的;
二、優化的需求
- 穩定性和業務的持續性,通常比效能更重要;
- 優化不可避免涉及到變更,變更就有風險;
- 優化使效能變好,維持和變差等概率事件;
- 切記優化,應該是各部門協同參與的工作,任何單一部門都不能對資料庫進行優化;
- 所有優化工作,都是因業務需要;
三、優化的參與者
在進行資料庫優化時,應該有DBA、業務部門代表,應用程式設計人員、應用程式開發人員、運維等相關人員共同參與。
四、優化思路
在資料庫優化上由兩個主要方面:
- 安全:資料可持續性;
- 效能:資料的高效能訪問;
五、優化的範圍
儲存、主機、作業系統方面
- 主機架構穩定性;
- I/O規劃及配置;
- Swap交換分割槽;
- OS核心引數和網路問題;
- 應用程式方面;
- 應用程式穩定性;
- SQL語句效能;
- 序列訪問資源;
- 效能欠佳會話管理;
- 這個應用是否適合使用MySQL;
資料庫方面
- 記憶體;
- 資料庫結構(物理&邏輯);
- 例項配置;
不管是在設計系統,定位問題還是優化,都可以按照上面順序執行!
六、優化維度
資料庫優化維度有以下四個:
- 硬體;
- 系統配置;
- 資料庫表結構;
- SQL及索引;
優化選擇:
- 優化成本:硬體>系統配置>資料庫表結構>SQL及索引
- 優化效果:硬體<系統配置<資料庫表結構<SQL及索引
七、優化工具
檢查問題常用工具如下:
- mysqladmin:mysql客戶端,可進行管理操作;
- mysqlshow:功能強大的檢視shell命令;
- show [SESSION|GLOBAL] variables:檢視資料庫引數資訊;
- show [SESSION|GLOBAL] status:檢視資料庫的狀態資訊;
- information_schema:獲取元資料的方法;
- show engine innodb status:Innodb引擎的所有狀態;
- show processlist:檢視當前所有連線session狀態;
- explain:獲取查詢語句的執行計劃;
- show index:查看錶的索引資訊;
- slow-log:記錄慢查詢語句;
- mysqldumpslow:分析slowlog檔案;
- mysqlslap:分析慢日誌;
- mysql profiling:統計資料庫整體狀態工具;
- Performance Schema mysql:效能狀態統計的資料;
- mysqlslap:分析慢日誌;
第三方工具:
- zabbix:監控主機、系統、資料庫(部署zabbix監控平臺);
- pt-query-digest:分析慢日誌;
- sysbench:壓力測試工具;
- workbench:管理、備份、監控、分析、優化工具(比較費資源);
八、資料庫層面問題解決思路
針對突然的業務辦理卡頓,無法進行正常的業務處理!需要立馬解決的場景!
1、show processlist;
2、show index from table;
3、通過執行計劃判斷,索引問題(有沒有、合不合理)或者語句本身問題
4、show status like '%lock%'; # 查詢鎖狀態
5、kill SESSION_ID; # 殺掉有問題的session
① 常規調優思路
針對業務週期性的卡頓,例如在每天10-11點業務特別慢,但是還能夠使用,過了這段時間就好了。
1、檢視slowlog,分析slowlog,分析出查詢慢的語句。
2、按照一定優先順序,進行一個一個的排查所有慢語句。
3、分析top sql,進行explain除錯,檢視語句執行時間。
4、調整索引或語句本身。
② 系統層面
CPU方面:vmstat、sar top、htop、nmon、mpstat
記憶體方面:free、ps -aux
IO裝置(磁碟、網路):iostat、 ss 、 netstat 、 iptraf、iftop、lsof
九、系統層面問題解決方法
在實際的生產中,一般認為 cpu只要不超過90%都沒什麼問題 !
當前可能有以下特殊情況:
- 問題一:CPU負載高、IO負載低
原因如下:
-
記憶體不足,磁碟效能差;
-
SQL問題:資料庫層,排查SQL問題;
-
IO出問題了(磁碟到臨界了、raid設計不好、raid降級、鎖、在單位時間內tps過高);
-
tps過高: 大量的小資料IO、大量的全表掃描;
-
問題二:IO負載高、CPU負載低
原因如下:
-
大量小的IO 寫操作;
-
autocommit ,產生大量小IO;
-
IO/PS,磁碟的一個定值,硬體出廠的時候,廠家定義的一個每秒最大的IO次數;
-
大量大的IO 寫操作;
-
SQL問題的機率比較大;
-
問題三:IO和CPU負載過高
-
硬體不夠了或sql存在問題!
十、基礎優化
- 定位問題點
硬體 --> 系統 --> 應用 --> 資料庫 --> 架構(高可用、讀寫分離、分庫分表)
- 處理方向
明確優化目標、效能和安全的折中、防患未然!
- 硬體優化
主機方面:
- 根據資料庫型別,主機CPU選擇、記憶體容量選擇、磁碟選擇;
- 平衡記憶體和磁碟資源;
- 隨機的I/O和順序的I/O;
- 主機 RAID卡的BBU(Battery Backup Unit)關閉;
- CPU的選擇
cpu的兩個關鍵因素:核數、主頻
根據不同的業務型別進行選擇:
- cpu密集型:計算比較多,OLTP 主頻很高的cpu、核數還要多;
- IO密集型:查詢比較,OLAP 核數要多,主頻不一定高的;
記憶體的選擇
- OLAP型別資料庫,需要更多記憶體,和資料獲取量級有關;
- OLTP型別資料一般記憶體是cpu核心數量的2倍到4倍,沒有最佳實踐;
儲存的選擇
- 根據儲存資料種類的不同,選擇不同的儲存裝置;
- 配置合理的RAID級別(raid5、raid10、熱備盤);
對與作業系統來講,不需要太特殊的選擇,最好做好冗餘(raid1)(ssd、sas 、sata)
raid卡:
- 實現作業系統磁碟的冗餘(raid1);
- 平衡記憶體和磁碟資源;
- 隨機的I/O和順序的I/O;
- 主機 RAID卡的BBU(Battery Backup Unit)要關閉;
網路裝置方面
- 使用流量支援更高的網路裝置(交換機、路由器、網線、網絡卡、HBA卡);
注意:以上這些規劃應該在初始設計系統時就應該考慮好。
伺服器硬體優化
1、物理狀態燈;
2、自帶管理裝置:遠端控制卡(FENCE裝置:ipmi ilo idarc),開關機、硬體監控;
3、第三方的監控軟體、裝置(snmp、agent)對物理設施進行監控;
4、儲存裝置:自帶的監控平臺。EMC2(hp收購了), 日立(hds),IBM低端OEM hds,高階儲存是自己技術,華為儲存;
系統優化
- CPU:基本不需要調整,在硬體選擇方面下功夫即可;
- 記憶體:基本不需要調整,在硬體選擇方面下功夫即可;
- swap:MySQL儘量避免使用swap。阿里雲的伺服器中預設swap為0;
- IO:raid、no lvm、 ext4或xfs、ssd、IO排程策略;
- 不使用swap分割槽:
/proc/sys/vm/swappiness的內容改成0(臨時)
/etc/sysctl.conf上新增vm.swappiness=0(永久)
這個引數決定了Linux是傾向於使用swap,還是傾向於釋放檔案系統cache。在記憶體緊張的情況下,數值越低越傾向於釋放檔案系統cache。當然,這個引數只能減少使用swap的概率,並不能避免Linux使用swap。
修改MySQL的配置引數innodb_flush_method,開啟O_DIRECT模式。這種情況下,InnoDB的buffer pool會直接繞過檔案系統cache來訪問磁碟,但是redo log依舊會使用檔案系統cache。值得注意的是,Redo log是覆寫模式的,即使使用了檔案系統的cache,也不會佔用太多。
- IO排程策略:
臨時修改為deadline:
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
十一、系統引數調整
Linux系統引數優化
vim /etc/sysctl.conf
net.ipv4.ip_local_port_range =102465535# 使用者埠範圍
net.ipv4.tcp_max_syn_backlog =4096
net.ipv4.tcp_fin_timeout =30
fs.file-max=65535# 系統最大檔案控制代碼,控制的是能開啟檔案最大數量
使用者限制(mysql可以不設定以下引數)
vim/etc/security/limits.conf
* soft nproc65535
* hard nproc65535
* soft nofile65535
* hard nofile65535
十二、應用優化
業務應用和資料庫應用獨立,防火牆:iptables、selinux等其他無用服務(關閉):
$ chkconfig --level 23456 acpid off
$ chkconfig --level 23456 anacronoff
$ chkconfig --level 23456 autofsoff
$ chkconfig --level 23456 avahi-daemonoff
$ chkconfig --level 23456 bluetoothoff
$ chkconfig --level 23456 cupsoff
$ chkconfig --level 23456 firstbootoff
$ chkconfig --level 23456 haldaemonoff
$ chkconfig --level 23456 hplipoff
$ chkconfig --level 23456 ip6tablesoff
$ chkconfig --level 23456 iptablesoff
$ chkconfig --level 23456 isdnoff
$ chkconfig --level 23456 pcscdoff
$ chkconfig --level 23456 sendmailoff
$ chkconfig --level 23456 yum-updatesdoff
安裝圖形介面的伺服器不要啟動圖形介面 runlevel 3,另外,將來我們的業務是否真的需要MySQL,還是使用其他種類的資料庫。用資料庫的最高境界就是不用資料庫。
十三、資料庫優化
SQL優化方向
執行計劃、索引、SQL改寫
架構優化方向
高可用架構、高效能架構、分庫分表
十四、資料庫引數優化
例項整體(高階優化,擴充套件)
thread_concurrency #併發執行緒數量個數
sort_buffer_size #排序快取
read_buffer_size #順序讀取快取
read_rnd_buffer_size #隨機讀取快取
key_buffer_size #索引快取
thread_cache_size #執行緒快取(1G—>8, 2G—>16, 3G>32,3G—>64)
連線層(基礎優化)
設定合理的連線客戶和連線方式:
max_connections #最大連線數,看交易筆數設定
max_connect_errors #最大錯誤連線數,能大則大
connect_timeout #連線超時
max_user_connections #最大使用者連線數
skip-name-resolve #跳過域名解析
wait_timeout #等待超時
back_log #可以在堆疊中的連線數量
SQL層(基礎優化)
query_cache_size: 查詢快取
OLAP型別資料庫,需要重點加大此記憶體快取.
但是一般不會超過GB.
對於經常被修改的資料,快取會立馬失效。
我們可以實用記憶體資料庫(redis、memecache),替代他的功能。
十五、儲存引擎層(innodb基礎優化引數)
default-storage-engine
innodb_buffer_pool_size # 沒有固定大小,50%測試值,看看情況再微調。但是儘量設定不要超過實體記憶體70%
innodb_file_per_table=(1,0)
innodb_flush_log_at_trx_commit=(0,1,2) #1是最安全的,0是效能最高,2折中
binlog_sync
Innodb_flush_method=(O_DIRECT, fdatasync)
innodb_log_buffer_size #100M以下
innodb_log_file_size #100M 以下
innodb_log_files_in_group #5個成員以下,一般2-3個夠用(iblogfile0-N)
innodb_max_dirty_pages_pct #達到百分之75的時候刷寫 記憶體髒頁到磁碟。
max_binlog_cache_size #可以不設定
max_binlog_size #可以不設定
innodb_additional_mem_pool_size #小於2G記憶體的機器,推薦值是20M。32G記憶體以上100M
注:在生產環境中,資料庫的各個引數都是隨著需求去更改的,但是沒有必要去為了更改一個配置引數去重啟資料庫,但是我們可以先將需要更改的配置項設定為全域性環境變數,以便生效,然後再寫入配置檔案中,只要資料庫不重啟,設定的環境變數就不會失效,一旦重啟,配置檔案就會生效。
配置檔案可以參考如下格式:
cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3306
server_id=1
slow_query_log = 1
slow_query_log_file = /usr/local/mysql/data/slow-query.log
long_query_time = 1
log-queries-not-using-indexes
max_connections = 1024
back_log = 128
wait_timeout = 60
interactive_timeout = 7200
key_buffer_size=256M
query_cache_size = 256M
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
log-bin=mysql-bin
binlog_cache_size=2M
max_binlog_cache_size=8M
max_binlog_size=512M
expire_logs_days=7
read_buffer_size=1M
read_rnd_buffer_size=16M
bulk_insert_buffer_size=64M
log-error = /usr/local/mysql/data/mysqld.err