1.MySQL數據庫高效優化解析
Mysql優化是一項非常重要的工作,而且是一項長期的工作,曾經有一個為位DBA前輩說過:mysql的優化,三分配置的優化,七分sql語句的優化。
Mysql的優化:一般分為配置的優化、sql語句的優化、表結構的優化、索引的優化,而配置的優化:一般包括系統內核優化、mysql本身配置文件的優化。
MySQL常見的優化參數詳解:
硬件上的優化:增加內存和提高磁盤讀寫速度,都可以提高MySQL數據庫的查詢,更新的速度。另一種提高MySQL性能的方式是使用多塊磁盤來存儲數據。因為可以從多塊磁盤上並行讀取數據,這樣可以提高讀取數據的速度。
MySQL參數的優化:內存中會為MySQL保留部分的緩沖區。這些緩沖區可以提高MySQL的速度。緩沖區的大小都是在MySQL的配置文件中進行設置的。
下面對幾個重要的參數進行詳細介紹:
- key_buffer_size:表示索引緩存的大小。這個值越大,使用索引進行查詢的速度就越快。
- table_cache:表示同時打開的表的個數。這個值越大,能同時打開的表的個數就越多。這個值不是越大越好,因為同時打開的表過多會影響操作系統的性能。
- query_cache_size:表示查詢緩沖區的大小。使用查詢緩存區可以提高查詢的速度。這個方式只使用與修改操作少且經常執行相同的查詢操作的情況;默認值是0。
- Query_cache_type:表示查詢緩存區的開啟狀態。0表示關閉,1表示開啟。
- Max_connections:表示數據庫的最大連接數。這個連接數不是越大越好,因為連接會浪費內存的資源。
- sort_buffer_size:排序緩存區的大小,這個值越大,排序就越快。
- Innodb_buffer_pool_size:表示InnoDB類型的表和索引的最大緩存。這個值越大,查詢的速度就會越快。這個值太大了就會影響操作系統的性能。
當然了Mysql是一個長期的優化過程,所以在日常的運維工作中,需要不斷去總結和學習。
2.建議調整下面幾個關鍵參數以獲得較好的性能(可使用本站提供的my.cnf生成器生成配置文件模板):
1、選擇Percona或MariaDB版本的話,強烈建議啟用thread pool特性,可使得在高並發的情況下,性能不會發生大幅下降。此外,還有extra_port功能,非常實用, 關鍵時刻能救命的。還有另外一個重要特色是 QUERY_RESPONSE_TIME 功能,也能使我們對整體的SQL響應時間分布有直觀感受;
2、設置default-storage-engine=InnoDB,也就是默認采用InnoDB引擎,強烈建議不要再使用MyISAM引擎了,InnoDB引擎絕對可以滿足99%以上的業務場景,在高版本中已經默認InnoDB了,已經完全取代MyISAM;
3、調整innodb_buffer_pool_size大小,如果是單實例且絕大多數是InnoDB引擎表的話,可考慮設置為物理內存的50% ~ 70%左右;
4、根據實際需要設置innodb_flush_log_at_trx_commit、sync_binlog的值。如果要求數據不能丟失,那么兩個都設為1。如果允許丟失一點數據,則可分別設為2和10。而如果完全不用care數據是否丟失的話(例如在slave上,反正大不了重做一次),則可都設為0。這三種設置值導致數據庫的性能受到影響程度分別是:高、中、低,也就是第一個會另數據庫最慢,最后一個則相反;
5、設置innodb_file_per_table = 1,使用獨立表空間,我實在是想不出來用共享表空間有什么好處了;
6、設置innodb_data_file_path = ibdata1:1G:autoextend,千萬不要用默認的10M,否則在有高並發事務時,會受到不小的影響;
7、設置innodb_log_file_size=256M,設置innodb_log_files_in_group=2,基本可滿足90%以上的場景;
8、設置long_query_time = 1,而在5.5版本以上,已經可以設置為小於1了,建議設置為0.05(50毫秒),記錄那些執行較慢的SQL,用於后續的分析排查;
9、根據業務實際需要,適當調整max_connection(最大連接數)、max_connection_error(最大錯誤數,建議設置為10萬以上,而open_files_limit、innodb_open_files、table_open_cache、table_definition_cache這幾個參數則可設為約10倍於max_connection的大小;
10、常見的誤區是把tmp_table_size和max_heap_table_size設置的比較大,曾經見過設置為1G的,這2個選項是每個連接會話都會分配的,因此不要設置過大,否則容易導致OOM發生;其他的一些連接會話級選項例如:sort_buffer_size、join_buffer_size、read_buffer_size、read_rnd_buffer_size等,也需要注意不能設置過大;
11、由於已經建議不再使用MyISAM引擎了,因此可以把key_buffer_size設置為32M左右,並且強烈建議關閉query cache功能;
3.Mysql Innodb 引擎優化
1.首先介紹一個Innodb最重要的參數:
innodb_buffer_pool_size=4G
該參數分配內存的原則:這個參數默認分配只有8M,可以說是非常小的一個值。如果是一個專用DB服務器,那么他可以占到內存的70%-80%。這個參數不能動態更改,所以分配需多考慮。分配過大,會使Swap占用過多,致使Mysql的查詢特慢。如果你的數據比較小,那么可分配是你的數據大小+10%左右做為這個參數的值。例如:數據大小為50M,那么給這個值分配innodb_buffer_pool_size=64M
innodb_additional_mem_pool=16M
作用:用來存放Innodb的內部目錄
這個值不用分配太大,系統可以自動調。不用設置太高。通常比較大數據設置16M夠用了,如果表比較多,可以適當的增大。如果這個值自動增加,會在error log有中顯示的。
2.關於日志方面:
innodb_log_file_size=256M
作用:指定日值的大小
分配原則:幾個日值成員大小加起來差不多和你的innodb_buffer_pool_size相等。上限為每個日值上限大小為4G.一般控制在幾個LOG文件相加大小在2G以內為佳。具體情況還需要看你的事務大小,數據大小為依據。
innodb_log_files_in_group=3
作用:指定你有幾個日值組。
分配原則: 一般我們可以用2-3個日值組。默認為兩個。
innodb_log_buffer_size=3M
作用:事務在內存中的緩沖。
分配原則:控制在2-8M.這個值不用太多的。他里面的內存一般一秒鍾寫到磁盤一次。具體寫入方式和你的事務提交方式有關。在Oracle等數據庫了解這個,一般最大指定為3M比較合適。
innodb_flush_logs_at_trx_commit=1
作用:控制事務的提交方式
分配原則:這個參數只有3個值,0,1,2請確認一下自已能接受的級別。默認為1,主庫請不要更改了。
性能更高的可以設置為0或是2,但會丟失一秒鍾的事務。
3. 文件IO分配,空間占用方面
innodb_file_per_table=1
作用:使每個Innodb的表,有自已獨立的表空間。如刪除文件后可以回收那部分空間。
分配原則:只有使用不使用。但DB還需要有一個公共的表空間。
innodb_file_io_threads=4
作用:文件讀寫IO數,這個參數只在Windows上起作用。在LINUX上只會等於4
innodb_open_files=1024
作用:限制Innodb能打開的表的數據。
分配原則:如果庫里的表特別多的情況,請增加這個。這個值默認是300。
4. 其它相關參數
這里說明一個比較重要的參數:
innodb_flush_method=O_DIRECT
作用:Innodb和系統打交道的一個IO模型
分配原則:Windows不用設置。
innodb_max_dirty_pages_pct=90
作用:控制Innodb的臟頁在緩沖中在那個百分比之下,值在范圍1-100,默認為90.
這個參數的另一個用處:當Innodb的內存分配過大,致使Swap占用嚴重時,可以適當的減小調整這個值,使達到Swap空間釋放出來。建義:這個值最大在90%,最小在15%。太大,緩存中每次更新需要致換數據頁太多,太小,放的數據頁太小,更新操作太慢。
動態更改需要有Super權限:
set global innodb_max_dirty_pages_pct=50;
附一個真實環境MySQL配置my.cnf內容,可以根據實際情況修改:
[client] port = 3306 socket = /tmp/mysql.sock [mysqld] user = mysql server_id = 10 port = 3306 socket = /tmp/mysql.sock datadir = /data/mysql/data1 old_passwords = 1 lower_case_table_names = 1 character-set-server = utf8 default-storage-engine = INNODB log-bin = bin.log log-error = error.log pid-file = /tmp/mysql.pid long_query_time = 2 slow_query_log = 'on' slow_query_log_file = /data/mysql/data1/slow.log binlog_cache_size = 4M binlog_format = mixed max_binlog_cache_size = 16M max_binlog_size = 1G expire_logs_days = 30 ft_min_word_len = 4 back_log = 512 max_allowed_packet = 64M max_connections = 4096 max_connect_errors = 100 join_buffer_size = 2M read_buffer_size = 2M read_rnd_buffer_size = 2M sort_buffer_size = 2M query_cache_size = 64M table_open_cache = 10000 thread_cache_size = 256 max_heap_table_size = 64M tmp_table_size = 64M thread_stack = 192K thread_concurrency = 24 local-infile = 0 skip-show-database skip-name-resolve skip-external-locking connect_timeout = 600 interactive_timeout = 600 wait_timeout = 600 #*** MyISAM key_buffer_size = 512M bulk_insert_buffer_size = 64M myisam_sort_buffer_size = 64M myisam_max_sort_file_size = 1G myisam_repair_threads = 1 concurrent_insert = 2 myisam_recover #*** INNODB innodb_buffer_pool_size = 16G innodb_additional_mem_pool_size = 32M innodb_data_file_path = ibdata1:1G;ibdata2:1G:autoextend innodb_read_io_threads = 8 innodb_write_io_threads = 8 innodb_file_per_table = 1 innodb_flush_log_at_trx_commit = 2 innodb_lock_wait_timeout = 120 innodb_log_buffer_size = 8M innodb_log_file_size = 256M innodb_log_files_in_group = 3 innodb_max_dirty_pages_pct = 90 innodb_thread_concurrency = 16 innodb_open_files = 1024 read-only relay-log = relay.log log-slave-updates [mysqld_safe] |
下面是實驗虛擬機得mysql參數配置 在真實企業里 以實際優化參數來配置
Master主:
[client] port = 3306 default-character-set=utf8 (字符集) [mysqld] datadir=/usr/local/mysql/data socket=/usr/local/mysql/mysql.sock user=mysql character-set-server=utf8 symbolic-links=0 open_files_limit = 102400 max_connections=2000 skip-name-resolve #skip-grant-tables slow_query_log = 'on' long_query_time=2 (超過2秒的記錄在慢查詢) slow_query_log_file=/usr/local/mysql/mysql-slow.log (慢查詢日志目錄) tmp_table_size=256M key_buffer_size=512M read_buffer_size=32M sort_buffer_size=32M query_cache_limit=1M query_cache_size=16M default-storage-engine=INNODB (這里只設置默認mysql引擎) innodb_buffer_pool_size=4G innodb_buffer_pool_instances=8 innodb_log_file_size=10M innodb_log_buffer_size=8M innodb_lock_wait_timeout=50 innodb_file_per_table=OFF innodb_flush_log_at_trx_commit=2 server-id = 1 log-bin=mysql-bin (開啟bin-log日志) log-slave-updates binlog_cache_size = 4M binlog_format = mixed max_binlog_cache_size = 1G max_binlog_size = 1G auto_increment_offset=1 auto_increment_increment=2 [mysqld_safe] log-error=/var/log/mysqld.log pid-file=/usr/local/mysql/data/mysqld.pid replicate-do-db =all |
slave 從:
[client] port = 3306 default-character-set=utf8 (字符集) [mysqld] datadir=/usr/local/mysql/data socket=/usr/local/mysql/mysql.sock user=mysql character-set-server=utf8 symbolic-links=0 open_files_limit = 102400 max_connections=2000 skip-name-resolve #skip-grant-tables slow_query_log = 'on' long_query_time=2 (超過2秒的記錄在慢查詢) slow_query_log_file=/usr/local/mysql/mysql-slow.log (慢查詢日志目錄) tmp_table_size=256M key_buffer_size=512M read_buffer_size=32M sort_buffer_size=32M query_cache_limit=1M query_cache_size=16M default-storage-engine=INNODB (這里只設置默認mysql引擎) innodb_buffer_pool_size=4G innodb_buffer_pool_instances=8 innodb_log_file_size=10M innodb_log_buffer_size=8M innodb_lock_wait_timeout=50 innodb_file_per_table=OFF innodb_flush_log_at_trx_commit=2 server-id = 2 log-bin=mysql-bin (開啟bin-log日志) log-slave-updates binlog_cache_size = 4M binlog_format = mixed max_binlog_cache_size = 1G max_binlog_size = 1G auto_increment_offset=1 auto_increment_increment=2 [mysqld_safe] log-error=/var/log/mysqld.log pid-file=/usr/local/mysql/data/mysqld.pid replicate-do-db =all |