目錄
寫在前面
學習鏈接:數據庫 MySQL 視頻教程全集
1. mysql的架構介紹
mysql簡介
概述
高級Mysql
- 完整的mysql優化需要很深的功底,大公司甚至有專門的DBA寫上述
- mysql內核
- sql優化工程師
- mysql服務器的優化
- 各種參數常量設定
- 查詢語句優化
- 主從複製
- 軟硬件升級
- 容災備份
- sql編程
mysqlLinux版的安裝
- mysql5.5
- 下載地址:https://dev.mysql.com/downloads/mysql/5.5.html#downloads
- 檢查當前系統是否安裝過mysql:
- 查詢命令:rpm -qa|grep -i mysql
- 刪除命令:rpm -e RPM軟件包名稱
- 刪除自帶的mysql:yum -y remove mysql-libs-5.1.73-7.el6.x86_64
- 安裝mysql服務端(注意提示):
- rpm -ivh MySQL-server-5.5.48-1.linux2.6.i386.rpm
- 如果報錯libc.so.6:https://blog.csdn.net/xiyuliuyang/article/details/90750049
- 如果警告key ID 5072e1f5: NOKEY:https://blog.csdn.net/Aaron960214/article/details/78451321
- rpm -ivh MySQL-server-5.5.48-1.linux2.6.i386.rpm
- 安裝mysql客戶端
- rpm -ivh MySQL-client-5.5.48-1.linux2.6.i386.rpm
- 查看MySQL安裝時創建的mysql用戶和mysql組
- cat /etc/passwd|grep mysql
- cat /etc/group|grep mysql
- mysqladmin --version
- cat /etc/passwd|grep mysql
- mysql服務的啓+停
- service mysql start
- service mysql start
- 如果報錯ERROR! The server quit without updating PID file (/var/lib/mysql/localhost.localdomain.pid).
- 解決辦法:https://www.cnblogs.com/bingco/p/8068243.html
mysql_install_db --datadir=/var/lib/mysql chown mysql:mysql /var/lib/mysql -R
- 查看mysql的進程:ps -ef|grep mysql
- mysql服務啓動後,開始連接
- 首次連接成功:mysql(不需要輸入密碼)
- 給root用戶設置密碼:/usr/bin/mysqladmin -u root password 123456
- 首次連接成功:mysql(不需要輸入密碼)
- 自啓動mysql服務
- 設置開機自啓動mysql:chkconfig mysql on
- 查看mysql的等級:chkconfig --list | grep mysql
- 查看不同等級代表的含義:cat /etc/inittab
- 查看開機自動服務有哪些:ntsysv
- 設置開機自啓動mysql:chkconfig mysql on
- 修改配置文件位置
- 版本5.5:cp /usr/share/mysql/my-huge.cnf /etc/my.cnf
- 版本5.6:cp /usr/share/mysql/my-default.cnf /etc/my.cnf
- 版本5.5:cp /usr/share/mysql/my-huge.cnf /etc/my.cnf
- 修改字符集和數據存儲路徑
- 查看字符集
- show variables like ‘character%’;
- show variables like ‘%char%’;
- 由於默認的是客戶端和服務器都使用的latin1,所以都是亂碼
- 修改
- 重啓mysql
- 重新連接後,原來的庫由於建立於修改字符集之前,所以中文依然是亂碼,而新建表中文不是亂碼
- 查看字符集
- MySQL的安裝位置
-
- /var/lib/mysql:mysql數據庫文件的存放路徑
- /usr/share/mysql:配置文件目錄
- /usr/bin:相關命令目錄
- /etc/init.d/mysql:啓停相關腳本
-
mysql配置文件
- 主要配置文件
- 二進制日誌log-bin
- 主從複製
- 錯誤日誌log-error
- 默認是關閉的,記錄嚴重的警告和錯誤信息,每次啓動和關閉的詳細信息等。
- 查詢日誌log
- 默認關閉,記錄查詢的sql語句,如果開啓會降低mysql的整體性能,因爲記錄日誌也是需要消耗系統資源的。
- 數據文件
- 兩系統
- windows:D:\devSoft\MySQLServer5.5\data目錄下可以挑選很多庫
- linux
- 看看當前系統中的全部庫後再進去
- 默認路徑:/var/lib/mysql
- frm文件:存放表結構
- myd文件:存放表數據
- myi文件:存放表索引
- 兩系統
- 如何配置
- windows:my.ini文件
- Linux:/etc/my.cnf文件
- 二進制日誌log-bin
mysql邏輯架構介紹
- 和其它數據庫相比,MySQL有點與衆不同,它的架構可以在多種不同場景中應用併發揮良好作用。主要體現在存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構可以根據業務的需求和時機需要選擇合適的存儲引擎。
- 從上到下,連接層,服務層,引擎層,存儲層
mysql存儲引擎
- 查看命令
- 如何用命令查看
- 看你的mysql現在已提供什麼存儲引擎:show engines;
- 看你的mysql當前默認的存儲引擎:show variables like '%storage_engine%';
- 如何用命令查看
- MyISAM和InnoDB
- 阿里巴巴、淘寶用哪個
2. 索引優化分析
性能下降SQL慢
- 執行時間長,等待時間長
- 查詢語句寫的爛
- 索引失效
- 單值索引
- 複合索引
- 關聯查詢太多join(設計缺陷或不得已的需求)
- 服務器調優及各個參數設置(緩衝、線程數等)
常見通用的Join查詢
- SQL執行順序
- 手寫
- 機讀
- 總結
- Join圖-7種JOIN
索引簡介
- 是什麼
- MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。可以得到索引的本質:索引是數據結構。
- 你可以簡單理解爲“排好序的快速查找數據結構”。
- 詳解(B樹)
- 結論數據本身之外,數據庫還維護着一個滿足特定查找算法的數據結構,這些數據結構以某種方式指向數據,這樣就可以在這些數據結構的基礎上實現高級查找算法,這種數據結構就是索引。
- 一般來說索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在磁盤上。
- 我們平常所說的索引,如果沒有特別指明,都是指B樹(多路搜索樹,並不一定是二叉的)結構組織的索引。其中聚集索引,次要索引,覆蓋索引,複合索引,前綴索引,唯一索引默認的都是使用B+樹索引,統稱索引。當然,除了B+樹這種類型的索引之外,還有哈希索引(hash index)等。
- 優勢
- 類似大學圖書館建書目索引,提高數據檢索的效率,降低數據庫的IO成本。
- 通過索引列對數據進行排序,降低數據排序的成本,降低了CPU的消耗。
- 劣勢
- 實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,所以索引列也是要佔用空間的。
- 雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,都會調整因爲更新所帶來的鍵值變化後的索引信息。
- 索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或者優化查詢。
- mysql索引分類
- 單值索引:即一個索引只包含單個列,一個表可以有多個單列索引
- 唯一索引:索引列的值必須唯一,但允許有空值
- 複合索引:即一個索引包含多個列
- 基本語法
- 創建:create [unique] index indexname on mytable(columnname(length));alter mytable add [unique] index [indexname] on (columnname(length))
- 如果是char,varchar類型,length可以小於字段實際長度;如果是blob和text類型,必須指定length。
- 刪除:drop index [indexname] on mytable;
- 查看:show index from table_name\G
- 使用alter命令
- 創建:create [unique] index indexname on mytable(columnname(length));alter mytable add [unique] index [indexname] on (columnname(length))
- mysql索引結構
- BTree索引
- 索引原理
- Hash索引
- full-text全文索引
- R-Tree索引
- BTree索引
- 哪些情況需要創建索引
- 主鍵自動建立唯一索引
- 頻繁作爲查詢條件的字段應該創建索引
- 查詢中與其它表關聯的字段,外鍵關係建立索引
- 頻繁更新的字段不適合創建索引,因爲每次更新不單單是更新了記錄,還會更新索引,加重IO負擔
- where條件裏用不到的字段不創建索引
- 單鍵/組合索引的選擇問題,who?(在高併發下傾向創建組合索引)
- 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度
- 查詢中統計或者分組字段
- 哪些情況不需要創建索引
- 表記錄太少
- 經常增刪改的表
- Why:提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件。
- 數據重複且分佈平均的表字段,因此應該只爲最經常查詢和最經常排序的數據列建立索引。注意,如果某個數據列包含許多重複的內容,爲它建立索引就沒有太大的實際效果。
性能分析
- MySQL Query Optimizer
- MySQL常見瓶頸
- CPU:CPU在飽和的時候一般發生在數據裝入內存或從磁盤上讀取數據時候
- IO:磁盤I/O瓶頸發生在裝入數據遠大於內存容量的時候
- 服務器硬件的性能瓶頸:top,free,iostat和vmstat來查看系統的性能狀態
- Explain
- 是什麼(查看執行計劃)
- 使用EXPLAIN關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸。
- 能幹嘛
- 表的讀取順序
- 數據讀取操作的操作類型
- 哪些索引可以使用
- 哪些索引被實際使用
- 表之間的應用
- 每張表有多少行被優化器查詢
- 怎麼玩
- Explain+SQL語句
- 執行計劃包含的信息
- 各字段解釋
- id
- select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序
- 三種情況:
- id相同,執行順序由上至下
- id不同,如果是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
- id相同不同,同時存在
- 衍生:DERIVED
- select_type:
- 有哪些
- 查詢的類型,主要是用於區別普通查詢、聯合查詢、子查詢等的複雜查詢
- SIMPLE:簡單的select查詢,查詢中不包含子查詢或者UNION。
- PRIMARY:查詢中包含任何複雜的子部分,最外層查詢則被標記爲PRIMARY。
- SUBQUERY:在FROM列表中包含的子查詢被標記爲DERIVED(衍生),MySQL會遞歸執行這些子查詢,把結果放在臨時表裏。
- DERIVED:在FROM列表中包含的子查詢被標記爲DERIVED(衍生)。MySQL會遞歸執行這些子查詢,把結果放在臨時表裏。
- UNION:若第二個SELECT出現在UNION之後,則被標記爲UNION;若UNION包含在FROM子句的子查詢中,外層SELECT將被標記爲:DERIVED。
- UNION RESULT:從UNION表中獲取結果的SELECT。
- table:顯示這一行的數據是關於哪些表的。
- type:
- 訪問類型排序
- type顯示的是訪問類型,是較爲重要的一個指標,結果值從最好到最壞依次是:system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>All
- 顯示查詢使用了何種類型,從最好到最差依此是:system>const>eq_ref>ref>range>index>All
- system:表只有一行記錄(等於系統表),這是const類型的特例,平時不會出現,這個也可以忽略不計。
- const:表示通過索引一次就找到了,const用於比較primary key或則unique索引。因爲只匹配一行數據,所以很快。如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量。
- eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描。
- ref:非唯一性索引掃描,返回匹配某個單獨值的所有行。本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,所以它應該屬於查找和掃描的混合體。
- range:只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。一般就是在你的where語句中出現了between、<、>、in等的查詢。這種範圍掃描索引掃描比全表掃描要好,因爲它只需要開始於索引的某一點,而結束於另一點,不會掃描全部索引。
- index:Full Index Scan,index與All區別爲index類型只遍歷索引樹。這通常比All快,因爲索引文件通常比數據文件小。(也就是說雖然all和index都是讀全表,但index是從索引中讀取的,而all是從硬盤中讀的)
- all:Full Table Scan,將遍歷全表以找到匹配的行。
- 一般來說,得保證查詢至少達到range級別,最好能達到ref。
- 訪問類型排序
- possible_keys:顯示可能應用在這張表中的索引,一個或多個。查詢涉及到的字段上若存在索引,則該索引將被列出。但不一定被查詢實際使用。
- key:實際使用的索引。如果爲NULL,則沒有使用索引。查詢中若使用了覆蓋索引,則該索引僅出現在key列表中,不會出現在possible_keys列表中。(覆蓋索引:查詢的字段與建立的複合索引的個數一一吻合)
- key_len:表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度。在不損失精確性的情況下,長度越短越好。key_len顯示的值爲索引字段的最大可能長度,並非實際使用長度,即key_len是根據表定義計算而得,不是通過表內檢索出的。
- ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或常量被用於查找索引列上的值。查詢中與其它表關聯的字段,外鍵關係建立索引。
- rows:根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數。
- Extra:包含不適合在其他列中顯示但十分重要的額外信息。
- Using filesort:說明mysql會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。MySQL中無法利用索引完成的排序操作成爲“文件排序”。
- Using temporary:使用了臨時表保存中間結果,MySQL在對查詢結果排序時使用臨時表。常見於排序order by和分組查詢group by。
- Using index:表示相應的select操作中使用了覆蓋索引(Covering Index),避免訪問了表的數據行,效率不錯!如果同時出現using where,表明索引被用來執行索引鍵值的查找;如果沒有同時出現using where,表明索引用來讀取數據而非執行查找動作。覆蓋索引:
- Using where:表明使用了where過濾。
- Using join buffer:使用了連接緩存。
- impossible where:where子句的值總是false,不能用來獲取任何元組。(查詢語句中where的條件不可能被滿足,恆爲False)
- select tables optimized away:在沒有GROUPBY子句的情況下,基於索引優化MIN/MAX操作或者對於MyISAM存儲引擎優化COUNT(*)操作,不必等到執行階段再進行計算,查詢執行計劃生成的階段即完成優化。
- distinct:優化distinct操作,在找到第一匹配的元組後即停止找相同值的動作。
- id
- 熱身Case
- 是什麼(查看執行計劃)
索引優化
- 索引分析
- 單表
- 建表SQL
- 案例
- 兩表
- 建表SQL
- 案例
- 總結:左連接建右表,右連接建左表。理由:以左連接爲例,左表的信息全都有,所以右表需要查找,所以建立右表index。
- 三表
- 建表SQL
- 案例
- 總結:Join語句的優化
- 儘可能減少Join語句中的NestedLoop的循環總次數:“永遠用小結果集驅動大的結果集”。
- 優先優化NestedLoop的內層循環。
- 保證Join語句中被驅動表上Join條件字段已經被索引。
- 當無法保證被驅動表的Join條件字段被索引且內存資源充足的前提下,不要太吝惜JoinBuffer的設置。
- 單表
- 索引失效(應該避免)
- 建表SQL
- 案例(索引失效)
- 全值匹配我最愛
- 最佳左前綴法則:
- 如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。(帶頭大哥不能死,中間兄弟不能斷哈哈哈)
- 不在索引列上作任何操作(計算、函數、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描
- 存儲引擎不能使用索引中範圍條件右邊的列
- 中間兄弟別搞範圍,要搞等值
- 儘量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),減少select *
- 按需取數據,用多少取多少,儘量與索引一致
- Extra中出現了using index很好!
- mysql在使用不等於(!=或者<>)的時候無法使用索引會導致全表掃描
- is null,is not null也無法使用索引
- like以通配符開頭(‘%abc…’)mysql索引失效會變成全表掃描的操作
- like%加右邊
- 問題:解決like ‘%字符串%’時索引不被使用的方法?
- 利用覆蓋索引解決兩邊%的優化問題。
- 字符串不加單引號索引失效該問題同問題3,是索引列上做了類型轉換!
- VARCHAR類型絕對不能失去單引號
- 少用or,用它來連接時會索引失效
- 小總結
- 優化總結口訣:全值匹配我最愛,最左前綴要遵守;帶頭大哥不能死,中間兄弟不能斷;
索引列上少計算,範圍之後全失效;
LIKE百分寫最右,覆蓋索引不寫星;
不等空值還有or,索引失效要少用;
VAR引號不可丟,SQL高級也不難!
- 優化總結口訣:全值匹配我最愛,最左前綴要遵守;帶頭大哥不能死,中間兄弟不能斷;
- 面試題講解
- 題目SQL
- c3的作用在排序而不是查找,用到了但是沒有統計在結果中
- 出現了filesort
- 只用c1一個字段索引,但是c2、c3用於排序,無filesort
- 出現了filesort,我們建的索引是1234,它沒有按照順序來,3和2顛倒了
- 用c1、c2兩個字段索引,但是c2、c3用於排序,無filesort
- 本例有常量c2的情況,因此排序就相當於order by c3,常量,所以沒有出現filesort的情況
- 定值、範圍還是排序,一般order by是給個範圍
- group by基本上都需要進行排序,會有臨時表產生
- 題目SQL
- 一般性建議
- 對於單鍵索引,儘量選擇針對當前query過濾性更好的索引
- 在選擇組合索引的時候,當前Query中過濾性最好的字段在索引字段順序中,位置越靠前越好
- 在選擇組合索引的時候,儘量選擇可以能夠包含當前query中的where字句中更多字段的索引
- 儘可能通過分析統計信息和調整query的寫法來達到選擇合適索引的目的
3. 查詢截取分析
- 分析
- 觀察,至少跑1天,看看生產的慢SQL情況。
- 開啓慢查詢日誌,設置閾值,比如超過5秒鐘的就是慢SQL,並將它抓取出來。
- explain+慢SQL分析
- show profile
- 運維經理 or DBA,進行SQL數據庫服務器參數調優。
- 總結
- 慢查詢的開啓並捕獲
- explain+慢SQL分析
- show profile查詢SQL在Mysql服務器裏面的執行細節和生命週期情況
- SQL數據庫服務器的參數調優
查詢優化
- 永遠小表驅動大表,類似嵌套循環Nested Loop
- 優化原則:小表驅動大表,即小的數據集驅動大的數據集。
- 當B表的數據集必須小於A表的數據集時,用in優於exists
- 當A表的數據集必須小於B表的數據集時,用exists優於in
- 注意:A表與B表的ID字段應建立索引。
- EXISTS
- SELECT … FROM table WHERE EXISTS(subquery)
- 該語法可以理解爲:將主查詢的數據,放到子查詢中做條件驗證,根據驗證結果(TRUE或FALSE)來決定主查詢的數據結果是否得以保留。
- 提示
- EXISTS(subquery)只返回TRUE或FALSE,因此子查詢中的SELECT *也可以是SELECT 1或SELECT ‘X’,官方說法是實際執行時會忽略SELECT清單,因此沒有區別。
- EXISTS子查詢的實際執行過程可能經過了優化而不是我們理解上的逐條對比,如果擔心效率問題,可進行實際檢驗以確定是否有效率問題。
- EXISTS子查詢往往也可以用條件表達式/其他子查詢或者JOIN來替代,何種最優需要具體問題具體分析。
- 總結
- ORDER BY關鍵字優化
- ORDER BY子句,儘量使用Index方式排序,避免使用FileSort方式排序
- 建表SQL
- Case
- case1
- case2
- MySQL支持兩種方式的排序
- FileSort和Index,Index效率高。FileSort方式效率較低。
- Using Index,它指MySQL掃描索引本身完成排序。
- ORDER BY滿足兩種情況,會使用Index方式排序:
- ORDER BY語句使用索引最左前列
- 使用Where子句與ORDER BY子句條件列組合滿足索引最左前列
- 儘可能在索引列上完成排序操作,遵照索引建的最佳最前綴
- 如果不在索引列上,filesort有兩種算法:
- mysql就要啓動雙路排序和單路排序
- 雙路排序
- MySQL4.1之前是使用雙路排序,字面意思就是兩次掃描磁盤,最終得到數據。讀取行指針和order by列,對他們進行排序,然後掃描已經排好序的列表,按照列表中的值重新從列表中讀取對應的數據輸出。
- 從磁盤取排序字段,在buffer進行排序,再從磁盤讀取其他字段。
- 取一批數據,要對磁盤進行了兩次掃描,衆所周知,I\O是很耗時的,所以在mysql4.1之後,出現了第二種改進的算法,就是單路排序
- 單路排序
- 從磁盤讀取查詢需要的所有列,按照order by列在buffer對它們進行排序,然後掃描排序後的列表進行輸出,它的效率更快一些,避免了第二次讀取數據。並且把隨機IO變成了順序IO,但是它會使用更多的空間。
- 結論及引申出的問題
- 由於單路是後出的,總體而言好過雙路
- 但是用單路有問題本來想省一次I/O操作,反而導致了大量的I/O操作,反而得不償失。(原因:數據的總大小超過sort_buffer的容量)
- 雙路排序
- mysql就要啓動雙路排序和單路排序
- 優化策略
- 增大sort_buffer_size參數的設置
- 增大max_length_for_sort_data參數的設置
- Why
- 小總結
- ORDER BY子句,儘量使用Index方式排序,避免使用FileSort方式排序
- GROUP BY關鍵字優化
- group by實質是先排序後進行分組,遵照索引建的最佳左前綴。
- 當無法使用索引列,增大max_length_for_sort_data參數的設置+增大sort_buffer_size參數的設置。
- where高於having,能寫在where限定的條件就不要去having限定了。
慢查詢日誌
- 是什麼
- MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閾值的語句,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中。
- long_query_time的默認值是10,意思是運行10秒以上的語句。
- 由它來查看哪些SQL超出了我們的最大忍耐時間值,比如一條sql執行超過5秒鐘,我們就算慢SQL,希望能收集超過5秒的sql,結合之前的explain進行全面分析。
- 怎麼玩
- 說明
- 默認情況下,MySQL數據庫沒有開啓慢查詢日誌,需要我們手動來設置這個參數。
- 當然,如果不是調優需要的話,一般不建議啓動該參數,因爲開啓慢查詢日誌會或多或少帶來一定的性能影響。慢查詢日誌支持將日誌記錄寫入文件。
- 查看是否開啓及如何開啓
- 默認:SHOW VARIABLES LIKE ‘%slow_query_log%’;
- 開啓:set global slow_query_log=1;
- 那麼開啓了慢查詢日誌後,什麼樣的SQL纔會記錄到慢查詢日誌裏面呢
- Case
- 查看當前多少秒算慢:SHOW VARIABLES LIKE ‘long_query_time%’;
- 設置慢的閾值時間:set global long_query_time=3;
- 爲什麼設置後看不出變化(設置3之後,查詢依然顯示10):
- 需要重新連接或新開一個會話才能看到修改值。
- SHOW VARIABLES LIEK ‘long_query_time%’;
- show global variables like ‘long_query_time’;
- 記錄慢SQL並後續分析
- 查詢當前系統中有多少條慢查詢記錄:show global status like ‘%Slow_queries%’;
- 配置版
- 說明
- 日誌分析工具mysqldumpslow
- 在生產環境中,如果要手工分析日誌,查找、分析SQL,顯然是個體力活,MySQL提供了日誌分析工具mysqldumpslow。
- 查看mysqldumpslow的幫助信息
- mysqldumpslow --help
- s:是表示按照何種方式排序
- c:訪問次數
- I:鎖定時間
- r:返回記錄
- t:查詢時間
- al:平均鎖定時間
- ar:平均返回記錄數
- at:平均查詢時間
- t:即爲返回前面多少條的數據
- g:後邊搭配一個正則匹配模式,大小寫不敏感
- 工作常用參考
批量數據腳本
- 往表裏插入1000w數據
- 建表
- 設置參數log_bin_trust_function_creators
- 創建函數,保證每條數據都不同
- 隨機產生字符串
- 隨機產生部門編號
- 創建存儲過程
- 調用存儲過程
- dept:
DELIMITER ; CALL insert_dept(100, 10);
- emp:
DELIMITER ; CALL insert_emp(100001, 500000);
- dept:
Show Profile
- 是什麼:是mysql提供的可以用來分析當前會話中語句執行的資源消耗情況。可以用於SQL的調優的測量
- 默認情況下,參數處於關閉狀態,並保存最近15次的運行結果
- 分析步驟
- 是否支持,看看當前的mysql版本是否支持
- show variables like ‘profiling’;
- 開啓功能,默認是關閉,使用前需要開啓
- set profiling = on;
- 運行SQL
- select * from emp group by id%10 limit 150000;
- select * from emp group by id%20 order by 5;
- 查看結果,show profiles;
- 診斷SQL,show profile cpu, block io for query [上一步前面的問題SQL數字號碼];
- 參數備註
- 日常開發需要注意的結論
- converting HEAP to MyISAM:查詢結果太大,內存都不夠用了往磁盤上搬了
- Creating tmp table:創建臨時表
- 拷貝數據到臨時表
- 用完再刪除
- Copying to tmp table on disk:把內存中臨時表複製到磁盤,危險!!
- locked
- 是否支持,看看當前的mysql版本是否支持
全局查詢日誌
- 配置啓用
- 編碼啓用
- 永遠不要在生產環境開啓這個功能!
4. MySQL鎖機制
概述
- 定義
- 鎖是計算機協調多個進程併發訪問某一資源的機制。
- 生活購物
- 鎖的分類
- 從對數據操作的類型(讀/寫)分
- 讀鎖(共享鎖):針對同一份數據,多個讀操作可以同時進行而不會互相影響。
- 寫鎖(排它鎖):當前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖。
- 從對數據操作的粒度分
- 表鎖
- 行鎖
- 從對數據操作的類型(讀/寫)分
三鎖
- 開銷、加鎖速度、死鎖、粒度、併發性能
- 只能就具體應用的特點來說那種鎖更合適
表鎖(偏讀)
- 特點:偏向MyISAM存儲引擎,開銷小,加鎖快;無死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低。
- 案例分析
- 建表SQL
- 手動增加表鎖
- lock table 表名字 read(write), 表名字2 read(write), 其他;
- 查看錶上加過的鎖
- show open tables;
- 釋放表鎖
- unlock tables;
- 加讀鎖(我們爲mylock表加read鎖(讀阻塞寫例子))
- 加寫鎖(我們爲mylock表加write鎖(MyISAM存儲引擎的寫阻塞讀例子))
- 案例結論簡而言之,就是讀鎖會阻塞寫,但是不會阻塞讀。而寫鎖則會把讀和寫都阻塞。
- 表鎖分析
- 看看哪些表被加鎖了:show open tables;
- 如何分析表鎖定:可以通過檢查table_locks_waited和table_locks_immediate狀態變量來分析系統上的表鎖定。
- show status like ‘table%’;
- 這裏有兩個狀態變量記錄MySQL內部表級鎖定的情況,兩個變量的說明如下:
- Table_locks_immediate:產生表級鎖定的次數,表示可以立即獲取鎖的查詢次數,每立即獲取鎖值加1;
- Table_locks_waited:出現表級鎖定爭用而發生等待的次數(不能立即獲取鎖的次數,每等待一次鎖值加1),此值高則說明存在着較嚴重的表級鎖爭用情況。
- 此外,MyISAM的讀寫鎖調度是寫優先,這也是MyISAM不適合做寫爲主表的引擎。因爲寫鎖後,其他線程不能做任何操作,大量的更新會使查詢很難得到鎖,從而造成永遠阻塞。
行鎖(偏寫)
- 特點
- 偏向Innodb存儲引擎,開銷大,加鎖慢;會出現死鎖;鎖定粒度小,發生鎖衝突的概率最低,併發度也最高。
- Innodb與MyISAM的最大不同有兩點:
- 一是支持事務(TRANSACTION)
- 而是採用了行級鎖
- 由於行鎖支持事務,複習老知識
- 事務(Transaction)及其ACID屬性
- 併發事務處理帶來的問題
- 更新丟失(Lost Update)
- 髒讀(Dirty Reads)
- 不可重複讀(Non-Repeatable Reads)
- 幻讀(Phantom Reads)
- 事務隔離級別
- 案例分析
- 建表SQL
- 行鎖定基本演示
- 無索引行鎖升級爲表鎖
- 如果在更新數據的時候出現了強制類型轉換導致索引失效,使得行鎖變表鎖,即在操作不同行的時候,會出現阻塞的現象。
- 間隙鎖危害
- 什麼是間隙鎖:當我們用範圍條件而不是相等條件索引數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫做“間隙(GAP)”。InnoDB也會對這個“間隙”加鎖,這種鎖機制就是所謂的間隙鎖(Next-Key鎖)。
- 危害:
- 因爲Query執行過程中通過範圍查找的話,會鎖定整個範圍內所有的索引鍵值,即使這個鍵值並不存在。
- 間隙鎖有一個比較致命的弱點,就是當鎖定一個範圍鍵值之後,即使某些不存在的鍵值也會被無辜的鎖定,而造成在鎖定的時候無法插入鎖定鍵值範圍內的任何數據。在某些場景下這可能會對性能造成很大的危害。
- 面試題:常考如何鎖定一行
- select * from 表 where 某一行的條件 for update;
- 案例結論
- InnoDB存儲引擎由於實現了行級鎖定,雖然在鎖定機制的實現方面所帶來的性能損耗可能比表級鎖定會更高一些,但是在整體併發處理能力方面要遠遠優於MyISAM的表級鎖定的。當系統併發量較高的時候,InnoDB的整體性能和MyISAM相比就會有比較明顯的優勢了。
- 但是,InnoDB的行級鎖定同樣也有其脆弱的一面,當我們使用不當的時候,可能會讓InnoDB的整體性能表現不僅不能比MyISAM高,甚至可能會更差。
- 行鎖分析
- 如何分析行鎖定
- 通過檢查InnoDB_row_lock狀態變量來分析系統上的行鎖的爭奪情況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:系統啓動後到現在總共等待的次數。
- 對於這5個變量,比較重要的是
- innodb_row_lock_time_avg(等待平均時長)
- innodb_row_lock_waits(等待總次數)
- innodb_row_lock_time(等待總時長)
- 這三項
- 尤其是當等待次數很高,而且每次等待時長也不小的時候,我們就需要分析系統中爲什麼會有如此多的等待,然後根據分析結果着手製定優化計劃。
- 如何分析行鎖定
- 優化建議
- 儘可能讓所有數據檢索都通過索引來完成,避免無索引行鎖升級爲表鎖。
- 合理設計索引,儘量縮小鎖的範圍。
- 儘可能減少索引條件,避免間隙鎖。
- 儘量控制事務大小,減少鎖定資源量和時間長度。
- 儘可能低級別事務隔離。
頁鎖
- 開銷和加鎖時間介於表鎖和行鎖之間。
- 會出現死鎖。
- 鎖定粒度介於表鎖和行鎖之間。
- 併發度一般
5. 主從複製
複製的基本原理
- slave會從master讀取binlog來進行數據同步
- 三步驟+原理圖
複製的基本原則
- 每個slave只有一個master
- 每個slave只能有一個唯一的服務器ID
- 每個master可以有多個slave
複製的最大問題
- 延時
一主一從常見配置
- mysql版本一致且後臺以服務運行
- 主從都配置在[mysqld]結點下,都是小寫
- 主機修改my.ini配置文件
- 【必須】主服務器唯一ID
- server-id=1
- 【必須】啓用二進制日誌
- log-bin=自己本地的路徑/mysqlbin
- 【可選】啓用錯誤日誌
- log-err=自己本地的路徑/mysqlerr
- 【可選】根目錄
- basedir=自己本地路徑
- 【可選】臨時目錄
- temdir=自己本地路徑
- 【可選】數據目錄
- datadir=自己本地路徑/Data/
- read-only=0
- 主機,讀寫都可以
- 【可選】設置不要複製的數據庫
- binlog-ignore-db=mysql
- 【可選】設置需要複製的數據庫
- binlog-do-db=需要複製的主數據庫名字
- 【必須】主服務器唯一ID
- 從機修改my.cnf配置文件
- 【必須】從服務器唯一ID
- server-id=2
- 【可選】啓用二進制日誌
- 【必須】從服務器唯一ID
- 因修改過配置文件,請主機+從機都重啓後臺mysql服務
- 主機從機都關閉防火牆
- windows手動關閉
- 關閉虛擬機linux防火牆:service iptables stop
- 在Windows主機上建立賬戶並授權slave
GRANT REPLICATION SLAVE ON *.* TO 'zhangsan' @ '192.168.14.167【從機數據庫IP】' IDENTIFIED BY '123456';
- flush privileges;
- 查詢master的狀態
- show master status
- 記錄下File和Position的值
- 執行完此步驟後不要再操作主服務器MYSQL,防止主服務器狀態值變化
- 在Linux從機上配置需要複製的主機
CHANGE MASTER TO MASTER_HOST='主機IP', MASTER_USER='zhangsan', MASTER_PASSWORD='123456', MASTER_LOG_FILE='file名字', MASTER_LOG_POS=position數字;
eg.- 啓動從服務器複製功能
- start slave;
- show slave status\G【\G是爲了以鍵值的形式顯示,好看一些】
- 下面兩個參數都是Yes,則說明主從配置成功!
- Slave_IO_Running:Yes
- Slave_SQL_Running:Yes
- 主機新建庫、新建表、insert記錄,從機複製
- 如何停止從服務複製功能
- stop slave;