MySQL索引及優化

MySQL

一、MySQL的架構總覽

1

查詢優化器 :MySQL會對咱們的SQL語句進行優化;html

存儲引擎mysql

  • InnoB:支持事務、行級鎖、基於XA協議的分佈式事務;適用於高併發場景(5.5的默認存儲引擎)
  • MyISAM:不支持事務、表級鎖;性能優先
查詢數據庫支持的存儲引擎
show engines;

SQL優化sql

  • 緣由:執行時間長、等待時間長、索引失效、參數設置不合理(緩衝區、線程數)
  • SQL優化主要是優化索引

索引數據庫

  • MySQL用來幫助高效查詢的數據結構(B-Tree)

二、B-Tree和B+Tree

B-Tree (平衡多路查找樹):能夠顯著減小定位記錄時所經歷的中間過程,從而加快存取速度服務器

一個M階的B-Tree具備的特性
    > 每一個節點最多有m個孩子
    > 根節點的孩子數>=2(前提:樹的高度大於一)
    > 除了根節點和葉子結點,其餘節點的孩子數(ceil(m/2));向上取整
    > 全部的葉子結點都在一層
    > 各個結點包含n個關鍵字信息:(P0,K1,P1,K2,P2......Kn,Pn)
        其中
        - Ki(i=1,2......n)爲關鍵字,且K(i-1)<Ki,即從小到大排序
        - 關鍵字的個數n必須知足:[ceil(m/2)-1,m-1]
        - Pi指向子樹,且指針P(i-1)所指向的子樹結點中全部關鍵字均小於Ki。即:父結點中任何關鍵字的左孩子都小於它,右孩子大於它

B-Tree示例圖:數據結構

2

B+Tree :B+Tree是在B-Tree基礎上的一種優化,使其更適合實現外存儲索引結構,InnoDB存儲引擎就是用B+Tree實現其索引結構架構

B+Tree相對於B-Tree有幾點不一樣:

    非葉子節點只存儲鍵值信息;
    全部葉子節點之間都有一個鏈指針;
    數據記錄都存放在葉子節點中;

B+Tree示例圖:併發


三、索引

1)單值索引

單列;一個表能夠有多個單值索引分佈式

建立索引高併發

-- 給users表的name屬性建立索引
create index name_index on users(name) ;
alter table users add index name_index(name);

-- 查詢索引
show index from users(表名);
-- 刪除索引
drop index name_index(索引名) on users(表名);

2)惟一索引

單列;一個表只有一個惟一索引;主鍵默認惟一索引

-- 給users表的id屬性建立索引
create unique index id_index on users(id) ;
alter table users add unique index id_index(id);

3)複合索引

多列;

-- 給users表的birthday,name屬性建立索引
-- 先找birthday,若是birthday相同則再去name找
create index birthday_name_index on users(birthday,name) ;
alter table users add index birthday_name_index(birthday,name);

4)主鍵索引

主鍵索引不能爲null,單值索引能夠爲null;

5)聚簇索引和非聚簇索引

聚簇索引:主索引葉子結點指向數據,輔助索引葉子結點指向對應數據的主索引;

非聚簇索引:索引表和數據表分開,主索引和輔助索引的葉子結點都指向數據;

6) 索引的優劣

優點:以快速檢索,減小I/O次數,加快檢索速度;根據索引分組和排序,能夠加快分組和排序;

劣勢:索引自己也是表,所以會佔用存儲空間。索引的維護和建立須要時間成本,這個成本隨着數據量增大而增大;構建索引會下降數據表的修改操做(刪除,添加,修改)的效率,由於在修改數據表的同時還須要修改索引表。

四、SQL執行計劃

1)分析SQL執行計劃

使用關鍵字explain ,分析分析SQL執行計劃

mysql> explain select * from user;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+

2)準備數據

-- 建表準備數據
CREATE TABLE course(
  cid INT(2),
  cname VARCHAR(10),
  tid INT(2)
);
CREATE TABLE teacher(
  tid INT(2),
  tname VARCHAR(10),
  tcid INT(2)
);
CREATE TABLE teacher_card(
  tcid INT(2)teacher_card,
  tcdesc VARCHAR(10)
);

3)執行計劃中的屬性詳解

可參考博客

-- 查詢課程編號爲2 或 教師證爲3的老師
mysql> explain SELECT *
    -> FROM teacher t,course c, teacher_card tc
    -> WHERE t.tid=c.tid AND t.tcid= tc.tcid AND (c.cid=2 OR tc.tcid=3);
+----+-------------+-------+------
| id | select_type | table | ...
|  1 | SIMPLE      | t     | ...                         
|  1 | SIMPLE      | tc    | ... 
|  1 | SIMPLE      | c     | ... 

-- 在鏈接查詢中,id值相同
-- t - tc - c 已知記錄數順序 3- 3- 4;==>執行順序:記錄數少的先執行;
-- 1- 查詢產生的笛卡爾積
-- >  3 * 3 = 9 ;9 * 4 = 36
-- 2- 若是記錄數多的先執行
-- >  4 * 3 = 12 ; 12  * 3= 36
-- 雖然最後的笛卡爾積數量不變,可是中間產生笛卡爾積數量不同,第一種中間記錄數少,佔用的資源少;

-- 查詢教英語的老師描述
mysql> EXPLAIN SELECT tc.tcdesc
    -> FROM teacher_card tc
    -> WHERE tc.tcid = (SELECT t.tcid FROM teacher t
    -> WHERE t.tid = (SELECT c.tid FROM course c WHERE c.cname = '英語'));
+----+-------------+-------+------+
| id | select_type | table | ...
|  1 | PRIMARY     | tc     | ... 
|  2 | SUBQUERY    | t    | ... 
|  3 | SUBQUERY    | c     | ... 

-- 在子查詢中,id有 3-2-1 執行順序 c-t-tc
-- 越內層的子查詢,越先執行
  • id : id值相同 ,從上往下順序執行 ;id值不一樣,從大到小順序執行;

  • select_type

    • SIMPLE:簡單查詢(不包括鏈接查詢,子查詢)
    • PRIMARY :最外層的查詢
    • SUNQUERY:非最外層查詢
    • DERIVED:衍生查詢(在查詢的時候用到了臨時表)
    • UNION RESULT:鏈接查詢時產生的表
  • type

    SYSTEM>CONST> EQ_REF> REF>RANGE>IANDEX> ALL(要對type優化,前提是有索引)

    SYSTEM:只有一條數據的系統表、主查詢的衍生表只有一條數據;(查詢結果只有一條)

    -- 例如,這條SQL的主查詢知足條件爲system類型
    mysql>ALTER TABLE teacher ADD INDEX tid_index(tid);
    mysql> EXPLAIN SELECT *
        -> FROM (SELECT * FROM teacher t WHERE t.tid = 1) t_derived;
    +----+-------------+------------+--------+---------------+-----------+---------+------+--
    | id | select_type | table      | type   | possible_keys | key       | key_len | ref  | 
    +----+-------------+------------+--------+---------------+-----------+---------+------+---
    |  1 | PRIMARY     | <derived2> | system | NULL          | NULL      | NULL    | NULL |   
    |  2 | DERIVED     | t          | ref    | tid_index     | tid_index | 5       |      |   
    +----+-------------+------------+--------+---------------+-----------+---------+------+--

    CONST:在主鍵索引或惟一索引的狀況下,只查詢一條數據;(查詢結果只有一條)

    mysql> ALTER TABLE teacher ADD PRIMARY KEY tid_primary(tid);
    -- 主鍵索引是tid,type是const
    mysql> EXPLAIN SELECT * FROM teacher t WHERE t.tid = 1;
    +----+-------------+-------+-------+-------------------+---------+---------+-------+------
    | id | select_type | table | type  | possible_keys     | key     | key_len | ref   | rows 
    +----+-------------+-------+-------+-------------------+---------+---------+-------+------
    |  1 | SIMPLE      | t     | const | PRIMARY,tid_index | PRIMARY | 4       | const |    1 
    +----+-------------+-------+-------+-------------------+---------+---------+-------+-----
    
    -- 查詢tcid ,type 是 all
    mysql> EXPLAIN SELECT * FROM teacher t WHERE t.tcid = 1;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra 
    +----+-------------+-------+------+---------------+------+---------+------+------+-------
    |  1 | SIMPLE      | t     | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using 
    +----+-------------+-------+------+---------------+------+---------+------+------+-------

    EQ_REF:惟一性索引; 對於每一個索引鍵的查詢,必須返回有且只有一條數據; (查詢結果多條)

    -- 將列改成惟一性索引
    mysql> ALTER TABLE teacher ADD UNIQUE INDEX tcid_index(tcid);
    mysql> ALTER TABLE teacher_card ADD PRIMARY KEY tcid_primary(tcid);
    -- 此時teacher和teacher_card的數據條數爲3
    -- 查詢索引鍵,若兩邊數據條數一致(必須是惟一性索引)
    mysql> EXPLAIN SELECT t.tcid FROM teacher t,teacher_card tc WHERE t.tcid = tc.tcid;
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | eq_ref | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------

    REF:非惟一性索引; 對於每一個索引鍵的查詢,返回n條數據(能夠n=0);(查詢結果多條)

    -- 給teacher添加一條數據
    -- 查詢索引鍵,若兩邊數據條數不一致(能夠爲非惟一性索引)
    mysql> EXPLAIN SELECT t.tcid FROM teacher t,teacher_card tc WHERE t.tcid = tc.tcid;
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | ref    | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------

    RANGE:檢索指定範圍的行的索引鍵 (關鍵字in有時候會失效);(查詢結果多條)

    mysql> EXPLAIN SELECT t.tcid FROM teacher t WHERE t.tcid > 1;
    +----+-------------+-------+-------+---------------+------------+---------+------+------+-
    | id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | 
    +----+-------------+-------+-------+---------------+------------+---------+------+------+-
    |  1 | SIMPLE      | t     | range | tcid_index    | tcid_index | 5       | NULL |    3 | 
    +----+-------------+-------+-------+---------------+------------+---------+------+------+-

    INDEX:查詢數據的索引鍵;

    ALL:查詢全部數據;

  • possible_keys:預測用到的索引(實際可能發生索引失效)

  • key:實際用到的索引

  • key_len :索引的計算長度

    # char和varchar類型key_len計算公式
    varchr(N)變長字段且容許NULL   =\
    N * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(變長字段)
    varchr(N)變長字段且不容許NULL = \
    N * ( character set:utf8=3,gbk=2,latin1=1)+2(變長字段)
    char(N)固定字段且容許NULL = N * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)
    char(N)固定字段且容許NULL = N * ( character set:utf8=3,gbk=2,latin1=1)
    
    # 與數據類型長度無關
    # 數值數據的key_len計算公式:
    TINYINT容許NULL = 1 + 1(NULL)
    TINYINT不容許NULL = 1
    SMALLINT容許爲NULL = 2+1(NULL)
    SMALLINT不容許爲NULL = 2
    INT容許爲NULL = 4+1(NULL)
    INT不容許爲NULL = 4
    
    # 日期時間型的key_len計算:(針對mysql5.5)
    DATETIME容許爲NULL = 8 + 1(NULL)
    DATETIME不容許爲NULL = 8
    TIMESTAMP容許爲NULL = 4 + 1(NULL)
    TIMESTAMP不容許爲NULL = 4
  • ref:指明當前表參照的字段(null,const常量,參照的字段)

    -- tc 表參照了mydb3.t.tcid 字段
    mysql> EXPLAIN SELECT t.tcid FROM teacher t,teacher_card tc WHERE t.tcid = tc.tcid;
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | ref    | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------
  • rows:實際查詢的記錄數

    mysql> EXPLAIN SELECT t.tcid FROM teacher_card tc,teacher t WHERE t.tcid = tc.tcid;
    
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    | id | select_type | table | type   | possible_keys | key        | key_len | ref         
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    |  1 | SIMPLE      | t     | index  | tcid_index    | tcid_index | 5       | NULL         
    |  1 | SIMPLE      | tc    | ref    | PRIMARY       | PRIMARY    | 4       | mydb3.t.tcid 
    +----+-------------+-------+--------+---------------+------------+---------+-------------
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    3 | Using index              |
    |    1 | Using where; Using index |
    +------+--------------------------+
    mysql> SELECT t.tcid FROM teacher_card tc,teacher t WHERE t.tcid = tc.tcid;
    +------+
    | tcid |
    +------+
    |    1 |
    |    2 |
    |    3 |
    +------+
  • extra

    • Using index,使用到索引
    • Using where,表示優化器須要經過索引回表查詢數據;
  • Using filesort:沒法利用索引來完成的排序

    -- 單列索引
    CREATE TABLE a(
      a INT,
      b INT,
      c INT,
      INDEX a_index(a),
      INDEX b_index(b),
      INDEX c_index(c)
    );
    -- 查詢的 a 可是額外用b排了序,若是用a排序則不會出現Using filesort
    mysql> EXPLAIN SELECT * FROM a WHERE a='' ORDER BY b;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using filesort |
    +------+--------------------------+
    
    -- 複合索引 不能跨列 要知足最佳左前綴,不然出現Using filesort
    DROP INDEX a_index ON a;
    DROP INDEX b_index ON a;
    DROP INDEX c_index ON a;
    ALTER TABLE a ADD INDEX a_b_c_index(a,b,c);
    -- 知足最佳左前綴,沒有跨列
    mysql> EXPLAIN SELECT * FROM a WHERE a='' ORDER BY b;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using index |
    +------+--------------------------+
    -- 跨列
    mysql> EXPLAIN SELECT * FROM a WHERE a='' ORDER BY c;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using index; Using filesort |
    +------+--------------------------+
    -- 不知足最佳左前綴
    mysql>EXPLAIN SELECT * FROM a WHERE b='' ORDER BY c;
    +------+--------------------------+
    | rows | Extra                    |
    +------+--------------------------+
    |    1 | Using where; Using index; Using filesort |
    +------+--------------------------+

    (補充: 回表查詢:指的是在索引中沒有要查詢的數據,須要回到表中查詢)

五、優化示例

1)單表優化

-- 單表優化
-- 建立表
CREATE TABLE book(
  bid INT NOT NULL PRIMARY KEY,
  NAME VARCHAR(20),
  authorid INT NOT NULL,
  publicid INT NOT NULL,
  typeid INT NOT NULL
);
-- 查詢authorID=1,typeid=2或3的 bid
mysql> EXPLAIN SELECT bid FROM book WHERE typeid IN (2,3) AND authorid = 1 ORDER BY typeid DESC;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows |                   |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
|  1 | SIMPLE      | book  | ALL  | NULL          | NULL | NULL    | NULL |    5 | 
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
 Extra
------------------+
 Using where; Using filesort
------------------+
-- 優化 1 添加索引,(消除了Using filesort,提升了type等級index)
ALTER TABLE book ADD INDEX b_t_a_index(bid,typeid,authorid);
mysql> EXPLAIN SELECT bid FROM book WHERE typeid IN (2,3) AND authorid = 1 ORDER BY typeid DESC;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows |                   |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
|  1 | SIMPLE      | book  | index  | NULL        | NULL |   12    | NULL |    5 | 
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
------------------+
 Extra
------------------+
 Using where; Using index;Using filesort
------------------+
-- 優化2 
-- 修改索引順序(提升了type等級 ref)
-- 含IN 的查詢放到後面,避免可能的失效
ALTER TABLE book ADD INDEX atb_index(authorid,typeid,bid); 
mysql> EXPLAIN SELECT bid FROM book WHERE authorid = 1 AND typeid IN (2,3) ORDER BY typeid DESC;
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----
| id | select_type | table | type | possible_keys | key       | key_len | ref   | rows | 
+----+-------------+-------+------+---------------+-----------+---------+-------+------+-----
|  1 | SIMPLE      | book  | ref  | atb_index     | atb_index | 4       | const |    2 | 
+----+-------------+-------+------+---------------+-----------+---------+-------+------+--------------------------+
Extra                    |
---------------------+
Using where; Using index |
---------------------+

2)多表優化

EXPLAIN SELECT * FROM teacher t , course c  WHERE t.tid = c.tid AND c.cname = '語文';
-- 或者
EXPLAIN SELECT * FROM teacher t LEFT JOIN  course c ON t.tid = c.tid WHERE c.cname = '語文';
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows |           
+----+-------------+-------+------+---------------+------+---------+------+------+-----------
|  1 | SIMPLE      | t     | ALL  | NULL          | NULL | NULL    | NULL |    3 |           
|  1 | SIMPLE      | c     | ALL  | NULL          | NULL | NULL    | NULL |    4 | 
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
Extra     
--------------------+
Using where; Using join buffer |
--------------------+

-- 優化 1 添加索引 
-- 給哪張表添加索引 --> 知足原則"小表驅動大表";
--                --> 索引常用,不常改變

3)避免索引失效原則

  • 複合索引須要知足最佳左前綴;
  • 複合索引儘可能使用全索引匹配;
  • 複合索引不能使用(不等於、和 IS NULL);
  • 索引上不要進行一些運算操做;
  • 範圍查詢是不使用關鍵字IN;
  • 模糊查詢儘可能以"常量"開頭不以"%"開頭;
  • 不要使用OR;
  • 不要使用字段的類型轉換;

4)常見的優化方法

  • IN和EXIST的使用:

    • 若是主查詢的數據很大,用IN
    • 若是子查詢的數據很大,用EXIST
  • order by 的使用

    Using filesort 分爲雙路排序[1掃描排序字段,2掃描其它字段]、單路排序[掃描全度字段](根據磁盤IO次數)

    能夠經過切換排序方法和增大排序使用的buffer大小

    保證排序的一致性

  • 避免使用SELECT *

5) 慢查詢日誌

記錄mysql中超過閥值(long query time)默認10秒;

-- 查看慢查詢日誌是否開啓
show variables like "%slow_query_log%";
-- 臨時開啓
set globle slow_query_log = 1;
-- 永久開啓
-- 修改mysql的配置文件
-- slow_query_log = 1
-- slow_query_log_file = /var/mysql/slow.log    制定一個路徑尋訪日誌

-- 查看閥值大小
show variables like "%long_query_time%";
-- 臨時設置大小(重啓生效)
set globle long_query_time = 時長(s);
-- 永久設置大小(重啓生效)
-- 修改mysql的配置文件
-- long_query_time = 時長

-- 查詢超過閥值的SQL 
show globle status like "%slow_queris%"; -- 數量

-- mysql的工具,查看慢日誌記錄
mysqldumpslow

六、分析數據

1)使用profiles

分析執行SQL的在各環節的執行時間

-- 查看執行SQL的時間和query_id
show profiles
-- 
show variables like "%profiling%";
-- 開啓profiling屬性
set profiling = on;
-- 分析執行SQL的在各環節的執行時間
show profile all for query 1; -- 1是查出來的query_id

2)使用全局日誌

能夠記錄全部執行的SQL

-- 查看是否開啓全局日誌
show variables like "%general_log%";
-- 開啓全局日誌,記錄到mysql.general_log表中
set globle general_log = 1;
set globle log_output = 'table';

七、鎖機制

解決資源共享形成的併發問題 參考[mydddfly]博客

  • 讀鎖(共享鎖):讀操做,一個資源能夠被多個訪問讀取;
  • 寫鎖(互斥鎖):寫操做,一個資源在進行寫操做時,獨佔;

1)MySQL的鎖機制

開銷 加鎖速度 死鎖 粒度 併發性能
行級鎖 不會死鎖 大(鎖衝突機率高)
表級鎖 會出現死鎖 小(鎖衝突機率低)
頁面鎖 會出現死鎖

2)存儲引擎使用的鎖

  • INNODB:默認使用行級鎖,也支持表級鎖
  • MyISAM:默認使用表級鎖
  • MEMORY:默認使用表級鎖

3)表鎖

MySQL的表級鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨佔寫鎖(Table Write Lock)

MyISAM在執行查詢語句(SELECT)前,會自動給涉及的全部表加讀鎖,在執行更新操做(UPDATE、DELETE、INSERT等)前,會自動給涉及的表加寫鎖;

-- 經過檢查table_locks_waited和table_locks_immediate狀態變量來分析系統上的表鎖定爭奪狀況;
-- 值越大爭奪越嚴重
mysql> show status like 'table%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Table_locks_immediate | 46    |
| Table_locks_waited    | 0     |
+-----------------------+-------+

如何給表加鎖

-- lock table 表名 read/write  給表加上讀/寫鎖
mysql> lock table teacher read;
-- 查看錶是否使用鎖
mysql> show open tables;
+--------------------+----------------------------------------------+--------+-------------+
| Database           | Table                                        | In_use | Name_locked |
+--------------------+----------------------------------------------+--------+-------------+
| mysql              | time_zone_transition_type                    |      0 |           0 |
| mydb3              | teacher                                      |      1 |           0 |
+--------------------+----------------------------------------------+--------+-------------+

4)行鎖

  • InnoDB實現瞭如下兩種類型的行鎖。
    • 共享鎖(S):容許一個事務去讀一行,阻止其餘事務得到相同數據集的排他鎖
    • 排他鎖(X):容許得到排他鎖的事務更新數據,阻止其餘事務取得相同數據集的共享讀鎖和排他寫鎖
    • 意向共享鎖(IS):事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖
    • 意向排他鎖(IX):事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖

(爲了容許行鎖和表鎖共存,實現多粒度鎖機制,InnoDB還有兩種內部使用的意向鎖(Intention Locks),這兩種意向鎖都是表鎖)

  • 如何給行加鎖
-- 能夠經過檢查InnoDB_row_lock狀態變量來分析系統上的行鎖的爭奪狀況:
show status like 'innodb_row_lock%';
Show innodb status;

-- 共享鎖
select * from teacher where tid = 1 lock in share mode;
-- 排它鎖
select * from teacher where tid = 1 for update;

八、主從複製

博文看考

1)mysql 的主從複製原理


MySQL之間數據複製的基礎是二進制日誌文件(binary log file)。一臺MySQL數據庫一旦啓用二進制日誌後,其做爲master,它的數據庫中全部操做都會以「事件」的方式記錄在二進制日誌中,其餘數據庫做爲slave經過一個I/O線程與主服務器保持通訊,並監控master的二進制日誌文件的變化,若是發現master二進制日誌文件發生變化,則會把變化複製到本身的中繼日誌中,而後slave的一個SQL線程會把相關的「事件」執行到本身的數據庫中,以此實現從數據庫和主數據庫的一致性,也就實現了主從複製;

2)實現主從複製

主服務器配置

-- 修改配置文件
[mysqld]
log-bin = mysql-bin
server-id = 1
-- 建立用戶並受權
mysql> CREATE USER 'flynn'@'localhost' IDENTIFIED BY '123456';#建立用戶
mysql> GRANT REPLICATION SLAVE ON *.* TO 'flynn'@'localhost';#分配權限
mysql>flush privileges;   #刷新權限
-- 查看master狀態,記錄二進制文件名和位置:
show master status;

從服務器配置、

-- 配置文件
server-id = 2

-- 重啓mysql,打開mysql會話,執行同步SQL語句
mysql> CHANGE MASTER TO
    ->     MASTER_HOST='',
    ->     MASTER_USER='',
    ->     MASTER_PASSWORD='',
    ->     MASTER_LOG_FILE='二進制文件名',
    ->     MASTER_LOG_POS='位置';
    
-- 啓動slave 同步
mysql> start slave;
-- 查看狀態
mysql> show slave status

對主服務器配置約束

[mysqld]
# 不一樣步哪些數據庫  
binlog-ignore-db = ''  
  
# 只同步哪些數據庫,除此以外,其餘不一樣步  
binlog-do-db = ''

九、思考

1)爲何索引是默認是B-Tree,而不是hash、二叉樹、紅黑樹

  • hash:能夠快速定位可是沒有順序IO複雜度高
  • 二叉樹:樹的高度不均勻,不能自平衡,存儲的數據越大則樹的高度越高,IO代價越高
  • 紅黑樹:存儲的數據越大則樹的高度越高,IO代價越高

2)爲何建議使用自增加的主鍵做爲索引

自增的主鍵是連續的在插入過程當中儘可能減小頁分裂,即便進行頁分裂,也只會分裂不多的一部分。而且能減小數據的移動,每次插入都是插入到最後。總之就是減小分裂和移動的頻率

3)爲何InnoDB非主鍵索引廣泛比主鍵索引要慢

InNoDB使用的是聚簇索引,使用輔助索引要查詢兩次才能拿到數據;而主鍵索引只須要查一次;

4)爲何InnoDB採用的是B+Tree 而不是B-Tree

B-Tree的非葉子結點也會存儲數據,這樣致使了非葉子結點上存儲的指針變少,數據量大時只能增長樹的高度(即增長了IO訪問的次數);

相關文章
相關標籤/搜索