Mysql高級(索引優化等)總結

@[TOC]Mysql高級部分總結

mysql架構介紹

1、mysql在linux下的安裝

在linux下查看安裝目錄 ps -ef|grep mysql
在這裏插入圖片描述

參數 路徑 解釋 備註
–basedir /usr/bin 相關命令目錄 mysqladmin mysqldump等命令
–datadir /var/lib/mysql/ mysql數據庫文件的存放路徑
–plugin-dir /usr/lib64/mysql/plugin mysql插件存放路徑
–log-error /var/lib/mysql/jack.atguigu.err mysql錯誤日誌路徑
–pid-file /var/lib/mysql/jack.atguigu.pid 進程pid文件
–socket /var/lib/mysql/mysql.sock 本地連接時用的unix套接字文件
/usr/share/mysql 配置文件目錄 mysql腳本及配置文件
/etc/init.d/mysql 服務啓停相關腳本

2、配置編碼方式

  1. 查看字符集編碼
    show variables like ‘character%’;
    show variables like ‘%char%’;
    在這裏插入圖片描述
    默認的是客戶端和服務器都用了latin1,所以會亂碼
  2. 修改my.cnf
    在/usr/share/mysql/ 中找到my.cnf的配置文件,
    拷貝其中的my-huge.cnf 到 /etc/ 並命名爲my.cnf
    mysql 優先選中 /etc/ 下的配置文件
    然後修改my.cnf:
    [client]
    default-character-set=utf8
    [mysqld]
    character_set_server=utf8
    character_set_client=utf8
    collation-server=utf8_general_ci
    [mysql]
    default-character-set=utf8
  3. 重新啓動mysql
    但是原庫的設定不會發生變化,參數修改之對新建的數據庫生效
  4. 已生成的庫表字符集如何變更
    修改數據庫的字符集
    mysql> alter database mytest character set ‘utf8’;
    修改數據表的字符集
    mysql> alter table user convert to character set ‘utf8’;

3、mysql配置文件

  1. 二進制日誌log-bin
    log-bin 中存放了所有的操作記錄(寫?),可以用於恢復。
    my.cnf中的log-bin配置(默認關閉)
    在這裏插入圖片描述
  2. 錯誤日誌log-error
    默認是關閉的,記錄嚴重的警告和錯誤信息,每次啓動和關閉等信息
  3. 慢查詢日誌log
    可自定義“慢”的概念:0-10秒之間的一個數。
    慢查詢日誌會將超過這個查詢事件的查詢記錄下來,方便找到需要優化的 sql 。
    用於優化sql語句時使用
  4. 數據文件
    a.存放路徑
    windows下存放路徑:
    …\MySQLServer5.5\data目錄下很多數據庫文件
    linux存放路徑:默認路徑 /var/lib/mysql下,每個目錄代表一個數據庫
    可在配置文件中更改 /usr/share/mysql/ 下的 my-huge.cnf
    b.配置文件路徑:
    在這裏插入圖片描述
    c.Myisam存放方式:
    show create table mydb 查看創建 mydb 表的基本信息,其中包括了數據引擎。
    自帶的庫 mysql 庫中所有的表都是以 Myisam 引擎存的。通過 myisam 引擎存的表都是 一式三份,放在庫同名的文件夾下 /var/lib/mysql
    在這裏插入圖片描述
    d.Innodb存放方式:
    Innodb引擎將所有表的的數據都存在這裏面 /usr/share/mysql/ibdata1,而frm文件存放在庫同名的包下
    要想單獨存儲表,設置set innodb_file_per_table=on,設在爲 on 後 單獨以 table名.ibd 的文件名存儲或者修改全局變量:SET GLOBAL innodb_file_per_table=1;
    例如:
    create table mmm (id int(20) auto_increment ,name varchar(20),primary key(id));
    在這裏插入圖片描述

4、用戶權限管理

1)用戶管理

  1. 創建用戶
    create user zhang3 identified by ‘123123’;
    表示創建名稱爲zhang3的用戶,密碼設爲123123;

  2. 查看用戶
    select host,user,password,select_priv,insert_priv,drop_priv from mysql.user;
    select * from user\G;
    將 user 中的數據以行的形式顯示出來(針對列很長的表可以採用這個方法 )
    在這裏插入圖片描述
    host :表示連接類型
    % 表示所有遠程通過 TCP方式的連接
    IP 地址 如 (192.168.1.2,127.0.0.1) 通過指定ip地址進行的TCP方式的連接
    機器名 通過指定網絡中的機器名進行的TCP方式的連接
    ::1 IPv6的本地ip地址 等同於IPv4的 127.0.0.1
    localhost 本地方式通過命令行方式的連接 ,比如mysql -u xxx -p 123xxx 方式的連接。
    User:表示用戶名
    同一用戶通過不同方式鏈接的權限是不一樣的。
    password:密碼
    所有密碼串通過 password(明文字符串) 生成的密文字符串。加密算法爲MYSQLSHA1 ,不可逆 。
    mysql 5.7 的密碼保存到 authentication_string 字段中不再使用password 字段。
    select_priv , insert_priv等
    爲該用戶所擁有的權限。

2)修改密碼

修改當前用戶的密碼:
set password =password(‘123456’)

修改某個用戶的密碼:
update mysql.user set password=password(‘123456’) where user=‘li4’;
flush privileges; #所有通過user表的修改,必須用該命令才能生效

3) 修改用戶名

update mysql.user set user=‘li4’ where user=‘wang5’;
flush privileges; #所有通過user表的修改,必須用該命令才能生效。

4)刪除用戶

drop user 用戶名;
在這裏插入圖片描述
不要通過delete from user u where user=‘li4’ 進行刪除,系統會有殘留信息保留。

2)用戶管理

(1)授予權限

語法:grant 權限1,權限2,…權限n on 數據庫名稱.表名稱 to 用戶名@用戶地址 identified by ‘連接口令’;
該權限如果發現沒有該用戶,則會直接新建一個用戶。
比如
grant select,insert,delete,drop on atguigudb.* to li4@localhost ;
#給li4用戶用本地命令行方式下,授予atguigudb這個庫下的所有表的插刪改查的權限。

grant all privileges on . to joe@’%’ identified by ‘123’;
#授予通過網絡方式登錄的的joe用戶 ,對所有庫所有表的全部權限,密碼設爲123.
注意:就算 all privileges 了所有權限,grant_priv 權限也只有 root 才能擁有。

給 root 賦連接口令 grant all privileges on . to root@’%’;後新建的連接沒有密碼,需要設置密碼才能遠程連接。
update user set password=password(‘root’) where user=‘root’ and host=’%’;

(2)收回權限

語法:revoke 權限1,權限2,…權限n on 數據庫名稱.表名稱 from 用戶名@用戶地址 ;

REVOKE ALL PRIVILEGES ON mysql.* FROM joe@localhost;
#若賦的全庫的表就 收回全庫全表的所有權限

REVOKE select,insert,update,delete ON mysql.* FROM joe@localhost;
#收回mysql庫下的所有表的插刪改查權限
注意:必須用戶重新登錄後才能生效

(3)查看權限

查看當前用戶權限
show grants;

查看某用戶的全局權限
select * from user ;

查看某用戶的某庫的權限
select * from db;

查看某用戶的某個表的權限
select * from tables_priv;

5、mysql雜項配置

1)大小寫配置

windows系統默認大小寫不敏感,但是linux系統是大小寫敏感的
SHOW VARIABLES LIKE ‘%lower_case_table_names%’
在這裏插入圖片描述
默認爲0,大小寫敏感。
設置1,大小寫不敏感。創建的表,數據庫都是以小寫形式存放在磁盤上,對於sql語句都是轉換爲小寫對錶和DB進行查找。
設置2,創建的表和DB依據語句上格式存放,凡是查找都是轉換爲小寫進行。

設置變量常採用 set lower_case_table_names = 1; 的方式,但此變量是隻讀權限,所以需要在配置文件中改
當想設置爲大小寫不敏感時,要在my.cnf這個配置文件 [mysqld] 中加入 lower_case_table_names = 1 ,然後重啓服務器。
但是要在重啓數據庫實例之前就需要將原來的數據庫和錶轉換爲小寫,否則更改後將找不到數據庫名。
在進行數據庫參數設置之前,需要掌握這個參數帶來的影響,切不可盲目設置。

2)MySQL的sql_mode合理設置

sql_mode是個很容易被忽視的變量,默認值是空值,在這種設置下是可以允許一些非法操作的,比如允許一些非法數據的插入。在生產環境必須將這個值設置爲嚴格模式,所以開發、測試環境的數據庫也必須要設置,這樣在開發測試階段就可以發現問題
在這裏插入圖片描述
使用 set sql_mode=ONLY_FULL_GROUP_BY; 的方式設置會將之前的設置覆蓋掉
同時設置多個限制:set sql_mode=‘ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO’;

sql_mode常用值如下:
ONLY_FULL_GROUP_BY:
對於GROUP BY聚合操作,如果在SELECT中的列,沒有在GROUP BY中出現,那麼這個SQL是不合法的,因爲列不在GROUP BY從句中

NO_AUTO_VALUE_ON_ZERO:
該值影響自增長列的插入。默認設置下,插入0或NULL代表生成下一個自增長值。如果用戶 希望插入的值爲0,而該列又是自增長的,那麼這個選項就有用了。

STRICT_TRANS_TABLES:
在該模式下,如果一個值不能插入到一個事務表中,則中斷當前的操作,對非事務表不做限制
NO_ZERO_IN_DATE:
在嚴格模式下,不允許日期和月份爲零

NO_ZERO_DATE:
設置該值,mysql數據庫不允許插入零日期,插入零日期會拋出錯誤而不是警告。

ERROR_FOR_DIVISION_BY_ZERO:
在INSERT或UPDATE過程中,如果數據被零除,則產生錯誤而非警告。如 果未給出該模式,那麼數據被零除時MySQL返回NULL

NO_AUTO_CREATE_USER:
禁止GRANT創建密碼爲空的用戶

NO_ENGINE_SUBSTITUTION:
如果需要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常

PIPES_AS_CONCAT:
將"||"視爲字符串的連接操作符而非或運算符,這和Oracle數據庫是一樣的,也和字符串的拼接函數Concat相類似

ANSI_QUOTES:
啓用ANSI_QUOTES後,不能用雙引號來引用字符串,因爲它被解釋爲識別符

ORACLE:
設置等同:PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER.

6、mysql邏輯架構(***)

1)總體概述

       和其它數據庫相比,MySQL與衆不同的一點是它的架構可以在多種不同場景中應用併發揮良好作用。
       主要體現在存儲引擎的架構上,插件式的存儲引擎架構查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構可以根據業務的需求和實際需要選擇合適的存儲引擎。
在這裏插入圖片描述
1.連接層
最上層是一些客戶端和連接服務,包含本地sock通信和大多數基於客戶端/服務端工具實現的類似於tcp/ip的通信。主要完成一些類似於連接處理、授權認證、及相關的安全方案。在該層上引入了線程池的概念,爲通過認證安全接入的客戶端提供線程。同樣在該層上可以實現基於SSL的安全鏈接。服務器也會爲安全接入的每個客戶端驗證它所具有的操作權限。

2.服務層
2.1 Management Serveices & Utilities: 系統管理和控制工具
2.2 SQL Interface: SQL接口
接受用戶的SQL命令,並且返回用戶需要查詢的結果。比如select from就是調用SQL Interface
2.3 Parser: 解析器
SQL命令傳遞到解析器的時候會被解析器驗證和解析。
2.4 Optimizer: 查詢優化器。
SQL語句在查詢之前會使用查詢優化器對查詢進行優化。
用一個例子就可以理解: select uid,name from user where gender= 1;
優化器來決定先投影還是先過濾。
2.5 Cache和Buffer: 查詢緩存。
如果查詢緩存有命中的查詢結果,查詢語句就可以直接去查詢緩存中取數據。
這個緩存機制是由一系列小緩存組成的。比如表緩存,記錄緩存,key緩存,權限緩存等
緩存是負責讀,緩衝負責寫。
3.引擎層
存儲引擎層,存儲引擎真正的負責了MySQL中數據的存儲和提取,服務器通過API與存儲引擎進行通信。不同的存儲引擎具有的功能不同,這樣我們可以根據自己的實際需要進行選取。後面介紹MyISAM和InnoDB
4.存儲層
數據存儲層,主要是將數據存儲在運行於裸設備的文件系統之上,並完成與存儲引擎的交互

2)查詢流程分析

首先,mysql的查詢流程大致是:

  1. mysql客戶端通過協議與mysql服務器建連接,發送查詢語句,先檢查查詢緩存,如果命中(一模一樣的sql才能命中),直接返回結果,否則進行語句解析,也就是說,在解析查詢之前,服務器會先訪問查詢緩存(query
    cache)——它存儲SELECT語句以及相應的查詢結果集。如果某個查詢結果已經位於緩存中,服務器就不會再對查詢進行解析、優化、以及執行。它僅僅將緩存中的結果返回給用戶即可,這將大大提高系統的性能
  2. 語法解析器和預處理:首先mysql通過關鍵字將SQL語句進行解析,並生成一顆對應的“解析樹”。mysql解析器將使用mysql語法規則驗證和解析查詢;預處理器則根據一些mysql規則進一步檢查解析數是否合法
  3. 查詢優化器當解析樹被認爲是合法的了,並且由優化器將其轉化成執行計劃。一條查詢可以有很多種執行方式,最後都返回相同的結果。優化器的作用就是找到這其中最好的執行計劃
  4. 然後,mysql默認使用的BTREE索引,並且一個大致方向是:無論怎麼折騰sql,至少在目前來說,mysql最多隻用到表中的一個索引

7、mysql存儲引擎

1)mysql引擎介紹

1、InnoDB存儲引擎
InnoDB是MySQL的默認事務型引擎,它被設計用來處理大量的短期(short-lived)事務。使用B+樹,不僅緩存索引還緩存真實數據。除非有非常特別的原因需要使用其他的存儲引擎,否則應該優先考慮InnoDB引擎。行級鎖,適合高併發情況。

2、MyISAM存儲引擎
MyISAM提供了大量的特性,包括全文索引、壓縮、空間函數(GIS)等,但MyISAM不支持事務和行級鎖(myisam改表時會將整個表全鎖住),有一個毫無疑問的缺陷就是崩潰後無法安全恢復。使用B-樹,只緩存索引,不緩存真實數據。

3、Archive引擎
Archive存儲引擎只支持INSERT和SELECT操作,在MySQL5.1之前不支持索引。
Archive表適合日誌和數據採集類應用。適合低訪問量大數據等情況。
根據英文的測試結論來看,Archive表比MyISAM表要小大約75%,比支持事務處理的InnoDB表小大約83%。

4、Blackhole引擎
Blackhole引擎沒有實現任何存儲機制,它會丟棄所有插入的數據,不做任何保存。但服務器會記錄Blackhole表的日誌,所以可以用於複製數據到備庫,或者簡單地記錄到日誌。但這種應用方式會碰到很多問題,因此並不推薦。

5、CSV引擎
CSV引擎可以將普通的CSV文件作爲MySQL的表來處理,但不支持索引。
CSV引擎可以作爲一種數據交換的機制,非常有用。
CSV存儲的數據直接可以在操作系統裏,用文本編輯器,或者excel讀取。

6、Memory引擎
如果需要快速地訪問數據,並且這些數據不會被修改,重啓以後丟失也沒有關係,那麼使用Memory表是非常有用。Memory表至少比MyISAM表要快一個數量級。(使用專業的內存數據庫更快,如redis)。

7、Federated引擎
Federated引擎是訪問其他MySQL服務器的一個代理,儘管該引擎看起來提供了一種很好的跨服務器的靈活性,但也經常帶來問題,因此默認是禁用的。

2)查詢索引命令

#查看你的mysql現在已提供什麼存儲引擎:
mysql> show engines
在這裏插入圖片描述
#查看你的mysql當前默認的存儲引擎:
mysql> show variables like ‘%storage_engine%’;
在這裏插入圖片描述

索引優化分析

1、Sql性能下降的原因

  1. 查詢數據過多
  2. 關聯(join)太多表
  3. 沒有利用到索引
  4. 服務器調優及性能參數設置不合理(緩存、線程數等)

2、常見join查詢

1)sql順序

(1)書寫順序

在這裏插入圖片描述

(2)執行順序

在這裏插入圖片描述

(3)join理解

在這裏插入圖片描述
1 A、B兩表共有
select * from t_emp a inner join t_dept b on a.deptId = b.id;

2 A、B兩表共有+A的獨有
select * from t_emp a left join t_dept b on a.deptId = b.id;

3 A、B兩表共有+B的獨有
select * from t_emp a right join t_dept b on a.deptId = b.id;

4 A的獨有
select * from t_emp a left join t_dept b on a.deptId = b.id where b.id is null;

5 B的獨有
select * from t_emp a right join t_dept b on a.deptId = b.id where a.deptId is null;

6 AB全有
#MySQL Full Join的實現 因爲MySQL不支持FULL JOIN,下面是替代方法
#left join + union(可去除重複數據)+ right join
SELECT * FROM t_emp A LEFT JOIN t_dept B ON A.deptId = B.id
UNION
SELECT * FROM t_emp A RIGHT JOIN t_dept B ON A.deptId = B.id

7 A的獨有+B的獨有
SELECT * FROM t_emp A LEFT JOIN t_dept B ON A.deptId = B.id WHERE B.id IS NULL
UNION
SELECT * FROM t_emp A RIGHT JOIN t_dept B ON A.deptId = B.id WHERE A.deptId IS NULL;

3、Mysql索引簡介

在這裏插入圖片描述
左邊是數據表,一共有兩列七條記錄,最左邊的是數據記錄的物理地址
爲了加快Col2的查找,可以維護一個右邊所示的二叉查找樹,每個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就可以運用二叉查找在一定的複雜度內獲取到相應數據,從而快速的檢索出符合條件的記錄。

索引如果沒有特別指明,都是指B樹(多路搜索樹,並不一定是二叉樹)。除了B+樹這種類型之外,還有哈希索引等。索引一般也很大,所以以索引文件的形式存儲在磁盤上。

索引的優點:提高檢索效率,降低IO效率;降低排序成本,降低CPU效率

索引的缺點:索引也佔用了一定的空間;雖然提高了查詢速度,但是降低了更新錶速度,因爲更新表的同時還需要更新索引

索引的應用場景:
在這裏插入圖片描述

不適合建立索引的場景:
在這裏插入圖片描述

4、Mysql索引結構

1)B樹索引–Myisam索引

在這裏插入圖片描述

2)B+樹索引–Innodb索引

在這裏插入圖片描述
B+Tree與B-Tree 的區別:結論在內存有限的情況下,B+TREE 永遠比 B-TREE好。無限內存則後者方便
 1)B-樹的關鍵字和記錄是放在一起的,B+樹葉子節點中只有關鍵字和指向下一個節點的索引,記錄只放在葉子節點中。
  2)在B-樹中,越靠近根節點的記錄查找時間越快,只要找到關鍵字即可確定記錄的存在;而B+樹中每個記錄的查找時間基本是一樣的,都需要從根節點走到葉子節點,而且在葉子節點中還要再比較關鍵字。但因爲B+樹的非葉子節點不存放實際的數據,這樣每個節點可容納的元素個數比B-樹多,樹高比B-樹小,這樣帶來的好處是減少磁盤訪問次數。儘管B+樹找到一個記錄所需的比較次數要比B-樹多,但是一次磁盤訪問的時間相當於成百上千次內存比較的時間,因此實際中B+樹的性能可能還會好些,而且B+樹的葉子節點使用指針連接在一起,方便順序遍歷(例如查看一個目錄下的所有文件,一個表中的所有記錄等),這也是很多數據庫和文件系統使用B+樹的緣故。

3)聚簇索引與非聚簇索引

聚簇索引並不是一種單獨的索引類型,而是一種數據存儲方式。
術語‘聚簇’表示數據行和相鄰的鍵值進錯的存儲在一起。
如下圖,左側的索引就是聚簇索引,因爲數據行在磁盤的排列和索引排序保持一致。
在這裏插入圖片描述
聚簇索引的有點:
按照聚簇索引排列順序,查詢顯示一定範圍數據的時候,由於數據都是緊密相連,數據庫不用從多個數據塊中提取數據,所以節省了大量的io操作
聚簇索引的限制:
對於mysql數據庫目前只有innodb數據引擎支持聚簇索引,而Myisam並不支持聚簇索引。
由於數據物理存儲排序方式只能有一種,所以每個Mysql的表只能有一個聚簇索引。一般情況下就是該表的主鍵。
爲了充分利用聚簇索引的聚簇的特性,所以innodb表的主鍵列儘量選用有序的順序id,而不建議用無序的id,比如uuid這種。
這裏說明了主鍵索引爲何採用自增的方式:1、業務需求,有序 2、能使用到聚簇索引

4)Mysql索引分類

(1)主鍵索引

設定主鍵後會自動創建主鍵索引,Innodb爲聚簇索引

  1. 隨表一起建索引:
    CREATE TABLE customer (
    id INT(10) AUTO_INCREMENT ,
    customer_no VARCHAR(200),customer_name VARCHAR(200),
    PRIMARY KEY(id)
    );

  2. 單獨建主鍵索引:
    ALTER TABLE customer
    add PRIMARY KEY customer(customer_no);

  3. 刪除建主鍵索引:
    ALTER TABLE customer
    drop PRIMARY KEY ;

(2)單值索引

一個索引只包含單列,一個表可以有多個單值索引

  1. 隨表一起建索引:
    CREATE TABLE customer (
    id INT(10) AUTO_INCREMENT ,
    customer_no VARCHAR(200),customer_name VARCHAR(200),
    PRIMARY KEY(id),
    KEY (customer_name)
    );
  2. 單獨建單值索引:
    CREATE INDEX idx_customer_name ON customer(customer_name);
  3. 刪除索引:
    DROP INDEX idx_customer_name;

(3)唯一索引

索引列的值必須唯一,但可以爲空值

  1. 隨表一起建索引:
    CREATE TABLE customer (
    id INT(10) AUTO_INCREMENT ,
    customer_no VARCHAR(200),customer_name VARCHAR(200),
    PRIMARY KEY(id),
    KEY (customer_name)
    UNIQUE (customer_no)
    );
  2. 單獨建單值索引:
    CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no);
  3. 刪除索引:
    DROP INDEX idx_customer_no on customer ;

(4)複合索引

即一個索引包含多個列。在數據庫操作期間,複合索引比單值索引所需要的開銷更小(對於相同的多個列建索引)
當表的行數遠大於索引列的數目時可以使用複合索引

  1. 隨表一起建索引:
    CREATE TABLE customer (
    id INT(10) AUTO_INCREMENT ,
    customer_no VARCHAR(200),customer_name VARCHAR(200),
    PRIMARY KEY(id),
    KEY (customer_name)
    UNIQUE (customer_no)
    KEY (customer_no,customer_name)
    );
  2. 單獨建單值索引:
    CREATE INDEX idx_no_name ON customer(customer_no,customer_name);
  3. 刪除索引:
    DROP INDEX idx_no_name on customer ;

(5)基本語法

  • 有四種方式來創建數據表的索引:
    ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 該語句添加一個主鍵,這意味着索引值必須是唯一的,且不能爲NULL。
    ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 這條語句創建索引的值必須是唯一的(除了NULL外,NULL可能會出現多次)。
    ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出現多次。
    ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):該語句指定了索引爲 FULLTEXT ,用於全文索引。
  • 刪除:DROP INDEX [indexname] ON mytable
  • 查看:SHOW INDEX FROM mytable\G

5、性能分析

1)瓶頸

在這裏插入圖片描述
其中,最消耗CPU的活動是比較操作

2)Explain

(1)id

查詢中執行select子句或操作表的順序,分爲三種情況:

  1. id相同,執行順序由上至下 在這裏插入圖片描述
    此例中 先執行where 後的第一條語句 t1.id = t2.id 通過 t1.id 關聯 t2.id 。 而 t2.id 的結果建立在 t2.id=t3.id 的基礎之上。
  2. id不同,如果是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行在這裏插入圖片描述
  3. 同時存在在這裏插入圖片描述
    id如果相同,可以認爲是一組,從上往下順序執行;
    在所有組中,id值越大,優先級越高,越先執行
    衍生表 = derived2(2 表示由 id =2 的查詢衍生出來的表。type 肯定是 all ,因爲衍生的表沒有建立索引)

(2)select_type

查詢類型,主要是區別普通查詢、子查詢、聯合查詢等複雜情況
在這裏插入圖片描述

  1. simple在這裏插入圖片描述

  2. primary在這裏插入圖片描述

  3. derived在這裏插入圖片描述

  4. subquery在這裏插入圖片描述

  5. dependent subquery在這裏插入圖片描述
    dependent subquery 與 subquery 的區別
    依賴子查詢 : 子查詢結果爲 多值
    子查詢:查詢結果爲 單值

  6. uncacheable subquery在這裏插入圖片描述
    圖1 中的 @@ 表示查的環境參數 。沒辦法緩存

  7. union在這裏插入圖片描述

  8. union result在這裏插入圖片描述

(3)table

顯示這一行數據是關於哪張表的

(4)type(***)

  1. system
    表只有一行數據(等同於系統表),是const特例,一般不會出現,可以忽略。
  2. const
    表示通過索引一次就找到了,const用於比較Primary key或unique索引,因爲只匹配一行數據,所以很快。如在where中使用主鍵,mysql就能將這種查詢轉換爲常量在這裏插入圖片描述
  3. eq_ref
    唯一性索引掃描,對於每個索引建,表中只有一條記錄與之匹配。常見於主鍵或者唯一索引掃描在這裏插入圖片描述
  4. ref
    非唯一性索引掃描,返回匹配某個單獨值的所有行,本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然後,它可能會找到多個符合條件的行,所以數據查找和掃描的混合體在這裏插入圖片描述
  5. range
    只檢索給定範圍的行,使用一個索引來選擇行。key列顯示使用了哪個索引。一般就是在where語句中出現了between、<、>、in等的查詢。這種範圍掃描索引比全表掃描要好。在這裏插入圖片描述
  6. index
    full index scan,index和all的區別爲index類型只遍歷索引樹。這通常比all快,因爲索引文件通常比數據文件小。即all和index都是讀全表,但是index是從索引中讀取的,而all是從硬盤中讀取的。在這裏插入圖片描述
  7. all
    full table scan,將遍歷全表以找到匹配的行在這裏插入圖片描述
  8. index_merge
    在查詢過程中需要多個索引組合使用,通常出現在有or的關鍵字的sql中在這裏插入圖片描述
  9. ref_or_null
    對於某個字段既需要關聯條件,也需要null值的情況。在這裏插入圖片描述
  10. index_subquery
    利用索引來關聯子查詢,不再全表掃描在這裏插入圖片描述
  11. unique_subquery
    該聯接類型類似於index_subquery。子查詢中的唯一索引在這裏插入圖片描述
    結果值從最好到最壞依次是:
    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
    一般來說,得保證查詢至少達到range級別,最好能達到ref

(5)possible_keys

顯示可能應用在這張表中的索引,一個或多個。
查詢涉及到的字段上若存在索引,則該索引被列出,但不一定被實際查詢使用

(6)key

實際使用的索引,如果爲NULL,則沒有使用索引
查詢中若使用了覆蓋索引,則該索引和查詢的select字段重疊

(7)key_len

表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度
key_len字段能夠幫你檢查是否充分利用上了索引在這裏插入圖片描述在這裏插入圖片描述
第一組:key_len=deptno(int)+null + ename(varchar(20)3+動態 =4+1+203+2= 67
第二組:key_len=deptno(int)+null=4+1=5
在這裏插入圖片描述
在這裏插入圖片描述

(8)ref

顯示索引的哪一列被使用了,如果可能的話,是一個常數。哪些列或常量被用於查找索引列上的值在這裏插入圖片描述

(9)rows

rows列顯示MySQL認爲它執行查詢時必須檢查的行數,越少越好
在這裏插入圖片描述

(10)Extra

包含其他重要的額外信息

a.Using filesort

說明mysql會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取。mysql中無法利用索引完成的排序操作稱爲“文件排序”在這裏插入圖片描述

b.Using temporary

使用了臨時表保存中間結果,mysql在對查詢結果排序時使用臨時表。常見於排序order by和分組查詢group by在這裏插入圖片描述
在這裏插入圖片描述

c.Using index

表示響應的select操作中使用了覆蓋索引,避免訪問了表的數據行,提高了效率
如果同時出現using where,表明索引被用來執行索引鍵值的查找
如果沒有同時出現using where,表明索引只是用來讀取數據而非利用索引執行查找

索引是高效找到行的一個方法,但是一般數據庫也能使用索引找到一個列的數據,因此它不必讀取整個行。畢竟索引葉子節點存儲了它們索引的數據;當能通過讀取索引就可以得到想要的數據,那就不需要讀取行了。
覆蓋索引:一個索引包含了(或覆蓋了)[select子句]與查詢條件[Where子句]中所有需要的字段
例如:
select id , name from t_xxx where age=18;
有一個組合索引 idx_id_name_age_xxx 包含了(覆蓋了),id,name,age三個字段。查詢時直接將建立了索引的列讀取出來了,而不需要去查找所在行的其他數據。所以很高效。
(在數據量較大,固定字段查詢情況多時可以使用這種方法。)

注意:
如果要使用覆蓋索引,一定要注意select列表中只取出需要的列,不可select *,
因爲如果將所有字段一起做索引會導致索引文件過大,查詢性能下降。

d.Using where

表明使用where過濾

e.Using join buffer

使用了連接緩存在這裏插入圖片描述
出現在當兩個連接時,驅動表(被連接的表,left join 左邊的表。inner join 中數據少的表) 沒有索引的情況下。
給驅動表建立索引可解決此問題。且 type 將改變成 ref

f.impossible where

where子句的值總是false,不能用來獲取任何元素在這裏插入圖片描述

g.select tables optimized away

在沒有group by子句的情況下,基於索引優化min/max操作或者對於myisam存儲引擎優化count(*)操作,不必等到執行階段再進行計算,查詢執行計劃生成的階段即完成優化

myisam 中會維護總行數(還有其他參數)這個參數,所以在執行查詢時不會進行全表掃描。而是直接讀取這個數。
但會對增刪產生一定的影響。根據業務情況決定誰好誰壞
innodb 中沒有這個機制
在這裏插入圖片描述

6、查詢優化

1)索引失效分析

(1)全值匹配我最愛

在這裏插入圖片描述
在這裏插入圖片描述

(2)最佳左前綴法則(***)

即如果索引包含多列,則查詢的時候從索引的最左前列開始並不跳過索引中列
注意:

  • and 忽略左右關係,即使沒有沒有按順序由於優化器的存在,會自動優化
  • 假設建立了 idx_nameAge 索引id 爲主鍵,當使用覆蓋索引的方式時,“select name/age/id from staffs where age=10” 後面沒有其他沒有索引的字段條件,即使不是以 name 開頭,也會使用 idx_nameAge索引。即 select 後的字段有索引,where 後的字段也有索引,則無關執行順序
    在這裏插入圖片描述

(3)在索引列上做計算、函數類型轉換

不要在索引列上做任何操作(計算、函數、(手動或自動)類型轉換),會導致索引失效而轉向全表掃描
在這裏插入圖片描述

(4)存儲引擎不能使用索引中範圍條件右邊的列

若有索引則能使用到索引,範圍條件右邊的索引會失效(範圍條件右邊與範圍條件使用的同一個組合索引,右邊的纔會失效。若是不同索引則不會失效)
在這裏插入圖片描述

(5)儘量使用覆蓋索引,減少select *

在這裏插入圖片描述

(6)使用不等於(!=或<>)索引會失效導致全表掃描

索引 idx_nameAgeJob
idx_name
使用 != 和 <> 的字段索引失效( != 針對數值類型。 <> 針對字符類型)
前提and 後的字段在混合索引中的位置比當前字段靠後 where age != 10 and name=‘xxx’ ,這種情況下,mysql自動優化,將 name=‘xxx’ 放在 age !=10 之前,name 依然能使用索引。只是 age 的索引失效)

在這裏插入圖片描述

(7)is not null失效is null不會失效

在這裏插入圖片描述

(8)like模糊搜索以%開頭導致索引失效

like ‘%abc%’ type 類型會變成 all
like ‘abc%’ type 類型爲 range ,算是範圍,可以使用索引
在這裏插入圖片描述
如果一定要出現%字符串%的情況,用覆蓋索引來解決,即只select索引字段,不檢索非索引字段。這樣type爲index,比全表掃描提高了性能

(9)字符串不加單引號導致索引失效

在這裏插入圖片描述

(10)用or連接導致索引失效

在這裏插入圖片描述

2)例題分析

【建表語句】
create table test03(
id int primary key not null auto_increment,
c1 char(10),
c2 char(10),
c3 char(10),
c4 char(10),
c5 char(10)
);

insert into test03(c1,c2,c3,c4,c5) values(‘a1’,‘a2’,‘a3’,‘a4’,‘a5’);
insert into test03(c1,c2,c3,c4,c5) values(‘b1’,‘b2’,‘b3’,‘b4’,‘b5’);
insert into test03(c1,c2,c3,c4,c5) values(‘c1’,‘c2’,‘c3’,‘c4’,‘c5’);
insert into test03(c1,c2,c3,c4,c5) values(‘d1’,‘d2’,‘d3’,‘d4’,‘d5’);
insert into test03(c1,c2,c3,c4,c5) values(‘e1’,‘e2’,‘e3’,‘e4’,‘e5’);

select * from test03;

【建索引】
create index idx_test03_c1234 on test03(c1,c2,c3,c4);
show index from test03;

問題:我們創建了複合索引idx_test03_c1234 ,根據以下SQL分析下索引使用情況?

explain select * from test03 where c1=‘a1’;
explain select * from test03 where c1=‘a1’ and c2=‘a2’;
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c3=‘a3’;
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c3=‘a3’ and c4=‘a4’;

1)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c3=‘a3’ and c4=‘a4’;
2)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c4=‘a4’ and c3=‘a3’;
3)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c3>‘a3’ and c4=‘a4’;
4)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c4>‘a4’ and c3=‘a3’;
5)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c4=‘a4’ order by c3;
c3作用在排序而不是查找
6)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ order by c3;
7)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ order by c4;
出現了filesort
8)
8.1
explain select * from test03 where c1=‘a1’ and c5=‘a5’ order by c2,c3;

只用c1一個字段索引,但是c2、c3用於排序,無filesort
8.2
explain select * from test03 where c1=‘a1’ and c5=‘a5’ order by c3,c2;

出現了filesort,我們建的索引是1234,它沒有按照順序來,3 2 顛倒了
9)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ order by c2,c3;
10)
explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c5=‘a5’ order by c2,c3;
用c1、c2兩個字段索引,但是c2、c3用於排序,無filesort

explain select * from test03 where c1=‘a1’ and c2=‘a2’ and c5=‘a5’ order by c3,c2;

本例有常量c2的情況,和8.2對比

explain select * from test03 where c1=‘a1’ and c5=‘a5’ order by c3,c2; filesort
11)
explain select * from test03 where c1=‘a1’ and c4=‘a4’ group by c2,c3;
12)
explain select * from test03 where c1=‘a1’ and c4=‘a4’ group by c3,c2;

Using where; Using temporary; Using filesort

3)總結

  • 對於單鍵索引,儘量選擇針對當前查詢過濾性更好的索引
  • 對於組合索引,當前查詢過濾性最好的字段在索引字段的順序中位置越靠前越好
  • 選擇組合索引時,儘量選擇能夠包含當前查詢中where子句中更多字段的索引

4)關聯查詢優化

  • 保證被驅動表中的join字段已經被索引,被驅動表 join 後的表爲被驅動表 (需要被查詢)
  • left join時,小表作爲驅動表,大表作爲被驅動表
  • inner join時,mysql 自動選擇小表作爲驅動表。因爲驅動表無論如何都會被全表掃描,所以掃描次數越少越好
  • 子查詢儘量不要放在被驅動表中,有可能用不到索引
    例如:select a.name ,bc.name from t_emp a left join
    (select b.id , c.name from t_dept b
    inner join t_emp c on b.ceo = c.id)bc
    on bc.id = a.deptid.
    上段查詢中用到了子查詢,必然 bc 表沒有索引。肯定會進行全表掃描
    上段查詢 可以直接使用 兩個 left join 優化
    select a.name , c.name from t_emp a
    left join t_dept b on a.deptid = b.id
    left join t_emp c on b.ceo=c.id
    所有條件都可以使用到索引
    若必須用到子查詢,可將子查詢設置爲驅動表,,因爲驅動表的type 肯定是 all,而子查詢返回的結果表沒有索引,必定也是all

5)子查詢優化–in&exists

有索引的情況下,用inner join 是最好的,其次是 in,exists最糟糕。無索引的情況下用小表驅動大表,因爲join 方式需要distinct,沒有索引distinct消耗性能較大,所以 exists性能最佳 ,in其次, join性能最差。無索引的情況下大表驅動小表,in 和 exists 的性能應該是接近的 ,都比較糟糕 ,exists稍微好一點 超不過5% ,但是inner join 由於使用了 join buffer 所以快很多,如果left join 則最慢

6)order by關鍵字優化

mysql支持兩種方式排序,index和filesort。Index值mysql索引本身完成排序,效率高,filesort方式效率較低

(1)order by子句儘量使用索引排序,避免filesort排序

在這裏插入圖片描述
在這裏插入圖片描述

(2)儘可能在索引列上完成排序,遵循最佳左前綴

在這裏插入圖片描述
第二種中,where a = const and b > const order by b , c 不會出現 using filesort b , c 兩個銜接上了
但是:where a = const and b > const order by c 將會出現 using filesort 。因爲 b 用了範圍索引,斷了。而上一個 order by 後的b 用到了索引,所以能銜接上 c

(3)如果不在索引列上,filesort有兩種算法:雙路排序和單路排序

7)limit優化

在這裏插入圖片描述
在這裏插入圖片描述
實踐證明: 當order by 後的字段(a)有索引且sql 中有 limit 時,
當 select id 或a索引時,顯示 using index
當 select 後的字段包含非a字段,將顯示 using filesort

8)group by 優化

在這裏插入圖片描述

9)distinct

在這裏插入圖片描述

查詢截取分析

1、慢查詢日誌

1)慢查詢日誌概述

  • MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中。

  • long_query_time的默認值爲10,意思是運行10秒以上的語句(大於10秒纔行,等於不會放入)。

  • 默認情況下,MySQL數據庫沒有開啓慢查詢日誌,需要我們手動來設置這個參數。當然,如果不是調優需要的話,一般不建議啓動該參數,因爲開啓慢查詢日誌會或多或少帶來一定的性能影響。慢查詢日誌支持將日誌記錄寫入文件

  • 默認情況下slow_query_log的值爲OFF,表示慢查詢日誌是禁用的,可以通過設置slow_query_log的值來開啓:SHOW VARIABLES LIKE ‘%slow_query_log%’;
    在這裏插入圖片描述

  • 使用set global slow_query_log=1開啓了慢查詢日誌只對當前數據庫生效,如果MySQL重啓後則會失效。
    在這裏插入圖片描述
    但是設置全局變量需要重新開一個新的會話才能看到改變
    在這裏插入圖片描述
    或者設置會話變量:
    在這裏插入圖片描述
    如果要永久生效,就必須修改配置文件my.cnf(其它系統變量也是如此)
    修改my.cnf文件,[mysqld]下增加或修改參數
    slow_query_log 和slow_query_log_file後,然後重啓MySQL服務器。也即將如下兩行配置進my.cnf文件
    slow_query_log =1
    slow_query_log_file=/var/lib/mysql/atguigu-slow.log
    關於慢查詢的參數slow_query_log_file ,它指定慢查詢日誌文件的存放路徑,系統默認會給一個缺省的文件host_name-slow.log(如果沒有指定參數slow_query_log_file的話)

  • 實驗記錄一條慢sql
    在這裏插入圖片描述

  • 查詢當前記錄的慢sql條數: show global status like ‘%Slow_queries%’;
    在這裏插入圖片描述

2)分析工具–mysqldumpslow

查看參數:
在這裏插入圖片描述
常用命令:
得到返回記錄集最多的10個SQL
mysqldumpslow -s r -t 10 /var/lib/mysql/atguigu-slow.log

得到訪問次數最多的10個SQL
mysqldumpslow -s c -t 10 /var/lib/mysql/atguigu-slow.log

得到按照時間排序的前10條裏面含有左連接的查詢語句
mysqldumpslow -s t -t 10 -g “left join” /var/lib/mysql/atguigu-slow.log

另外建議在使用這些命令時結合 | 和more 使用 ,否則有可能出現爆屏情況
mysqldumpslow -s r -t 10 /var/lib/mysql/atguigu-slow.log | more

2、show profile

mysql提供可以用來分析當前會話中語句執行的資源消耗情況,可以用於sql調優的測量。默認情況下是關閉的,並保存最近15次的運行結果。

1)分析步驟

  • 查看並開啓
    show variables like ‘profiling’;
    set profiling=1;
    在這裏插入圖片描述

  • 運行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 n;(n爲上一步sql的數字號碼)
    在這裏插入圖片描述
    type:
    | ALL --顯示所有的開銷信息
    | BLOCK IO --顯示塊IO相關開銷
    | CONTEXT SWITCHES --上下文切換相關開銷
    | CPU --顯示CPU相關開銷信息
    | IPC --顯示發送和接收相關開銷信息
    | MEMORY --顯示內存相關開銷信息
    | PAGE FAULTS --顯示頁面錯誤相關開銷信息
    | SOURCE --顯示和Source_function,Source_file,Source_line相關的開銷信息
    | SWAPS --顯示交換次數相關開銷的信息

2)日常開發需要注意的項

  • converting heap to myisam:查詢結果太大,內存都不夠用往磁盤上寫入了
  • creating tmp table:創建了臨時表
  • copying to tmp table on disk:把內存中臨時表複製到磁盤,要注意!
  • locked

3、全局查詢日誌

語法:set global general_log=1;

#全局日誌可以存放到日誌文件中,也可以存放到Mysql系統表中。存放到日誌中性能更好一些,存儲到表中
set global log_output=‘TABLE’;
此後 ,你所編寫的sql語句,將會記錄到mysql庫裏的general_log表,可以用下面的命令查看
select * from mysql.general_log;
注意:不要再生產環境中開啓此功能

Mysql鎖機制

1、定義

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

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

鎖從對數據操作的粒度可分爲表鎖和行鎖和頁鎖,頁鎖的鎖定粒度介於行鎖和表鎖之間。

2、表鎖

偏向Myisam,開銷小、加鎖快、無死鎖、鎖定粒度大、發生鎖衝突概率最高,併發度最低,適合讀。

【手動增加表鎖】
lock table 表名字1 read(write),表名字2 read(write),其它;
【查看錶上加過的鎖】
show open tables;
【釋放表鎖】
unlock tables;
在這裏插入圖片描述

1)加讀鎖

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

2)加寫鎖

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

3)總結

MyISAM在執行查詢語句(SELECT)前,會自動給涉及的所有表加讀鎖,在執行增刪改操作前,會自動給涉及的表加寫鎖。
MySQL的表級鎖有兩種模式:
表共享讀鎖(Table Read Lock)
表獨佔寫鎖(Table Write Lock)
結論:
對MyISAM表進行操作,會有以下情況:
1、對MyISAM表的讀操作(加讀鎖),不會阻塞其他進程對同一表的讀請求,但會阻塞對同一表的寫請求。只有當讀鎖釋放後,纔會執行其它進程的寫操作。
2、對MyISAM表的寫操作(加寫鎖),會阻塞其他進程對同一表的讀和寫操作,只有當寫鎖釋放後,纔會執行其它進程的讀寫操作。
簡而言之,就是讀鎖會阻塞寫,但是不會堵塞讀。而寫鎖則會把讀和寫都堵塞

3、行鎖

偏向InnoDB存儲引擎,開銷大、加鎖慢、會出現死鎖、鎖定粒度最小、發生鎖衝突的概率最低、併發度也最高。
InnoDB與Myisam最大的兩點不同:一是支持事物,二十採用了行級鎖。
行鎖示例:
在這裏插入圖片描述
如果索引失效,行鎖會變表鎖
在這裏插入圖片描述

1)讀鎖

共享鎖(Share Lock)

共享鎖又稱讀鎖,是讀取操作創建的鎖。其他用戶可以併發讀取數據,但任何事務都不能對數據進行修改(獲取數據上的排他鎖),直到已釋放所有共享鎖。
如果事務T對數據A加上共享鎖後,則其他事務只能對A再加共享鎖,不能加排他鎖。獲准共享鎖的事務只能讀數據,不能修改數據。

用法
SELECT … LOCK IN SHARE MODE;

在查詢語句後面增加 LOCK IN SHARE MODE ,Mysql會對查詢結果中的每行都加共享鎖,當沒有其他線程對查詢結果集中的任何一行使用排他鎖時,可以成功申請共享鎖,否則會被阻塞。其他線程也可以讀取使用了共享鎖的表(行?),而且這些線程讀取的是同一個版本的數據。

2)寫鎖

排他鎖(eXclusive Lock)

共享鎖又稱寫鎖,如果事務T對數據A加上排他鎖後,則其他事務不能再對A加任任何類型的封鎖。獲准排他鎖的事務既能讀數據,又能修改數據。

用法

SELECT … FOR UPDATE;

   在查詢語句後面增加 FOR UPDATE ,Mysql會對查詢結果中的每行都加排他鎖,當沒有其他線程對查詢結果集中的任何一行使用排他鎖時,可以成功申請排他鎖,否則會被阻塞。

3)間隙鎖

【什麼是間隙鎖】
當我們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內但並不存在的記錄,叫做“間隙(GAP)”,
InnoDB也會對這個“間隙”加鎖,這種鎖機制就是所謂的間隙鎖(GAP Lock)。

【危害】
因爲Query執行過程中通過過範圍查找的話,他會鎖定整個範圍內所有的索引鍵值,即使這個鍵值並不存在。
間隙鎖有一個比較致命的弱點,就是當鎖定一個範圍鍵值之後,即使某些不存在的鍵值也會被無辜的鎖定,而造成在鎖定的時候無法插入鎖定鍵值範圍內的任何數據。在某些場景下這可能會對性能造成很大的危害
在這裏插入圖片描述

4)行鎖分析

  • 通過檢查InnoDB_row_lock狀態變量來分析系統上的行鎖的爭奪情況 mysql>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(等待總時長)
    尤其是當等待次數很高,而且每次等待時長也不小的時候,我們就需要分析系統中爲什麼會有如此多的等待,然後根據分析結果着手指定優化計劃。

  • 通過SELECT * FROM information_schema.INNODB_TRX\G; 來查詢正在被鎖阻塞的sql語句。

主從複製

1)原理

在這裏插入圖片描述
MySQL複製過程分成三步:
1 master將改變記錄到二進制日誌(binary log)。這些記錄過程叫做二進制日誌事件(binary log events);
2 slave將master的binary log events拷貝到它的中繼日誌(relay log);
3 slave重做中繼日誌中的事件,將改變應用到自己的數據庫中。 MySQL複製是異步的且串行化的
注意:
1.每個slave只能有一個master,但一個master可以用多個slav且每個slave只能有一個唯一的id
2.主從複製最大的問題就是會出現延遲

2)一主一從常見配置

(1)主、從服務器修改配置文件

  • 主服務器修改配置文件my.ini文件:

在這裏插入圖片描述
在這裏插入圖片描述

從服務器修改my.cnf配置文件
在這裏插入圖片描述
在這裏插入圖片描述

(2)重啓mysql服務

因都修改過配置文件,所以都需要重啓

(3)關閉防火牆

在這裏插入圖片描述

(4)在window主服務器上建立賬戶並授權slave

在這裏插入圖片描述

(5)在linux從機上配置需要複製的主機

在這裏插入圖片描述

(6)停止主從複製功能

從服務器上:stop slave;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章