1. 程式人生 > >mysql之基礎知識整理

mysql之基礎知識整理

MySQL複製原理

三個程序,兩種檔案。 
binlog dump、IO thread、SQL thread 
binlog 、relay log 
以下圖片擷取自《高效能MySQL》 
 
 這裡寫圖片描述

這裡寫圖片描述


binlog日誌格式的種類和優缺點

有三種格式:statement、mixed、row

1.statement:將修改資料的SQL記錄在binlog中。 
優點: 
不需要記錄每一行的變化,減少了binlog日誌量,節約了IO,提高效能。 
缺點: 
由於記錄的只是執行語句,為了這些語句能在slave上正確執行,因此還必須記錄每條語句在執行的時候的一些相關資訊,以保證所有語句能在slave得到和在master端執行時候相同的結果。 
另外mysql 的複製,像一些特定函式功能,slave可與master上要保持一致會有很多相關問題(如sleep()函式, last_insert_id(),以及user-defined functions(udf)會出現問題)。

2.row:不記錄sql語句上下文相關資訊,僅儲存哪條記錄被修改。 
優點:  
binlog中可以不記錄執行的sql語句的上下文相關的資訊,僅需要記錄那一條記錄被修改成什麼了。所以row level的日誌內容會非常清楚的記錄下每一行資料修改的細節。而且不會出現某些特定情況下的儲存過程,或function,以及trigger的呼叫和觸發無法被正確複製的問題 
缺點: 
所有的執行的語句當記錄到日誌中的時候,都將以每行記錄的修改來記錄,這樣可能會產生大量的日誌內容,比如一條update語句,修改多條記錄,則binlog中每一條修改都會有記錄,這樣造成binlog日誌量會很大,特別是當執行alter table之類的語句的時候,由於表結構修改,每條記錄都發生改變,那麼該表每一條記錄都會記錄到日誌中。

3.Mixed:是以上兩種level的混合使用,一般的語句修改使用statment格式儲存binlog,如一些函式,statement無法完成主從複製的操作,則採用row格式儲存binlog,MySQL會根據執行的每一條具體的sql語句來區分對待記錄的日誌形式,也就是在Statement和Row之間選擇一種。

新版本的MySQL中對row level模式也被做了優化,並不是所有的修改都會以row level來記錄,像遇到表結構變更的時候就會以statement模式來記錄。至於update或者delete等修改資料的語句,還是會記錄所有行的變更。

補充: 
expire_logs_days= 7                       //binlog過期清理時間 
max_binlog_size=100m                    //binlog每個日誌檔案大小 
sync_binlog

 

innodb事務與日誌的實現

參考《MySQL技術內幕 Innodb儲存引擎 》

Write-Ahead Logging ,WAL:預寫日誌方式 
 【1】Redo Log 
 在Innodb儲存引擎中,事務日誌是通過redo和innodb的儲存引擎日誌緩衝(Innodb log buffer)來實現的。 
當開始一個事務的時候,會記錄該事務的lsn(log sequence number)號;當事務執行時,會往InnoDB儲存引擎的日誌的日誌快取裡面插入事務日誌;當事務提交時,必須將儲存引擎的日誌緩衝寫入磁碟(通過innodb_flush_log_at_trx_commit來控制),也就是寫資料前,需要先寫日誌。 
這種方式稱為“預寫日誌方式”,innodb通過此方式來保證事務的完整性。也就意味著磁碟上儲存的資料頁和記憶體緩衝池上面的頁是不同步的,是先寫入redo log,然後寫入data file,因此是一種非同步的方式。通過 show engine innodb status\G 來觀察之間的差距。

innodb_log_group_home_dir=/dbdata/iblogs 
innodb_log_files_in_group=3 
innodb_log_file_size=50M    

【2】Undo  
undo的記錄正好與redo的相反,insert變成delete,update變成相反的update,redo放在redo file裡面。而undo放在一個內部的一個特殊segment上面,儲存與共享表空間內(ibdata1或者ibdata2中)。 
undo不是物理恢復,是邏輯恢復,因為它是通過執行相反的dml語句來實現的。而且不會回收因為insert和upate而新增加的page頁的。 
undo頁的回收是通過master thread執行緒來實現的。

在MySQL5.6中開始支援把undo log分離到獨立的表空間,並放到單獨的檔案目錄下;這給我們部署不同IO型別的檔案位置帶來便利,對於併發寫入型負載,我們可以把undo檔案部署到單獨的高速儲存裝置上。

innodb_undo_tablespaces:用於設定建立的undo表空間的個數,在Install db時初始化後,就再也不能被改動了;預設值為0,表示不獨立設定undo的tablespace,預設記錄到ibdata中;否則,則在undo目錄下建立這麼多個undo檔案,例如假定設定該值為16,那麼就會建立命名為undo001~undo016的undo tablespace檔案,每個檔案的預設大小為10M。

innodb_undo_logs:用於表示回滾段的個數(早期版本的命名為innodb_rollback_segments),該變數可以動態調整,但是物理上的回滾段不會減少,只是會控制用到的回滾段的個數。

innodb_undo_directory:當開啟獨立undo表空間時,指定undo檔案存放的目錄。如果我們想轉移undo檔案的位置,只需要修改下該配置,並將undo檔案拷貝過去就可以了。

當有長時間執行的事務時,可能導致purge操作來不及回收undo空間,進而導致undo空間急劇膨脹;理論上講,如果做一次乾淨的shutdown,應該可以安全的將將這些undo檔案刪除並重新做一次初始化;也許未來的某個MySQL版本可能實現這個功能,這對於某些服務(比如按磁碟空間收費的雲端計算提供商)是非常有必要的功能。

 

innodb與myisam的索引實現方式

參考文章:http://blog.csdn.net/zuiaituantuan/article/details/5909334

1 MyISAM只把索引載入記憶體,資料快取依賴於作業系統,InnoDB把索引和資料都載入記憶體緩衝 。 
2 MyISAM資料庫中的資料是按照插入的順序儲存,在每個索引節點中儲存對應的資料行的地址,理論上說主鍵索引和其他索引是一樣的,InnoDB資料庫中的資料和主鍵節點儲存在一起,所有其他索引節點中儲存的是主鍵索引的值。  
3 對於字串索引,MyISAM預設採用增量儲存,例如第一個索引值是’perform’,第二個索引的值是’performance’, 在索引檔案中第二個索引被儲存為’7,ance’。這樣能夠減小索引的尺寸。  
4 MyISAM儲存索引的狀態資訊在磁盤裡,每次執行ANALYZE TABLE會更新這個資訊。InnoDB則通過在啟動的時候隨機讀取索引來估計索引的狀態資訊,所以Show Index的結果對於MyISAM是精準的,但對於InnoDB不是絕對精準。  
5 索引長期執行之後會產生碎片,一種碎片是一行資料被儲存在不同的資料段,另一種是連續的表空間或行在磁碟上被分散地儲存。對於MyISAM兩種索引碎片都會出現,對於InnoDB只會出現後一種因為InnoDB不會把短行儲存到不同的資料段。要消除索引碎片一種方法是OPTIMIZE TABLE,另一種方法是把資料重新倒入。 

針對MyISAM和InnoDB不同的索引結構,要注意以下幾點:  
1 在InnoDB表中插入資料一定要儘可能按照主鍵增加的順序,AUTO_INCREMENT最好,這樣插入的速度最快。 
2 因為InnoDB索引節點中儲存的是主鍵的值,所以主鍵的值越簡單越好。 
3 對於InnoDB表,在查詢的時候如果只需要查詢索引列,就不要加入其它列,這樣速度最快。  
索引邏輯結構:左邊為innodb,右邊為myisam。 

這裡寫圖片描述


Seconds_Behind_Master的確切含義

mysql在binlog中會記錄event時間戳。binlog複製到slave節點並通過sql thread應用時,slave節點的時間和binlog中記錄的event的時間戳之間的差就是Seconds_Behind_Master。 
也就是說,如果slave節點系統時間比master節點系統時間晚一個小時,則每次有binlog event從master傳輸到slave並應用時,seconds_behind_master至少為3600。

 

一些MySQL高可用架構方面的言論

關於MySQL-HA,目前有多種解決方案,比如heartbeat、drbd、mmm、共享儲存,但是它們各有優缺點。heartbeat、drbd配置較為複雜,需要自己寫指令碼才能實現MySQL自動切換,對於不會指令碼語言的人來說,這無疑是一種腦裂問題;對於mmm,生產環境中很少有人用,且mmm 管理端需要單獨執行一臺伺服器上,要是想實現高可用,就得對mmm管理端做HA,這樣無疑又增加了硬體開支;對於共享儲存,個人覺得MySQL資料還是放在本地較為安全,儲存裝置畢竟存在單點隱患。使用MySQL雙master+keepalived是一種非常好的解決方案,在MySQL-HA環境中,MySQL互為主從關係,這樣就保證了兩臺MySQL資料的一致性,然後用keepalived實現虛擬IP,通過keepalived自帶的服務監控功能來實現MySQL故障時自動切換。

 

MySQL 高可用架構之MMM

簡介

MMM(Master-Master replication manager for MySQL)是一套支援雙主故障切換和雙主日常管理的指令碼程式。MMM使用Perl語言開發,主要用來監控和管理MySQL Master-Master(雙主)複製,雖然叫做雙主複製,但是業務上同一時刻只允許對一個主進行寫入,另一臺備選主上提供部分讀服務,以加速在主主切換時刻備選主的預熱,可以說MMM這套指令碼程式一方面實現了故障切換的功能,另一方面其內部附加的工具指令碼也可以實現多個slave的read負載均衡。

MMM提供了自動和手動兩種方式移除一組伺服器中複製延遲較高的伺服器的虛擬ip,同時它還可以備份資料,實現兩節點之間的資料同步等。由於MMM無法完全的保證資料一致性,所以MMM適用於對資料的一致性要求不是很高,但是又想最大程度的保證業務可用性的場景。對於那些對資料的一致性要求很高的業務,非常不建議採用MMM這種高可用架構。

總結: 
MMM不適用於對資料一致性要求很高的環境。但是高可用完全做到了。

詳細搭建及配置等請移步:(非常好的文章) 
http://www.tuicool.com/articles/qQVN3yA

 

MySQL高可用架構之MM+Keepalived

具體環境搭建步驟請移步: 
lvs+keepalived+mha+mysql高可用架構配置說明 
http://www.chocolee.cn/archives/276

KeepAlived + mysqlMM高可用 安裝配置 
 http://blog.chinaunix.net/uid-25135004-id-3807798.html

 

批量MySQL資料庫管理經驗

實際線上的mysql資料庫數量有多少?分多少個節點組? 
這些節點組上面的slow log是如何組合在一起來統計分析的? 
現在手上有600臺數據庫,新來的機器,Mysql都安裝好了,那麼你如何在最快的時間裡面把這600臺mysql資料庫的mysqld服務啟動起來?這個重點在於最快的時間。

 

SQL優化的思路及基本原則

SQL優化的思路: 
 1.優化更需要優化的sql; 
 2.定位優化物件的效能瓶頸:優化前需瞭解查詢的瓶頸是IO還是CPU,可通過PROFILING很容易定位查詢的瓶頸。 
 3.明確優化目標; 
 4.從Explain入手; 
 5.多使用profile; 
​ 
SQL優化的基本原則: 
 1.永遠用小結果集驅動大結果集; 
    From子句中sql解析順序為從右向左,執行時會以最左邊的表為基礎表迴圈與右邊表資料做笛卡爾積,所以以小結果集驅動能減少迴圈次數,從而減少對被驅動結果集的訪問,從而減少被驅動表的鎖定。 
 2.儘可能在索引中完成排序; 
    排序演算法有兩種:a.查出排序欄位和行指標,排序,再通過行指標獲得行資料所需列,返回結果集;b.取出所有排序列資料,在排序緩衝區中排完序直接返回結果集。 
    索引排序是利用索引的有序性對資料排序的。 
 3.只取出子集需要的colums 
 4.僅僅使用最有效的過濾條件; 
 5.儘可能避免複雜的Join和子查詢;

索引的好處: 
(1).提高資料檢索效率,降低資料庫的IO成本。 
(2).降低資料排序成本:要求排序欄位和索引鍵欄位一致。 
(3).降低資料分組成本:因為分組之前會先排序,同意如果分組欄位與索引欄位一致,會降低分組消耗的成本。 
索引的弊端: 
(1).索引是獨立於基礎資料的資料庫物件,因此它會佔用儲存空間。 
(2).資料新增、更新會導致索引的同步更新,所以會增加資料新增、更新所消耗的成本。 
判斷是否需要建立索引: 
(1).較為頻繁的作為查詢條件的欄位需要建立索引; 
(2). 唯一性太差的欄位不適合單獨建立索引,即使頻繁作為查詢條件; 
(3).更新非常頻繁的欄位不適合建立索引; 
(4).不會出現在where子句中的欄位不要建立索引;

索引語法: 
(1).唯一索引 
     ALTER TABLE tableName ADD UNIQUE indexName (column); 
     CREATE UNIQUE INDEX indexName ON tableName (column); 
(2).普通索引 
     ALTER TABLE tableName ADD INDEX indexName(column); 
     CREATE INDEX indexName ON tableName(column); 
(3).主鍵索引 
     ALTER TABLE tableName ADD PRIMARY KEY (column); 
(4).全文索引 
     ALTER TABLE tableName ADD FULLTEXT (column); 
(5).組合索引 
     ALTER TABLE tableName ADD INDEX indexName(col1,col2,…);

 

MySQL explain的各種引數

參考自己的部落格: 
mysql explain 輸出詳解 
http://blog.csdn.net/lijingkuan/article/details/50462372

對mysql explain講的比較清楚的(轉) 
http://blog.csdn.net/lijingkuan/article/details/50432680

 

MySQL explain中的file sort含義及出現場景

在使用order by關鍵字的時候,如果待排序的內容不能由所使用的索引直接完成排序的話,那麼mysql有可能就要進行檔案排序。

【這個 filesort 並不是說通過磁碟檔案進行排序,而只是告訴我們進行了一個排序操作而已】。

當然,using filesort不一定引起mysql的效能問題。但是如果查詢次數非常多,那麼每次在mysql中進行排序,還是會有影響的。 
此時,可以進行的優化: 
1、修改邏輯,不在mysql中使用order by而是在應用中自己進行排序。 
2、使用mysql索引,將待排序的內容放到索引中,直接利用索引的排序。

詳情參考: 
http://blog.csdn.net/imzoer/article/details/8485680

 

MySQL explain中的using temporary含義及出現場景

有待整理

 

MySql中explain之後,type欄位和Extra欄位中的index區別

一個查詢語句經過explain之後,type欄位可能會出現index,Extra中可能會出現using index。

那麼二者有什麼區別呢?他們是迥然不同的。

type中的index,僅僅是說,查詢型別index,表示本次查詢僅僅掃描索引樹,沒有其他讀取操作。

Extra中的using index,意思是說,查詢使用到了“覆蓋索引”。

詳情參考: 
http://blog.csdn.net/imzoer/article/details/8533929

 

MySQL profile

參考: 
mysql使用profile分析語句效能消耗  
http://blog.itpub.net/29371470/viewspace-1355948/

 

關於資料型別

以下圖片擷取自《高效能MySQL》 
整數型別 
 
 
字元型別 
 
BLOB&TEXT 
 

 


MySQL部分配置引數介紹

非快取引數變數

back_log 
back_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆疊中。也就是說,如果MySql的連線資料達到max_connections時,新來的請求將會被存在堆疊中,以等待某一連線釋放資源,該堆疊的數量即back_log,如果等待連線的數量超過back_log,將不被授予連線資源。將會報: 
unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL  
的等待連線程序時。(這個現象在通過DNS解析連線的時候也出現過。) 
back_log值不能超過TCP/IP連線的偵聽佇列的大小。若超過則無效,檢視當前系統的TCP/IP連線的偵聽佇列的大小命令:

 

cat /proc/sys/net/ipv4/tcp_max_syn_backlog1

目前系統為1024。 
對於Linux系統推薦設定為小於512的整數。 
修改系統核心引數http://www.51testing.com/html/64/n-810764.html 
檢視mysql 當前系統預設back_log值,命令:

 

show variables like 'back_log'; 1

wait_timeout 
我對wait-timeout這個引數的理解: 
MySQL客戶端的資料庫連線閒置最大時間值。 
說得比較通俗一點,就是當你的MySQL連線閒置超過一定時間後將會被強行關閉。 
MySQL預設的wait-timeout  值為8個小時,可以通過命令show variables like 'wait_timeout'檢視結果值。 
設定這個值是非常有意義的,比如你的網站有大量的MySQL連結請求(每個MySQL連線都是要記憶體資源開銷的 ),由於你的程式的原因有大量的連線請求空閒啥事也不幹,白白佔用記憶體資源,或者導致MySQL超過最大連線數從來無法新建連線導致“Too many connections”的錯誤。在設定之前你可以檢視一下你的MYSQL的狀態(可用show processlist),如果經常發現MYSQL中有大量的Sleep程序,則需要 修改wait-timeout值了。 
擴充套件:interactive_timeout,wait_timeout

max_connections 
max_connections是指MySql的最大連線數,如果伺服器的併發連線請求量比較大,建議調高此值,以增加並行連線數量,當然這建立在機器能支撐的情況下,因為如果連線數越多,介於MySql會為每個連線提供連線緩衝區,就會開銷越多的記憶體,所以要適當調整該值,不能盲目提高設值。可以過’conn%’萬用字元檢視當前狀態的連線數量,以定奪該值的大小。 
MySQL伺服器允許的最大連線數16384; 
檢視系統當前最大連線數:

 

show variables like 'max_connections';1

max_user_connections 
max_user_connections是指每個資料庫使用者的最大連線。 
針對某一個賬號的所有客戶端並行連線到MYSQL服務的最大並行連線數。 
簡單說是指同一個賬號能夠同時連線到mysql服務的最大連線數。 
設定為0表示不限制。目前預設值為:0不受限制。 
這兒順便介紹下Max_used_connections:它是指從這次mysql服務啟動到現在,同一時刻並行連線數的最大值。它不是指當前的連線情況,而是一個比較值。如果在過去某一個時刻,MYSQL服務同時有1000個請求連線過來,而之後再也沒有出現這麼大的併發請求時,則Max_used_connections=1000。請注意與show variables 裡的max_user_connections的區別。預設為0表示無限大。 
檢視max_user_connections值

 

show variables like 'max_user_connections';1

thread_concurrency 
thread_concurrency的值的正確與否, 對mysql的效能影響很大。 
在多個cpu(或多核)的情況下,錯誤設定了thread_concurrency的值, 會導致mysql不能充分利用多cpu(或多核), 出現同一時刻只能一個cpu(或核)在工作的情況。 
thread_concurrency應設為CPU核數的2倍。比如有一個雙核的CPU, 那thread_concurrency  的應該為4; 2個雙核的cpu, thread_concurrency的值應為8. 
比如:根據上面介紹我們目前系統的配置,可知道為4個CPU,每個CPU為8核,按照上面的計算規則,這兒應為:4*8*2=64 
檢視系統當前thread_concurrency預設配置命令:

 

show variables like 'thread_concurrency';1

skip-name-resolve 
禁止MySQL對外部連線進行DNS解析,使用這一選項可以消除MySQL進行DNS解析的時間。 
但需要注意,如果開啟該選項,則所有遠端主機連線授權都要使用IP地址方式,否則MySQL將無法正常處理連線請求!(主機名連線方式就不能用了。)

skip-networking 
建議被註釋掉,不要開啟。 
開啟該選項可以徹底關閉MySQL的TCP/IP連線方式,如果WEB伺服器是以遠端連線的方式訪問MySQL資料庫伺服器則不要開啟該選項!否則將無法正常連線!

 

快取引數優化

資料庫屬於IO密集型的應用程式,其主職責就是資料的管理及儲存工作。而我們知道,從記憶體中讀取一個數據庫的時間是微秒級別,而從一塊普通硬碟上讀取一個 IO是在毫秒級別,二者相差3個數量級。所以,要優化資料庫,首先第一步需要優化的就是IO,儘可能將磁碟IO轉化為記憶體IO。本文先從MySQL資料庫 IO相關引數(快取引數)的角度來看看可以通過哪些引數進行IO優化。

 

全域性快取

啟動MySQL時就要分配並且總是存在的全域性快取。目前有:key_buffer_size(預設值:402653184,即384M) 
innodb_buffer_pool_size(預設值:134217728即:128M) 
innodb_additional_mem_pool_size(預設值:8388608即:8M) 
innodb_log_buffer_size(預設值:8388608即:8M) 
query_cache_size(預設值:33554432即:32M)等五個。 
總共:560M。 
這些變數值都可以通過命令如:show variables like '變數名';檢視到。

key_buffer_size 
key_buffer_size是用於索引塊的緩衝區大小,增加它可得到更好處理的索引(對所有讀和多重寫),對MyISAM(MySQL表儲存的一種型別,可以百度等檢視詳情)表效能影響最大的一個引數。 
如果你使它太大,系統將開始換頁並且真的變慢了。嚴格說是它決定了資料庫索引處理的速度,尤其是索引讀的速度。對於記憶體在4GB左右的伺服器該引數可設定為256M或384M. 
怎麼才能知道key_buffer_size的設定是否合理呢,一般可以檢查狀態值Key_read_requests和Key_reads   ,比例key_reads / key_read_requests應該儘可能的低,比如1:100,1:1000 ,1:10000。 
其值可以用以下命令查得:show status like 'key_read%'; 
比如檢視系統當前key_read和key_read_request值為: 
+——————-+——-+ 
| Variable_name      | Value | 
+——————-+——-+ 
| Key_read_requests | 28535 | 
| Key_reads               | 269     | 
+——————-+——-+ 
可知道有28535個請求,有269個請求在記憶體中沒有找到直接從硬碟讀取索引。 
未命中快取的概率為:0.94%=269/28535*100%。一般未命中概率在0.1之下比較好。目前已遠遠大於0.1,證明效果不好。若命中率在0.01以下,則建議適當的修改key_buffer_size值。

innodb_buffer_pool_size 
主要針對InnoDB表效能影響最大的一個引數。功能與Key_buffer_size一樣。InnoDB佔用的記憶體,除innodb_buffer_pool_size用於儲存頁面快取資料外,另外正常情況下還有大約8%的開銷,主要用在每個快取頁幀的描述、adaptive hash等資料結構,如果不是安全關閉,啟動時還要恢復的話,還要另開大約12%的記憶體用於恢復,兩者相加就有差不多21%的開銷。假設:12G的innodb_buffer_pool_size,最多的時候InnoDB就可能佔用到14.5G的記憶體。若系統只有16G,而且只執行MySQL,且MySQL只用InnoDB,那麼為MySQL開12G,是最大限度地利用記憶體了。 
另外InnoDB和 MyISAM 儲存引擎不同, MyISAM 的 key_buffer_size 只能快取索引鍵,而 innodb_buffer_pool_size 卻可以快取資料塊和索引鍵。適當的增加這個引數的大小,可以有效的減少 InnoDB 型別的表的磁碟 I/O 。 
當我們操作一個 InnoDB 表的時候,返回的所有資料或者取資料過程中用到的任何一個索引塊,都會在這個記憶體區域中走一遭。 
可以通過 

 

(Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 1

計算快取命中率,並根據命中率來調整 innodb_buffer_pool_size 引數大小進行優化。 
值可以用以下命令查得:show status like 'Innodb_buffer_pool_read%'; 
比如檢視當前系統中系統中 
| Innodb_buffer_pool_read_requests      | 1283826 | 
| Innodb_buffer_pool_reads              | 519     | 
+—————————————+———+ 
其命中率99.959%=(1283826-519)/1283826*100%  命中率越高越好。

innodb_additional_mem_pool_size 
設定了InnoDB儲存引擎用來存放資料字典資訊以及一些內部資料結構的記憶體空間大小,所以當我們一個MySQL Instance中的資料庫物件非常多的時候,是需要適當調整該引數的大小以確保所有資料都能存放在記憶體中提高訪問效率的。 
這個引數大小是否足夠還是比較容易知道的,因為當過小的時候,MySQL會記錄Warning資訊到資料庫的error log中,這時候你就知道該調整這個引數大小了。 
檢視當前系統mysql的error日誌  cat  /var/lib/mysql/機器名.error 發現有很多waring警告。所以要調大為20M。 
根據MySQL手冊,對於2G記憶體的機器,推薦值是20M。32G記憶體的 100M。

innodb_log_buffer_size 
這是InnoDB儲存引擎的事務日誌所使用的緩衝區。類似於Binlog Buffer,InnoDB在寫事務日誌的時候,為了提高效能,也是先將資訊寫入Innodb Log Buffer中,當滿足innodb_flush_log_trx_commit引數所設定的相應條件(或者日誌緩衝區寫滿)之後,才會將日誌寫到檔案 (或者同步到磁碟)中。可以通過innodb_log_buffer_size 引數設定其可以使用的最大記憶體空間。 
   InnoDB 將日誌寫入日誌磁碟檔案前的緩衝大小。理想值為 1M 至 8M。大的日誌緩衝允許事務執行時不需要將日誌儲存入磁碟而只到事務被提交(commit)。 因此,如果有大的事務處理,設定大的日誌緩衝可以減少磁碟I/O。 在 my.cnf中以數字格式設定。 
預設是8MB,頻繁的系統可適當增大至4MB~8MB。當然如上面介紹所說,這個引數實際上還和另外的flush引數相關。一般來說不建議超過32MB 
注:innodb_flush_log_trx_commit引數對InnoDB Log的寫入效能有非常關鍵的影響,預設值為1。該引數可以設定為0,1,2,解釋如下: 
0:log buffer中的資料將以每秒一次的頻率寫入到log file中,且同時會進行檔案系統到磁碟的同步操作,但是每個事務的commit並不會觸發任何log buffer 到log file的重新整理或者檔案系統到磁碟的重新整理操作; 
1:在每次事務提交的時候將log buffer 中的資料都會寫入到log file,同時也會觸發檔案系統到磁碟的同步; 
2:事務提交會觸發log buffer到log file的重新整理,但並不會觸發磁碟檔案系統到磁碟的同步。此外,每秒會有一次檔案系統到磁碟同步操作。 
實際測試發現,該值對插入資料的速度影響非常大,設定為2時插入10000條記錄只需要2秒,設定為0時只需要1秒,而設定為1時則需要229秒。因此,MySQL手冊也建議儘量將插入操作合併成一個事務,這樣可以大幅提高速度。根據MySQL手冊,在存在丟失最近部分事務的危險的前提下,可以把該值設為0。

query_cache_size 
主要用來快取MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。當我們打開了 Query Cache功能,MySQL在接受到一條select語句的請求後,如果該語句滿足Query Cache的要求(未顯式說明不允許使用Query Cache,或者已經顯式申明需要使用Query Cache),MySQL會直接根據預先設定好的HASH演算法將接受到的select語句以字串方式進行hash,然後到Query Cache中直接查詢是否已經快取。也就是說,如果已經在快取中,該select請求就會直接將資料返回,從而省略了後面所有的步驟(如SQL語句的解析,優化器優化以及向儲存引擎請求資料等),極大的提高效能。根據MySQL使用者手冊,使用查詢緩衝最多可以達到238%的效率。 
當然,Query Cache也有一個致命的缺陷,那就是當某個表的資料有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的快取資料失效。所以,當我們的資料變化非常頻繁的情況下,使用Query Cache可能會得不償失。 
   Query Cache的使用需要多個引數配合,其中最為關鍵的是query_cache_size和query_cache_type,前者設定用於快取 ResultSet的記憶體大小,後者設定在何場景下使用Query Cache。在以往的經驗來看,如果不是用來快取基本不變的資料的MySQL資料庫,query_cache_size一般256MB是一個比較合適的大小。當然,這可以通過計算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))來進行調整。 query_cache_type可以設定為0(OFF),1(ON)或者2(DEMOND),分別表示完全不使用query cache,除顯式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有顯示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes(該引數記錄有多少條查詢因為記憶體不足而被移除出查詢快取。通過這個值,使用者可以適當的調整快取大小。 )的值非常大,則表明經常出現緩衝. 如果Qcache_hits的值也非常大,則表明查詢緩衝使用非常頻繁,此時需要增加緩衝大小; 
根據命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進行調整,一般不建議太大,256MB可能已經差不多了,大型的配置型靜態資料可適當調大. 
可以通過命令:show status like ‘Qcache_%’;檢視目前系統Query cache使用大小 
| Qcache_hits             | 1892463  | 
| Qcache_inserts          | 35627 
命中率98.17%=1892463/(1892463 +35627 )*100

 

區域性快取

除了全域性緩衝,MySql還會為每個連線發放連線緩衝。每個連線到MySQL伺服器的執行緒都需要有自己的緩衝。大概需要立刻分配256K,甚至線上程空閒時,它們使用預設的執行緒堆疊,網路快取等。 
事務開始之後,則需要增加更多的空間。 
執行較小的查詢可能僅給指定的執行緒增加少量的記憶體消耗,然而如果對資料表做複雜的操作例如掃描、排序或者需要臨時表,則需分配大約read_buffer_size,sort_buffer_size,read_rnd_buffer_size,tmp_table_size 大小的記憶體空間。 
不過它們只是在需要的時候才分配,並且在那些操作做完之後就釋放了。有的是立刻分配成單獨的組塊。tmp_table_size 可能高達MySQL所能分配給這個操作的最大記憶體空間了。 
注意,這裡需要考慮的不只有一點——可能會分配多個同一種類型的快取,例如用來處理子查詢。 
一些特殊的查詢的記憶體使用量可能更大——如果在MyISAM表上做成批的插入時需要分配 bulk_insert_buffer_size 大小的記憶體;執行 ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLE 命令時需要分配 myisam_sort_buffer_size 大小的記憶體。

read_buffer_size 
read_buffer_size 是MySql讀入緩衝區大小。 
對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會為它分配一段記憶體緩衝區。read_buffer_size變數控制這一緩衝區的大小。 
如果對錶的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變數值以及記憶體緩衝區大小提高其效能。

sort_buffer_size 
sort_buffer_size是MySql執行排序使用的緩衝大小。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試增加sort_buffer_size變數的大小。

read_rnd_buffer_size 
read_rnd_buffer_size 是MySql的隨機讀緩衝區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀快取區。 
進行排序查詢時,MySql會首先掃描一遍該緩衝,以避免磁碟搜尋,提高查詢速度,如果需要排序大量資料,可適當調高該值。但MySql會為每個客戶連線發放該緩衝空間,所以應儘量適當設定該值,以避免記憶體開銷過大。

tmp_table_size 
tmp_table_size是MySql的heap(堆積)表緩衝大小。 
所有聯合在一個DML指令內完成,並且大多數聯合甚至可以不用臨時表即可以完成。大多數臨時表是基於記憶體的(HEAP)表。具有大的記錄長度的臨時表 (所有列的長度的和)或包含BLOB列的表儲存在硬碟上。 
如果某個內部heap(堆積)表大小超過tmp_table_size,MySQL可以根據需要自動將記憶體中的heap表改為基於硬碟的MyISAM表。 
還可以通過設定tmp_table_size選項來增加臨時表的大小。也就是說,如果調高該值,MySql同時將增加heap表的大小,可達到提高聯接查詢速度的效果。

record_buffer 
record_buffer每個進行一個順序掃描的執行緒為其掃描的每張表分配這個大小的一個緩衝區。如果你做很多順序掃描,你可能想要增加該值。預設數值是131072(128K)。

 

其他快取

TABLE_CACHE 
(5.1.3及以後版本又名TABLE_OPEN_CACHE) 
存放當前已經開啟的表控制代碼。 
table_cache指定表快取記憶體的大小。(所有執行緒的總和) 
每當MySQL訪問一個表時,如果在表緩衝區中還有空間,該表就被開啟並放入其中,這樣可以更快地訪問表內容。 
通過檢查峰值時間的狀態值Open_tables和Opened_tables,可以決定是否需要增加table_cache的值。如果你發現open_tables等於table_cache,並且opened_tables在不斷增長,那麼你就需要增加table_cache的值了(上述狀態值可以使用SHOW STATUS LIKE ‘Open%tables’獲得)。 
注意,不能盲目地把table_cache設定成很大的值。如果設定得太高,可能會造成檔案描述符不足,從而造成效能不穩定或者連線失敗。

 

SHOW STATUS LIKE 'Open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 356   |
| Opened_tables | 0     |
+---------------+-------+
2 rows in set (0.00 sec)12345678

open_tables表示當前開啟的表快取數,如果執行flush tables操作,則此係統會關閉一些當前沒有使用的表快取而使得此狀態值減小; 
opend_tables表示曾經開啟的表快取數,會一直進行累加,如果執行flush tables操作,值不會減小。 
在mysql預設安裝情況下,table_cache的值在2G記憶體以下的機器中的值預設時256到512,如果機器有4G記憶體,則預設這個值 是2048,但這決意味著機器記憶體越大,這個值應該越大,因為table_cache加大後,使得mysql對SQL響應的速度更快了,不可避免的會產生 更多的死鎖(dead lock),這樣反而使得資料庫整個一套操作慢了下來,嚴重影響效能。所以平時維護中還是要根據庫的實際情況去作出判斷,找到最適合你維護的庫的 table_cache值。 
由於MySQL是多執行緒的機制,為了提高效能,每個執行緒都是獨自開啟自己需要的表的檔案描述符,而不是通過共享已經開啟的。 
針對不同儲存引擎處理的方法當然也不一樣: 
在myisam表引擎中,資料檔案的描述符 (descriptor)是不共享的,但是索引檔案的描述符卻是所有執行緒共享的。 
Innodb中和使用表空間型別有關,假如是共享表空間那麼實際就一個數據檔案,當然佔用的資料檔案描述符就會比獨立表空間少。 
mysql手冊上給的建議大小 是:table_cache=max_connections*n 
n表示查詢語句中最大表數, 還需要為臨時表和檔案保留一些額外的檔案描述符。 
這個資料遭到很多質疑,table_cache夠用就好,檢查 Opened_tables值,如果這個值很大,或增長很快那麼你就得考慮加大table_cache了. 
table_cache:所有執行緒開啟的表的數目。增大該值可以增加mysqld需要的檔案描述符的數量。預設值是64。

thread_cache_size 
預設的thread_cache_size=8,但是看到好多配置的樣例裡的值一般是32,64,甚至是128,感覺這個引數對優化應該有幫助,於是查了下: 
根據調查發現以上伺服器執行緒快取thread_cache_size沒有進行設定,或者設定過小,這個值表示可以重新利用儲存在快取中執行緒的數量,當斷開連線時如果快取中還有空間,那麼客戶端的執行緒將被放到快取中。如果執行緒重新被請求,那麼請求將從快取中讀取。如果快取中是空的或者是新的請求,那麼這個執行緒將被重新建立。如果有很多新的執行緒,增加這個值可以改善系統性能。 
通過比較 Connections 和 Threads_created 狀態的變數,可以看到這個變數的作用。(–>表示要調整的值)   根據實體記憶體設定規則如下: 
1G —> 8 
2G —> 16 
3G —> 32     >3G —> 64

 

mysql> show status like 'thread%';
| Variable_name     | Value |
| Threads_cached    | 0     |  <—當前被快取的空閒執行緒的數量
| Threads_connected | 1     |  <—正在使用(處於連線狀態)的執行緒
| Threads_created   | 1498  |  <—服務啟動以來,建立了多少個執行緒
| Threads_running   | 1     |  <—正在忙的執行緒(正在查詢資料,傳輸資料等等操作)123456

檢視開機起來資料庫被連線了多少次?

 

mysql> show status like '%connection%';
| Variable_name        | Value |
| Connections          | 1504  | –>服務啟動以來,歷史連線數
| Max_used_connections | 2     |1234

通過連線執行緒池的命中率來判斷設定值是否合適?命中率超過90%以上,設定合理。 
 (Connections -  Threads_created) / Connections * 100 %

Table definition cache 
存放表的定義資訊。是frm檔案在記憶體中的對映。MySQL需要開啟frm檔案,並將其內容初始化為Table Share 物件。這裡存放與儲存引擎無關的,獨立的表定義相關資訊。 
與table_cached是兩個概念完全不同的東西。為什麼MySQL會出現這兩個概念是因為:MySQL支援不同的儲存引擎,每種儲存引擎,資料儲存的格式都是不一樣的,因此需要指定一個儲存引擎相關的handler。這就有了table cache的作用。另外表的定義也需要存放記憶體中,而表的定義frm檔案每個儲存引擎是通用的,需要另外獨立開來,這就有了table definition cache。

 

資料庫隔離級別

SQL標準定義的四個隔離級別為: 
read uncommited 
read committed 
repeatable read 
serializable

Read Uncommitted(讀取未提交內容) 
在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因為它的效能也不比其他級別好多少。讀取未提交的資料,也被稱之為髒讀(Dirty Read)。

Read Committed(讀取提交內容) 
這是大多數資料庫系統的預設隔離級別(但不是MySQL預設的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別也支援所謂的不可重複讀(Nonrepeatable Read),因為同一事務的其他例項在該例項處理其間可能會有新的commit,所以同一select可能返回不同結果。

Repeatable Read(可重讀) 
這是MySQL的預設事務隔離級別,它確保同一事務的多個例項在併發讀取資料時,會看到同樣的資料行。不過理論上,這會導致另一個棘手的問題:幻讀(Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的資料行時,另一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的資料行時,會發現有新的“幻影” 行。InnoDB和Falcon儲存引擎通過多版本併發控制(MVCC,Multiversion Concurrency Control 間隙鎖)機制解決了該問題。注:其實多版本只是解決不可重複讀問題,而加上間隙鎖(也就是它這裡所謂的併發控制)才解決了幻讀問題。

Serializable(可序列化) 
這是最高的隔離級別,它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每個讀的資料行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。

對於不同的事務,採用不同的隔離級別分別有不同的結果。不同的隔離級別有不同的現象。主要有下面3種現在: 
1、髒讀(dirty read):一個事務可以讀取另一個尚未提交事務的修改資料。 
2、非重複讀(nonrepeatable read):在同一個事務中,同一個查詢在T1時間讀取某一行,在T2時間重新讀取這一行時候,這一行的資料已經發生修改,可能被更新了(update),也可能被刪除了(delete)。 
3、幻像讀(phantom read):在同一事務中,同一查詢多次進行時候,由於其他插入操作(insert)的事務提交,導致每次返回不同的結果集。

不同的隔離級別有不同的現象,並有不同的鎖定/併發機制,隔離級別越高,資料庫的併發性就越差,4種事務隔離級別分別表現的現象如下表: 

這裡寫圖片描述


mysql鎖模式

共享鎖 
排它鎖 
意向鎖(表級鎖,在加共享鎖或排它鎖之前,要先獲得意向鎖。)

可以參考:

 

innodb record-level鎖

record lock 
gap lock 
next-key lock

具體加鎖規則參考: 
http://blog.csdn.net/lijingkuan/article/details/50754236

 

MyISAM和Innodb引擎的區別

 

mysqldump以及xtranbackup的實現原理

mysqldump是最簡單的邏輯備份方式。在備份myisam表的時候,如果要得到一致的資料,就需要鎖表,簡單而粗暴。而在備份innodb表 的時候,加上–master-data=1 –single-transaction 選項,在事務開始時刻,記錄下binlog pos點,然後利用mvcc來獲取一致的資料,由於是一個長事務,在寫入和更新量很大的資料庫上,將產生非常多的undo,顯著影響效能,所以要慎用

優點:簡單,可針對單表備份,在全量匯出表結構的時候尤其有用。

缺點:簡單粗暴,單執行緒,備份慢而且恢復慢,跨IDC有可能遇到時區問題

xtrabackup它實際上是物理備份+邏輯備份的組合。在備份 innodb表的時候,它拷貝ibd檔案,並一刻不停的監視redo log的變化,append到自己的事務日誌檔案。在拷貝ibd檔案過程中,ibd檔案本身可能被寫”花”,這都不是問題,因為在拷貝完成後的第一個 prepare階段,Xtrabackup採用類似於innodb崩潰恢復的方法,把資料檔案恢復到與日誌檔案一致的狀態,並把未提交的事務回滾。如果同 時需要備份myisam表以及innodb表結構等檔案,那麼就需要用flush tables with lock來獲得全域性鎖,開始拷貝這些不再變化的檔案,同時獲得binlog位置,拷貝結束後釋放鎖,也停止對redo log的監視。