尚硅谷MySQL高級學習筆記


數據庫MySQL學習筆記高級篇

寫在前面

學習鏈接:數據庫 MySQL 視頻教程全集

1. mysql的架構介紹

mysql簡介

概述

img

高級Mysql

  • 完整的mysql優化需要很深的功底,大公司甚至有專門的DBA寫上述
    • mysql內核
    • sql優化工程師
    • mysql服務器的優化
    • 各種參數常量設定
    • 查詢語句優化
    • 主從復制
    • 軟硬件升級
    • 容災備份
    • sql編程

mysqlLinux版的安裝

  • mysql5.5

  • 安裝mysql服務端(注意提示):

  • 安裝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
  • 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:chkconfig mysql on
      • 查看mysql的等級:chkconfig --list | grep mysql
      • 查看不同等級代表的含義:cat /etc/inittab
      • 查看開機自動服務有哪些:ntsysv
  • 修改配置文件位置

    • 版本5.5:cp /usr/share/mysql/my-huge.cnf /etc/my.cnf
      • 版本5.6:cp /usr/share/mysql/my-default.cnf /etc/my.cnf
  • 修改字符集和數據存儲路徑

    • 查看字符集
      • show variables like ‘character%’;
      • show variables like ‘%char%’;
      • 由於默認的是客戶端和服務器都使用的latin1,所以都是亂碼
      • 修改img
      • 重啟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文件

mysql邏輯架構介紹

  • 和其它數據庫相比,MySQL有點與眾不同,它的架構可以在多種不同場景中應用並發揮良好作用。主要體現在存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構可以根據業務的需求和時機需要選擇合適的存儲引擎。img
  • 從上到下,連接層,服務層,引擎層,存儲層img

mysql存儲引擎

  • 查看命令
    • 如何用命令查看
      • 看你的mysql現在已提供什么存儲引擎:show engines;
      • 看你的mysql當前默認的存儲引擎:show variables like '%storage_engine%';
  • MyISAM和InnoDBimg
  • 阿里巴巴、淘寶用哪個img

2. 索引優化分析

性能下降SQL慢

  • 執行時間長,等待時間長
    • 查詢語句寫的爛
    • 索引失效
      • 單值索引
      • 復合索引
    • 關聯查詢太多join(設計缺陷或不得已的需求)
    • 服務器調優及各個參數設置(緩沖、線程數等)

常見通用的Join查詢

  • SQL執行順序

    • 手寫

      img

    • 機讀

      img

    • 總結

      img

  • Join圖-7種JOIN

    imgimg

索引簡介

  • 是什么

    • MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構。可以得到索引的本質:索引是數據結構。img

    • 你可以簡單理解為“排好序的快速查找數據結構”。

      • 詳解(B樹)

        img

      • 結論

        數據本身之外,數據庫還維護着一個滿足特定查找算法的數據結構,這些數據結構以某種方式指向數據,這樣就可以在這些數據結構的基礎上實現高級查找算法,這種數據結構就是索引。

    • 一般來說索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在磁盤上。

    • 我們平常所說的索引,如果沒有特別指明,都是指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命令img

  • mysql索引結構

    • BTree索引
      • 索引原理imgimg
    • Hash索引
    • full-text全文索引
    • R-Tree索引
  • 哪些情況需要創建索引

    • 主鍵自動建立唯一索引
    • 頻繁作為查詢條件的字段應該創建索引
    • 查詢中與其它表關聯的字段,外鍵關系建立索引
    • 頻繁更新的字段不適合創建索引,因為每次更新不單單是更新了記錄,還會更新索引,加重IO負擔
    • where條件里用不到的字段不創建索引
    • 單鍵/組合索引的選擇問題,who?(在高並發下傾向創建組合索引)
    • 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度
    • 查詢中統計或者分組字段
  • 哪些情況不需要創建索引

    • 表記錄太少
    • 經常增刪改的表
      • Why:提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件。
    • 數據重復且分布平均的表字段,因此應該只為最經常查詢和最經常排序的數據列建立索引。注意,如果某個數據列包含許多重復的內容,為它建立索引就沒有太大的實際效果。img

性能分析

  • MySQL Query Optimizer

    img

  • MySQL常見瓶頸

    • CPU:CPU在飽和的時候一般發生在數據裝入內存或從磁盤上讀取數據時候
    • IO:磁盤I/O瓶頸發生在裝入數據遠大於內存容量的時候
    • 服務器硬件的性能瓶頸:top,free,iostat和vmstat來查看系統的性能狀態
  • Explain

    • 是什么(查看執行計划)

      • 使用EXPLAIN關鍵字可以模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸。
    • 能干嘛

      • 表的讀取順序
      • 數據讀取操作的操作類型
      • 哪些索引可以使用
      • 哪些索引被實際使用
      • 表之間的應用
      • 每張表有多少行被優化器查詢
    • 怎么玩

      • Explain+SQL語句

      • 執行計划包含的信息

        img

    • 各字段解釋

      • id

        • select查詢的序列號,包含一組數字,表示查詢中執行select子句或操作表的順序
        • 三種情況:
          • id相同,執行順序由上至下
          • id不同,如果是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
          • id相同不同,同時存在
        • 衍生:DERIVED
      • select_type:

        • 有哪些

          img

        • 查詢的類型,主要是用於區別普通查詢、聯合查詢、子查詢等的復雜查詢

          1. SIMPLE:簡單的select查詢,查詢中不包含子查詢或者UNION。
          2. PRIMARY:查詢中包含任何復雜的子部分,最外層查詢則被標記為PRIMARY。
          3. SUBQUERY:在FROM列表中包含的子查詢被標記為DERIVED(衍生),MySQL會遞歸執行這些子查詢,把結果放在臨時表里。
          4. DERIVED:在FROM列表中包含的子查詢被標記為DERIVED(衍生)。MySQL會遞歸執行這些子查詢,把結果放在臨時表里。
          5. UNION:若第二個SELECT出現在UNION之后,則被標記為UNION;若UNION包含在FROM子句的子查詢中,外層SELECT將被標記為:DERIVED。
          6. UNION RESULT:從UNION表中獲取結果的SELECT。
      • table:顯示這一行的數據是關於哪些表的。

      • type:

        • img

        • 訪問類型排序

          • 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,表明索引用來讀取數據而非執行查找動作。

          覆蓋索引:img

        • Using where:表明使用了where過濾。

        • Using join buffer:使用了連接緩存。

        • impossible where:where子句的值總是false,不能用來獲取任何元組。(查詢語句中where的條件不可能被滿足,恆為False)

        • select tables optimized away:在沒有GROUPBY子句的情況下,基於索引優化MIN/MAX操作或者對於MyISAM存儲引擎優化COUNT(*)操作,不必等到執行階段再進行計算,查詢執行計划生成的階段即完成優化。

        • distinct:優化distinct操作,在找到第一匹配的元組后即停止找相同值的動作。

    • 熱身Case

      imgimg

索引優化

  • 索引分析

    • 單表

      • 建表SQLimg
      • 案例imgimgimg
    • 兩表

      • 建表SQL

        img

      • 案例

        imgimg

      • 總結:左連接建右表,右連接建左表。理由:以左連接為例,左表的信息全都有,所以右表需要查找,所以建立右表index。

    • 三表

      • 建表SQL

        img

      • 案例

        img

      • 總結:Join語句的優化

        • 盡可能減少Join語句中的NestedLoop的循環總次數:“永遠用小結果集驅動大的結果集”。
        • 優先優化NestedLoop的內層循環。
        • 保證Join語句中被驅動表上Join條件字段已經被索引。
        • 當無法保證被驅動表的Join條件字段被索引且內存資源充足的前提下,不要太吝惜JoinBuffer的設置。
  • 索引失效(應該避免)

    • 建表SQLimg

    • 案例(索引失效)

      1. 全值匹配我最愛

        img

      2. 最佳左前綴法則

        • 如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。(帶頭大哥不能死,中間兄弟不能斷哈哈哈)
      3. 不在索引列上作任何操作(計算、函數、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描

        img

      4. 存儲引擎不能使用索引中范圍條件右邊的列

        img

        • 中間兄弟別搞范圍,要搞等值
      5. 盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),減少select *

        img

        • 按需取數據,用多少取多少,盡量與索引一致
        • Extra中出現了using index很好!
      6. mysql在使用不等於(!=或者<>)的時候無法使用索引會導致全表掃描

        img

      7. is null,is not null也無法使用索引

        img

      8. like以通配符開頭(‘%abc…’)mysql索引失效會變成全表掃描的操作

        img

        • like%加右邊

        • 問題:解決like ‘%字符串%’時索引不被使用的方法?

          img

        • 利用覆蓋索引解決兩邊%的優化問題。

      9. 字符串不加單引號索引失效

        img

        該問題同問題3,是索引列上做了類型轉換!

        • VARCHAR類型絕對不能失去單引號
      10. 少用or,用它來連接時會索引失效

        img

      11. 小總結

        img

        • 優化總結口訣:

          全值匹配我最愛,最左前綴要遵守;

          帶頭大哥不能死,中間兄弟不能斷;

          索引列上少計算,范圍之后全失效;

          LIKE百分寫最右,覆蓋索引不寫星;

          不等空值還有or,索引失效要少用;

          VAR引號不可丟,SQL高級也不難!

    • 面試題講解

      • 題目SQL

        img

        • imgimg

        • imgimg

        • imgimg

        • imgimg

          c3的作用在排序而不是查找,用到了但是沒有統計在結果中

        • imgimg

        • imgimg

          出現了filesort

        • imgimg

          只用c1一個字段索引,但是c2、c3用於排序,無filesort

        • imgimg

          出現了filesort,我們建的索引是1234,它沒有按照順序來,3和2顛倒了

        • imgimg

        • imgimg

          用c1、c2兩個字段索引,但是c2、c3用於排序,無filesort

        • imgimg

          本例有常量c2的情況,因此排序就相當於order by c3,常量,所以沒有出現filesort的情況

        • imgimg

        • imgimg

        • imgimg

      • 定值、范圍還是排序,一般order by是給個范圍

      • group by基本上都需要進行排序,會有臨時表產生

  • 一般性建議

    • 對於單鍵索引,盡量選擇針對當前query過濾性更好的索引
    • 在選擇組合索引的時候,當前Query中過濾性最好的字段在索引字段順序中,位置越靠前越好
    • 在選擇組合索引的時候,盡量選擇可以能夠包含當前query中的where字句中更多字段的索引
    • 盡可能通過分析統計信息和調整query的寫法來達到選擇合適索引的目的

3. 查詢截取分析

  • 分析
    1. 觀察,至少跑1天,看看生產的慢SQL情況。
    2. 開啟慢查詢日志,設置閾值,比如超過5秒鍾的就是慢SQL,並將它抓取出來。
    3. explain+慢SQL分析
    4. show profile
    5. 運維經理 or DBA,進行SQL數據庫服務器參數調優。
  • 總結
    1. 慢查詢的開啟並捕獲
    2. explain+慢SQL分析
    3. show profile查詢SQL在Mysql服務器里面的執行細節和生命周期情況
    4. SQL數據庫服務器的參數調優

查詢優化

  • 永遠小表驅動大表,類似嵌套循環Nested Loop

    img

    • 優化原則:小表驅動大表,即小的數據集驅動大的數據集。img

    • 當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來替代,何種最優需要具體問題具體分析。
    • 總結

      img

  • ORDER BY關鍵字優化

    • ORDER BY子句,盡量使用Index方式排序,避免使用FileSort方式排序

      • 建表SQL

        img

      • Case

        • case1

          img

        • case2

          img

      • 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,但是它會使用更多的空間。
        • 結論及引申出的問題

          • 由於單路是后出的,總體而言好過雙路

          • 但是用單路有問題

            img

            本來想省一次I/O操作,反而導致了大量的I/O操作,反而得不償失。(原因:數據的總大小超過sort_buffer的容量

    • 優化策略

      • 增大sort_buffer_size參數的設置
      • 增大max_length_for_sort_data參數的設置
      • Whyimg
    • 小總結

      img

  • 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%’;

        img

      • 開啟:set global slow_query_log=1;

        imgimg

        img

    • 那么開啟了慢查詢日志后,什么樣的SQL才會記錄到慢查詢日志里面呢

      img

    • 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並后續分析

        img

      • 查詢當前系統中有多少條慢查詢記錄:

        show global status like ‘%Slow_queries%’;

    • 配置版

      img

  • 日志分析工具mysqldumpslow

    • 在生產環境中,如果要手工分析日志,查找、分析SQL,顯然是個體力活,MySQL提供了日志分析工具mysqldumpslow。

    • 查看mysqldumpslow的幫助信息

      • mysqldumpslow --help
      • s:是表示按照何種方式排序
      • c:訪問次數
      • I:鎖定時間
      • r:返回記錄
      • t:查詢時間
      • al:平均鎖定時間
      • ar:平均返回記錄數
      • at:平均查詢時間
      • t:即為返回前面多少條的數據
      • g:后邊搭配一個正則匹配模式,大小寫不敏感
    • 工作常用參考

      img

批量數據腳本

  • 往表里插入1000w數據

  • 建表

    imgimg

  • 設置參數log_bin_trust_function_creators

    img

  • 創建函數,保證每條數據都不同

    • 隨機產生字符串

      img

    • 隨機產生部門編號

      img

  • 創建存儲過程

    img

    img

  • 調用存儲過程

    • dept:

      DELIMITER ;
      CALL insert_dept(100, 10);
      
    • emp:

      DELIMITER ;
      CALL insert_emp(100001, 500000);
      

Show Profile

  • 是什么:是mysql提供的可以用來分析當前會話中語句執行的資源消耗情況。可以用於SQL的調優的測量

  • 默認情況下,參數處於關閉狀態,並保存最近15次的運行結果

  • 分析步驟

    1. 是否支持,看看當前的mysql版本是否支持

      • show variables like ‘profiling’;img
    2. 開啟功能,默認是關閉,使用前需要開啟

      • set profiling = on;

        img

    3. 運行SQL

      • select * from emp group by id%10 limit 150000;
      • select * from emp group by id%20 order by 5;
    4. 查看結果,show profiles;

    5. 診斷SQL,show profile cpu, block io for query [上一步前面的問題SQL數字號碼];

      img

      • 參數備注

        img

    6. 日常開發需要注意的結論

      • converting HEAP to MyISAM:查詢結果太大,內存都不夠用了往磁盤上搬了

      • Creating tmp table:創建臨時表

        • 拷貝數據到臨時表
        • 用完再刪除
      • Copying to tmp table on disk:把內存中臨時表復制到磁盤,危險!!

      • locked

        img

全局查詢日志

  • 配置啟用

    img

  • 編碼啟用

    img

  • 永遠不要在生產環境開啟這個功能!

4. MySQL鎖機制

概述

  • 定義

    • 鎖是計算機協調多個進程並發訪問某一資源的機制。

      img

  • 生活購物

    img

  • 鎖的分類

    • 從對數據操作的類型(讀/寫)分
      • 讀鎖(共享鎖):針對同一份數據,多個讀操作可以同時進行而不會互相影響。
      • 寫鎖(排它鎖):當前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖。
    • 從對數據操作的粒度分
      • 表鎖
      • 行鎖

三鎖

  • 開銷、加鎖速度、死鎖、粒度、並發性能
  • 只能就具體應用的特點來說那種鎖更合適

表鎖(偏讀)

  • 特點:偏向MyISAM存儲引擎,開銷小,加鎖快;無死鎖;鎖定粒度大,發生鎖沖突的概率最高,並發度最低。

  • 案例分析

    • 建表SQL

      img

    • 手動增加表鎖

      • lock table 表名字 read(write), 表名字2 read(write), 其他;
    • 查看表上加過的鎖

      • show open tables;
    • 釋放表鎖

      • unlock tables;
    • 加讀鎖(我們為mylock表加read鎖(讀阻塞寫例子))

      imgimg

    • 加寫鎖(我們為mylock表加write鎖(MyISAM存儲引擎的寫阻塞讀例子))

      imgimg

  • 案例結論

    簡而言之,就是讀鎖會阻塞寫,但是不會阻塞讀。而寫鎖則會把讀和寫都阻塞。

    img

  • 表鎖分析

    • 看看哪些表被加鎖了: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屬性

      img

    • 並發事務處理帶來的問題

      • 更新丟失(Lost Update)

        img

      • 臟讀(Dirty Reads)

        img

      • 不可重復讀(Non-Repeatable Reads)

        img

      • 幻讀(Phantom Reads)

        img

    • 事務隔離級別

      img

  • 案例分析

    • 建表SQL

      img

    • 行鎖定基本演示

      img

    • 無索引行鎖升級為表鎖

      • 如果在更新數據的時候出現了強制類型轉換導致索引失效,使得行鎖變表鎖,即在操作不同行的時候,會出現阻塞的現象。
    • 間隙鎖危害

      img

      • 什么是間隙鎖:當我們用范圍條件而不是相等條件索引數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件范圍內但並不存在的記錄,叫做“間隙(GAP)”。InnoDB也會對這個“間隙”加鎖,這種鎖機制就是所謂的間隙鎖(Next-Key鎖)。
      • 危害:
        • 因為Query執行過程中通過范圍查找的話,會鎖定整個范圍內所有的索引鍵值,即使這個鍵值並不存在。
        • 間隙鎖有一個比較致命的弱點,就是當鎖定一個范圍鍵值之后,即使某些不存在的鍵值也會被無辜的鎖定,而造成在鎖定的時候無法插入鎖定鍵值范圍內的任何數據。在某些場景下這可能會對性能造成很大的危害。
    • 面試題:常考如何鎖定一行

      • select * from 表 where 某一行的條件 for update;

      img

  • 案例結論

    • InnoDB存儲引擎由於實現了行級鎖定,雖然在鎖定機制的實現方面所帶來的性能損耗可能比表級鎖定會更高一些,但是在整體並發處理能力方面要遠遠優於MyISAM的表級鎖定的。當系統並發量較高的時候,InnoDB的整體性能和MyISAM相比就會有比較明顯的優勢了。
    • 但是,InnoDB的行級鎖定同樣也有其脆弱的一面,當我們使用不當的時候,可能會讓InnoDB的整體性能表現不僅不能比MyISAM高,甚至可能會更差。
  • 行鎖分析

    • 如何分析行鎖定

      • 通過檢查InnoDB_row_lock狀態變量來分析系統上的行鎖的爭奪情況

        show status like ‘innodb_row_lock%’;

        img

      • 對各個狀態量的說明如下:

        • 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來進行數據同步

  • 三步驟+原理圖

    img

復制的基本原則

  • 每個slave只有一個master
  • 每個slave只能有一個唯一的服務器ID
  • 每個master可以有多個slave

復制的最大問題

  • 延時

一主一從常見配置

  • mysql版本一致且后台以服務運行

  • 主從都配置在[mysqld]結點下,都是小寫

  • 主機修改my.ini配置文件

    • 【必須】主服務器唯一ID
      • server-id=1
    • 【必須】啟用二進制日志
      • log-bin=自己本地的路徑/mysqlbin
      • img
    • 【可選】啟用錯誤日志
      • log-err=自己本地的路徑/mysqlerr
      • img
    • 【可選】根目錄
      • basedir=自己本地路徑
      • img
    • 【可選】臨時目錄
      • temdir=自己本地路徑
      • img
    • 【可選】數據目錄
      • datadir=自己本地路徑/Data/
      • img
    • read-only=0
      • 主機,讀寫都可以
    • 【可選】設置不要復制的數據庫
      • binlog-ignore-db=mysql
    • 【可選】設置需要復制的數據庫
      • binlog-do-db=需要復制的主數據庫名字
  • 從機修改my.cnf配置文件

    • 【必須】從服務器唯一ID
      • server-id=2
    • 【可選】啟用二進制日志
  • 因修改過配置文件,請主機+從機都重啟后台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

        img

      • 記錄下File和Position的值

    • 執行完此步驟后不要再操作主服務器MYSQL,防止主服務器狀態值變化

  • 在Linux從機上配置需要復制的主機

    • CHANGE MASTER TO MASTER_HOST='主機IP', MASTER_USER='zhangsan', MASTER_PASSWORD='123456', MASTER_LOG_FILE='file名字', MASTER_LOG_POS=position數字;

      img

      eg.

      img

    • 啟動從服務器復制功能

      • start slave;
    • show slave status\G【\G是為了以鍵值的形式顯示,好看一些】

      • 下面兩個參數都是Yes,則說明主從配置成功!

      • Slave_IO_Running:Yes

      • Slave_SQL_Running:Yes

        img

  • 主機新建庫、新建表、insert記錄,從機復制

  • 如何停止從服務復制功能

    • stop slave;

我的CSDN:https://blog.csdn.net/qq_21579045

我的博客園:https://www.cnblogs.com/lyjun/

我的Github:https://github.com/TinyHandsome

紙上得來終覺淺,絕知此事要躬行~

歡迎大家過來OB~

by 李英俊小朋友


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM