對於數據庫來講,頻繁的關閉建立鏈接是比較消耗資源的,因此有必要創建 數據庫鏈接池mysql
在寫代碼的時候,一個sql查詢了某兩個字段,而另外一個sql查詢了id字段,則能夠將這sql合併,就能夠減小對數據進行重複檢索。算法
還能夠增長緩存層,使用Mybatis、Hibernate提供的一級二級緩存,或者Redis數據庫來緩存數據sql
(1)利用某種均衡算法,將載荷量分佈在不一樣的服務器上,好比Nginx代理服務器數據庫
(2)利用MySQL主從複製,實現讀寫分離緩存
咱們有一個MySQL的主節點服務器,它會將數據同步到其餘節點的服務器,而且徹底一致,在進行增刪改操做的時候,主節點服務器發生修改,而且同步到子節點服務器,可是在查詢的時候,就不須要經過主節點服務器,直接在子節點進行操做,這樣主從複製讀寫分離就能分解數據庫的壓力。安全
(3)使用分佈式數據庫架構服務器
在MySQL中開啓緩存查詢,當執行徹底相同的SQl語句的同時,服務器就直接在緩存中拿數據,數據被修改緩存就會失效。session
1.服務器收到一個sql數據結構
2.先檢查緩存器中是否有緩存,有的話直接返回結果架構
3.沒有的話要進行解析SQL解析、預處理,再由優化器生成對應的執行計劃
4.MySQL根據優化器生成的執行計劃,調用存儲引擎的API來執行查詢
5.將結果返回給客戶端
1.首先查看數據庫是否支持查詢緩存
show variables like 'have_query_cache';
2.查看數據庫是否開啓了緩存
show variables like 'query_cache_type';
OFF或者0:查詢緩存關閉
ON或者1:查詢緩存打開,符合條件的SQL就會緩存,顯式指定SQL_NO_CACHE不予緩存
DEMAND或者2:查詢緩存按需進行,顯式指定SQL_CACHE的select語句才混緩存
找到mysql的配置文件而後加上,就開啓了,重啓MySQL服務生效
query_cache_type=1
經過查詢語句的執行時間,能夠判斷是否進入了緩存
3.查詢緩存佔用的大小 下面單位是字節 算出來大約是1M
show variables like 'query_cache_size';
4.查看查詢緩存的狀態變量
show status like 'Qcache%';
Qcache_free_blocks:可用的內存快的個數
Qcache_free_memory:可用的內存空間
Qcache_hits:查詢緩存的命中次數
Qcache_inserts:添加到查詢緩存的次數 若是MySQL中沒有操做過緩存這兩個數據爲0
Qcache_lowmem_prunes:內存不足查詢緩存中刪除的次數
Qcache_not_cached:非緩存查詢的次數
Qcache_queries_in_cache:查詢緩存中註冊的查詢數
Qcache_total_blocks : 查詢緩存中的塊總數
5.查詢緩存select選項
能夠在select查詢的時候選擇使用緩存或者不使用緩存
SQL_CATCH:若是查詢緩存已經打開,則緩存查詢結果
SQL_NO_CATCH:服務器不使用查詢緩存 ,不緩存
select SQL_CATCH * from Student;
6.查詢結果緩存失效
(1)SQL語句不相同,這裏就再也不演示了
(2)查詢語句結果不固定,好比查詢當前時間等等 select Now()
(3)沒有使用表的語句
(4)查詢Mysql系統表的時候
(5)在存儲的函數,或者存儲過程當中的查詢
(6)表被更改,增刪改均可以讓表發生更改,刪除表。就會將表的緩存刪除變爲無效
(1)要儘可能將多的內存分配給MySQL
(2)MyISAM存儲引擎依賴操做系統自己的IO,所以若是有MyISAM表就要預留更多的內存給操做系統
(3)排序區和緩存區的內存要合理分配,由於過大的話,併發鏈接較高的時候,就會致使物理內存消耗
存儲引擎使用key_buffer 緩存索引塊,加速myisam索引的讀寫速度。對於myisam表的數據塊,mysql沒有特別的緩存機制,徹底依賴於操做系統的IO緩存。
key_buffer_size決定MyISAM索引塊緩存區的大小,直接影響到MyISAM表的存取效率。能夠在MySQL參數文件中設置key_buffer_size的值,對於通常MyISAM數據庫,建議至少將1/4可用內存分配給key_buffer_size。
在MySQL配置文件中作以下配置:
key_buffer_size=512M
若是須要常常順序掃描myisam表,能夠經過增大read_buffer_size的值來改善性能。但須要注意的是read_buffer_size是每一個session獨佔的,若是默認值設置太大,就會形成內存浪費。
對於須要作排序的myisam表的查詢,如帶有order by子句的sql,適當增長 read_rnd_buffer_size 的值,能夠改善此類的sql性能。但須要注意的是 read_rnd_buffer_size 是每一個session獨佔的,若是默認值設置太大,就會形成內存浪費。
InnoDB用內存區作緩存,用來緩存數據塊和索引塊,所以就要給InnoDB分配過多的緩存,在MySQL配置文件中
該變量決定了 innodb 存儲引擎表數據和索引數據的最大緩存區大小。在保證操做系統及其餘程序有足夠內存可用的狀況下,innodb_buffer_pool_size 的值越大,緩存命中率越高,訪問InnoDB表須要的磁盤I/O 就越少,性能也就越高。
innodb_buffer_pool_size=512M
決定了innodb重作日誌緩存的大小,對於可能產生大量更新記錄的大事務,增長innodb_log_buffer_size的大小,能夠避免innodb在事務提交前就執行沒必要要的日誌寫入磁盤操做。
innodb_log_buffer_size=10M
採用max_connections 控制容許鏈接到MySQL數據庫的最大數量,默認值是 151。若是狀態變量 connection_errors_max_connections 不爲零,而且一直增加,則說明不斷有鏈接請求因數據庫鏈接數已達到容許最大值而失敗,這是能夠考慮增大max_connections 的值。
Mysql 最大可支持的鏈接數,取決於不少因素,包括給定操做系統平臺的線程庫的質量、內存大小、每一個鏈接的負荷、CPU的處理速度,指望的響應時間等。在Linux 平臺下,性能好的服務器,支持 500-1000 個鏈接不是難事,須要根據服務器性能進行評估設定。
show variables like 'max_connection';
back_log 參數控制MySQL監聽TCP端口時設置的積壓請求棧大小。若是MySql的鏈接數達到max_connections時,新來的請求將會被存在堆棧中,以等待某一鏈接釋放資源,該堆棧的數量即back_log,若是等待鏈接的數量超過back_log,將不被授予鏈接資源,將會報錯。5.6.6 版本以前默認值爲 50 , 以後的版本默認爲 50 + (max_connections / 5), 但最大不超過900。
若是須要數據庫在較短的時間內處理大量鏈接請求, 能夠考慮適當增大back_log 的值。
show variables like 'back_log';
該參數用來控制全部SQL語句執行線程可打開表緩存的數量, 而在執行SQL語句時,每個SQL執行線程至少要打開 1 個表緩存。該參數的值應該根據設置的最大鏈接數 max_connections 以及每一個鏈接執行關聯查詢中涉及的表的最大數量來設定 :
max_connections x N ;
show variables like 'table_open_cache';
爲了加快鏈接數據庫的速度,MySQL 會緩存必定數量的客戶服務線程以備重用,經過參數 thread_cache_size 可控制 MySQL 緩存客戶服務線程的數量。
show variables like 'thread_cache_size';
該參數是用來設置InnoDB 事務等待行鎖的時間,默認值是50ms , 能夠根據須要進行動態設置。對於須要快速反饋的業務系統來講,能夠將行鎖的等待時間調小,以免事務長時間掛起; 對於後臺運行的批量處理程序來講, 能夠將行鎖的等待時間調大, 以免發生大的回滾操做。
show variables like 'innodb_lock_wait_timeout';
鎖是計算機協調多個進程或線程併發訪問某一資源的機制。在數據庫中,除傳統的計算資源(如 CPU、RAM、I/O 等)的爭用之外,數據也是一種供許多用戶共享的資源。如何保證數據併發訪問的一致性、有效性是全部數據庫必須解決的一個問題,鎖衝突也是影響數據庫併發訪問性能的一個重要因素。
表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的機率最高,併發度最低。
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。
頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常。
讀鎖(共享鎖):針對同一份數據,多個讀操做能夠同時進行而不會互相影響。
寫鎖(排它鎖):當前操做沒有完成以前,它會阻斷其餘寫鎖和讀鎖。
存儲引擎 | 表級鎖 | 行級鎖 | 頁面鎖 |
---|---|---|---|
MyISAM | 支持 | 不支持 | 不支持 |
InnoDB | 支持 | 支持 | 不支持 |
MEMORY | 支持 | 不支持 | 不支持 |
BDB | 支持 | 不支持 | 支持 |
僅從鎖的角度來講:表級鎖更適合於以查詢爲主,只有少許按索引條件更新數據的應用,如
Web 應用;而行級鎖則更適合於有大量按索引條件併發更新少許不一樣數據,同時又有併發
查詢的應用,如一些在線事務處理(OLTP)系統。
(1)在MyISAM引擎中查詢會自動的加上讀鎖,增刪改自動加上寫鎖。不須要人爲加上
(2)讀鎖:給一個表接了一個讀鎖以後,其餘客戶端也能夠查詢到,由於讀鎖能夠共同進行不會影響操做,必需要解鎖以後 unlock tables
,才能進行增刪改,否則直接進行修改表,會進去等待狀態。
(3)寫鎖:在進行寫鎖以後,在當前客戶端能夠增刪改查,可是在其餘客戶端執行操做就會進入等待狀態,須要解鎖才能夠進行下一步操做。
可見
(1)對 MyISAM 表的讀操做,不會阻塞其餘用戶對同一表的讀請求,但會阻塞對同一表的寫請求;
(2)對 MyISAM 表的寫操做,則會阻塞其餘用戶對同一表的讀和寫操做;
MyISAM 的讀寫鎖調度是寫優先,這也是MyISAM不適合作寫爲主的表的存儲引擎的緣由。由於寫鎖後,其餘線程不能作任何操做,大量的更新會使查詢很可貴到鎖,從而形成永遠阻塞。
show open tables;
In_user : 表當前被查詢使用的次數。若是該數爲零,則表是打開的,可是當前沒有被使用。
Name_locked:表名稱是否被鎖定。名稱鎖定用於取消表或對錶進行重命名等操做。
show status like 'table_locks%';
Table_locks_immediate : 指的是可以當即得到表級鎖的次數,每當即獲取鎖,值加1。
Table_locks_waited : 指的是不能當即獲取表級鎖而須要等待的次數,每等待一次,該值加1,此值高說明存在着較爲嚴重的表級鎖爭用狀況。
InnoDB 與 MyISAM 的最大不一樣有兩點:
(1)支持事務(TRANSACTION);
(2)採用了行級鎖。
事務是由一組 SQL 語句組成的邏輯處理單元,事務具備如下 4 個屬性,一般簡稱爲事務的ACID 屬性。
更新丟失(Lost Update):當兩個或多個事務選擇同一行,而後基於最初選定的值更新該行時,因爲每一個事務都不知道其餘事務的存在,就會發生丟失更新問題最後的更新覆蓋了由其餘事務所作的更新。例如,兩個編輯人員製做了同一文檔的電子副本。每一個編輯人員獨立地更改其副本,而後保存更改後的副本,這樣就覆蓋了原始文檔。最後保存其更改副本的編輯人員覆蓋另外一個編輯人員所作的更改。若是在一個編輯人員完成並提交事務以前,另外一個編輯人員不能訪問同一文件,則可避免此問題。
髒讀(Dirty Reads):一個事務正在對一條記錄作修改,在這個事務完成並提交前,這條記錄的數據就處於不一致狀態;這時,另外一個事務也來讀取同一條記錄,若是不加控制,第二個事務讀取了這些「髒」數據,並據此作進一步的處理,就會產生未提交的數據依賴關係。這種現象被形象地叫作"髒讀"。
不可重複讀(Non-Repeatable Reads):一個事務在讀取某些數據後的某個時間,再次讀取之前讀過的數據,卻發現其讀出的數據已經發生了改變、或某些記錄已經被刪除了!這種現象就叫作「不可重複讀」。
幻讀(Phantom Reads):一個事務按相同的查詢條件從新讀取之前檢索過的數據,卻發現其餘事務插入了知足其查詢條件的新數據,這種現象就稱爲「幻讀」。
數據庫實現事務隔離的方式,基本上可分爲如下兩種。
(1)在讀取數據前,對其加鎖,阻止其餘事務對數據進行修改。
(2)不用加任何鎖,經過必定機制生成一個數據請求時間點的一致性數據快照(Snapshot),並用這個快照來提供必定級別(語句級或事務級)的一致性讀取。從用戶的角度來看,好象是數據庫能夠提供同一數據的多個版本,所以,這種技術叫作數據多版本併發控制(MultiVersion Concurrency Control,簡稱 MVCC 或MCC),也常常稱爲多版本數據庫。
MySQL默認隔離級別
show variables like 'tx_isolation';
這4種隔離級別,並行性能依次下降,安全性依次提升。
先關閉InnoDB表的事務自動提交,這種狀況下只有提交事務纔會生效,而後打開終端A更新一條id=3的數據,如今數據更新成功可是不提交(commit),再打開終端B,寫上一樣的Sql語句,語句執行就處於等待狀態,這時候提交A終端數據,B終端正常更新了。InnoDB行級鎖只鎖定一行,更新兩條不一樣的行,正常能夠獲取到鎖,只要進行增刪改的時候InnoDb就會爲行加上排它鎖,別的事務沒法執行SQL語句。關閉自動提交,每次至關於開啓了一個事務,其餘地方提交的東西看不到,由於事務具備隔離級別,再提交一次才能夠看到。
在關閉事務自動提交以後,更新查詢字段爲varchar沒有加單引號致使索引會失效,索引失效就會致使行鎖升級爲表鎖。
當咱們用範圍條件,而不是使用相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據進行加鎖; 對於鍵值在條件範圍內但並不存在的記錄,叫作 "間隙(GAP)" , InnoDB也會對這個 "間隙" 加鎖,這種鎖機制就是所謂的 間隙鎖(Next-Key鎖) 。
好比在數據中更新分數大於80的學生,由於數據中有的學生沒有成績,爲空也會被加上鎖。這時候沒有提交數據,將沒法更新分數大於80的學生。
show status like 'innodb_row_lock%';
Innodb_row_lock_current_waits: 當前正在等待鎖定的數量 Innodb_row_lock_time: 從系統啓動到如今鎖定總時間長度 Innodb_row_lock_time_avg:每次等待所花平均時長 Innodb_row_lock_time_max:從系統啓動到如今等待最長的一次所花的時間 Innodb_row_lock_waits: 系統啓動後到如今總共等待的次數 當等待的次數很高,並且每次等待的時長也不小的時候,咱們就須要分析系統中爲何會有如此多的等待,而後根據分析結果着手製定優化計劃。
InnoDB存儲引擎因爲實現了 行級鎖定,雖然在鎖定機制的實現方面帶來了性能損耗可能表現比表鎖更高一些可是在橫踢併發處理方面能力要遠遠優於MyISAM的表鎖,當系統併發量較高的時候,InnoDB的增提性能和MyISAM相比就會有比較明顯的優點。可是當InnoDB行級鎖處理不當的時候,可能讓InnoDB總體性能表現比更差。
建議: