MySQL


MySql體系結構

一,連接層功能:

1,TCP/IP或者Socket的鏈接方式

2,驗證用戶名密碼功能

3,連接線程(客服):接收SQL語句,返回執行結果

 

二,SQL層

1,語法檢查模塊,檢查上層發過來的SQL語句,進行語法檢查

2,權限檢查模塊,檢測當前登錄用戶是否有權限操作數據庫對象

3,語義檢查模塊,識別語句種類

4,解析器,解析出SQL語句所有可能的執行方式,這些方式被稱為“執行計划”

5,優化器,基於執行代價(系統資源的消耗作為維度(cpu、內存、IO),管理員可以通過間接的方法,干擾優化器的選擇)

6,執行器,按照優化器選擇的“最優”的執行計划,執行SQL語句。得出結論:某某磁盤的某某位置,發送給存儲引擎層。

7,提供查詢緩存:有局限性。一般會用Redis產品來替代

8,記錄查詢日志

   

SQL語句的分類:

DDL:數據定義語言

DCL:數據控制語言

DML:數據操作語言

DQL:數據查詢語言

 

三,存儲引擎層:

和“磁盤”(文件系統)打交道的層次

根據SQL層執行的結果,去磁盤上找到對應的數據。結構化成表的模式,返回給用戶。

  

MySql邏輯結構組成:

一,庫(庫名字,庫屬性)

 二,庫(庫名字,列(列名字,列屬性)表屬性,表數據)

 

MySQL索引

  MySQL索引分類

存儲引擎管理

一,索引管理以及原理

1,索引的種類

B樹(B+tree  B*tree b-tree)

B-tree:針對某個明確值的查詢

查找順序:根節點——>枝節點——>葉子節點

B+tree:針對明確的范圍的查詢

缺點:無法同時包含回表查詢以及其它列的查詢

 

輔助索引:(B TREE)

alter table t1 add index idx_num(telnum);

怎么生成的:

根據創建索引時,指定的列的值,進行排序后,存儲在葉子節點中

優點:

1,優化了查詢,減少CPU 內存  IO消耗

2,減少了文件排序

 

覆蓋索引:(聯合索引)

通過一個索引列把需要查詢的列都添加到索引樹里面去

直接在索引樹里面直接有,減少或盡量避免回表查詢操作

優點:減少回表查詢的操作的幾率

聚集索引

同一等級情況下效率最高

大部分情況下輔助索引和聚集索引結合使用

輔助索引:where 條件   有id列的時候,比如id=28

隨機讀​ 順序讀

建表時,如果有主鍵列,自動生成聚集索引

沒有主鍵列,會去找unique列

優點:

減少回表查詢

將隨機IO轉換成順序IO

加強了緩存的應用,查詢效率提升

 

2,R樹

3,hash索引

4,全文索引

2,B樹索引的類型

  1,聚簇索引(cluster index):一般是基於主鍵的

  2,輔助索引(普通輔助索引:回表查詢;覆蓋索引;不回表查詢;唯一性索引)

  3,唯一索引

3,索引管理

索引的作用:在mysql數據庫中,索引是用來優化查詢的

除緩存之外,數據的查詢有兩種方式:

1,全表掃描

2,索引掃描

優化器索引掃描要優於全表掃描

索引管理:

索引就是一張表

創建索引的語句:

為某張表基於某列建索引:alter table 表名 add index idx_name(列名)

 

  MySQL不走索引的情況(開發規范)

重點關注:

1,沒有查詢條件,或者查詢條件沒有建立索引

  select * from tab ;全表掃描

  select * from tab where 1=1;

  在業務數據庫中,特別是數據庫量比較大的表,是沒有全表掃描這種需求的,當然我們也應該避免這種情況

    1,對用戶查看是非常痛苦的

    2,對服務器來說是毀滅性的

    (1) select * from tab

    SQL改寫成以下語句:

    select * from tab order by price limit 10 ;       需要在price列上建立索引

    (2) select * from tab where name=‘zhangsan';   name列沒有索引

2,查詢結果集是原表中的大部分數據,應該是25%以上。

  查詢的結果集,超過了總數行數25%,優化器就會覺得沒有必要走索引了。

  假如:tab表 id,name      id:1-100w,id列有索引

  select * from tab where id>50000;

3,索引本身失效,統計數據不真實

  大量的操作插入刪除操作,對表內容變化比較頻繁的情況下,有可能會出現索引失效的情況。

4,查詢條件使用函數在索引上,或者列進行計算,運算包括(+,-,*,/,!等)

  算數運算

  函數運算

  子查詢

例子:

  錯誤的例子:select * from test where id-1=9;

  正確的例子:select * from test where id=10;

5,隱式轉換導致索引失效,這一點應當引起重視,也是開發中經常遇到會犯的錯誤!

 

 6,<>,not in 不走索引

    單獨的 >,<,in有可能走,也有可能不走,和結果集有關,盡量結合業務添加limit

    or或 in  盡量改成 union

7,like "%_"百分號在前面不走索引

    %link%類的搜索需求,可以使用elasticsearch 專門做搜索服務的數據庫產品

8,單獨引用聯合索引里非第一位置的索引列,作為條件查詢時不走索引。

例子:

  復合索引

  DROP TABLE t1

  CREATE TABLE t1(id INT,NAME VARCHAR(20),age INT , sex ENUM('m','f'),money INT );

   ALTER TABLE t1 ADD INDEX t1_idx(money,age,sex);

  DESC t1

  SHOW INDEX FROM t1

  走索引的情況測試:

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30  AND  sex='m'; 

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 ;

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND sex='m';   ----->部分走索引

  不走索引的情況;

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30;

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30  AND  sex='m';  

    EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE sex='m'; 

 

MySQL存儲引擎

查看存儲引擎:

show engines;

show create table world.city;

插件式,即插即用存儲引擎,是在表級別設定的。

mysql5.5以后默認的是InnoDB

InnoDB與MyISAM存儲引擎的區別:

MVCC: innoDB支持,MyISAM不支持

鎖(行級別): innodb支持,myisam表級別

外鍵: innodb支持,myisam不支持

事務: innodb支持,myisam不支持

熱備份: innodb支持,myisam溫備份

CSR(故障斷電自動恢復)innodb支持,myisam不支持

InnoDB

MVCC

 鎖定粒度

外鍵

MyISAM

MEMORY(memory)

ARCHIVE(archive)

 

 

也可以使用第三方的存儲引擎

TokuDB  ------>zabbix

myrocks

 

InnoDB存儲引擎的物理存儲方式:

表空間(TBS)的管理模式:

來自於Oracle

表存儲到磁盤上是以表空間的管理模式來存儲

共享表空間:類似於Oracle管理模式

獨立表空間:每個表單獨使用表空間存儲

5.5默認:共享表空間

5.6以后:默認管理模式獨立表空間存儲,共享表空間也存在

 

表空間存儲數據的分類:

共享表空間:ibdata1   

存了什么?

系統數據

undo日志

磁盤臨時表

獨立表空間:

t1.ibd  ----->t1表的數據和索引

t1.frm ------>t1表的列相關信息

表空間操作:

共享表空間:

我們建議,在數據庫初始化的時候就配置好

一般建議2-3個,512M

/etc/my.cnf

innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

mysql_install_db

 

獨立表空間:一個表一個ibd文件,存儲表數據和索引

show variables like 'innodb_file_per_table';

 

事務

InnoDB存儲引擎核心特性:

1,事務

  簡單來說:

    事務會把業務流程中的多條語句放到一個執行(工作)單元里面,保證這多條語句要么全部成功,要么全部失敗。

    保證交易類業務完整性

  官方:

  一組數據操作執行步驟,這些步驟被視為一個工作單元

  用於對多個語句進行分組

  可以在多個客戶機並發訪問同一個表中的數據時使用

  所有步驟都成功或者都失敗

  如果所有步驟正常,則執行

  如果步驟出現錯誤或不完整,則取消

  

2,事務是保證數據的ACID特性

  Atomic(原子性)

    所有語句作為一個執行單元全部成功執行或全部取消執行。

    保證了穩定性。

  Consistent(一致性)

    如果數據庫在事務開始時處於一致狀態,則在執行該VT事務期間將保留一致狀態。

  Isolated(隔離性)

    事物之間不相互影響

  Durable(持久性)

    事務成功完成后,所做的所有更改都會准確地記錄在VT數據庫中,所做的更改不會丟,即使數據庫宕機

 

3,標准的事務控制語句:

  事務常見生命周期:

  周期一:

  begin;    開啟事務

  DML

  DML

  commit;   結束事務

 

  周期二:   開啟事務

  begin;

  DML

  DML

  rollback;   撤銷事務

  常識:MySQL5.5版本以后不需要自己手動來寫begin語句,寫DML語句時自動生成

  注意:正常的遵循事務的ACID特性的事務,對於autocommit=1,需要手動關閉,默認等於1處於開啟狀態,自動提交功能

    臨時關閉,臨時生效

    set  autocommit=0;

    set  global  autocommit=0;

    永久關閉

    在my.cnf設置

    autocommit=0;

4,隱式提交

  用於隱式提交的SQL語句:
     START TRANSACTION
     SET AUTOCOMMIT = 1
  導致提交的非事務語句:
     DDL語句:  ALTER、CREATE、DROP
     DCL語句:  GRANT、REVOKE、SET PASSWORD
     鎖定語句  LOCK TABLES 和 UNLOCK TABLES
  導致隱式提交的語句:
     TRUNCATE TABLES
     LOAD DATA INFILE
     SELECT FOR UPDATE

  隱式提交的幾種情況:

    情況一:

      begin

      DML1

      DML2

      begin

    情況二:

      begin

      DDL

      DDL

    情況三:

      begin

      DCL

      DDL

5,innodb存儲引擎物理存儲層

  表空間(t1.ibd)----->

  段    一個表就是一個段(除了分區表)

  區    連續的多個頁

  頁    page(16KB)

  每個數據頁作為一個存儲單元

6,存儲引擎日志 -----物理層面

Redo:重做日志

 

  Redo記錄的是內存數據頁的變化過程

  Rudo:事務日志的一種,在事務ACID過程中,實現的是“D”持久化的作用,AC特性也和它有關

  Rudo:CSR過程中實現前滾

  存儲位置:數據路徑下存放,默認兩個日志,默認標准大小50M,輪詢覆蓋形式使用文件日志

    通過這兩個參數控制,可以按照自己需求設定文件大小

      innodb_log_file_size=50331648

      innodb_log_files_in_group=2

    ib_logfile0

    ib_logfile1

    查看標准大小:

      mysql -uroot  -p

      show varables like '%log%';

   LSN:日志序列號(也就是數據變化的版本號)

    哪些地方會有日志序列版本號:

      data page      磁盤數據頁

      logfile

      data buffer

      redo log  buffer  日志的內存區域

      

    數據庫要求:啟動時,必須保證data page 與logfile 中LSN號一致才能正常打開數據庫,否則就會進行數據恢復

 

 

undo:回滾日志

  undo記錄了什么?

    undo:記錄數據頁變化之前的數據狀態以及TXID(數據頁的id)

   undo:事務日志的一種,在事務ACID過程中,實現的是“ACI”原子性,一致性的作用

  undo作用:

    1,rollback

    2,CSR過程中實現回滾

  事務沒有進行commit提交的情況下:

    先Rudo前滾

    再undo回滾

 

  四種隔離級別:

    READ UNCOMMITTED  臟讀

      允許事務查看其他事務所進行的未提交更改

    READ COMMITTED     幻讀

      允許事務查看其他事務所進行已提交更改

        有可能出現幻讀的現象,企業中堅決避免

    REPEATABLE READ******可重復讀,防止幻讀現象

      確保每個事務的SELECT 輸出一致

      InnoDB默認級別

    SERIALIZABLE

      將一個事務的結果與其他事務完全隔離

        會阻塞其他事務的所有操作,只保證當前事務正常運行

 

  Innodb事務鎖機制

  鎖:顧名思義就是鎖定的意思

  種類:行級鎖與表級鎖

  作用:在事務ACID過程中,鎖和隔離級別一起來實現隔離性的作用

  鎖的粒度:

    MyIasm:低並發鎖  ——表級鎖

    InooDB:高並發鎖  ——行級鎖

  事務出現沖突,出現鎖爭用:也名沖突事務

  沖突事務例子:

    例子:

        1,事務1想要把a=1修改成a=2,,而這時事務2想要把a=1修改成a=3,這種情況下

        2,兩個事務同時更新一條數據

 

 InnoDB體系結構擴展:

  1,內存結構

  2,線程結構

  3,事務工作更詳細流程

  4,InnoDB存儲引擎在安全和性能上的體現

  5,Double  Write

  6,Db crash恢復流程

 

 

 

日志管理

1,錯誤日志

  a,作用:

    記錄啟動\關閉\日常運行過程中,狀態信息,警告,錯誤

  b,配置:

    默認就是開啟狀態:/數據路徑下/hostname.err

    手動設定:

      vim /etc/my.cnf

      log_error=/var/log/mysql.log

      重啟生效:

      show variables like 'log_error';

   c,查看日志內容

      主要關注[error],看上下文

2,二進制日志:binlog

   1,作用:

      1,備份恢復

      2,主從環境

   2,binlog配置(5.7必須加server_id)

      vim /etc/my.cnf

      server_id=6

      log_bin=/data/mysql/mysql-bin

      binlog_format=row

      重啟生效

      注意:=/data/mysql 必須事先創建好,必須對mysql有權限

   3,binlog記錄了什么?

      記錄mysql數據庫所有變更類的SQL語句

      DDL,DCL,記錄方式:SQL語句直接記錄

      DML記錄三種方式:  只記錄已經commit的DML

        row       5.7默認

          特點:記錄數據行的變化,可讀性不高,日志量較大,記錄數據精確

        statment    5.6默認

          特點:可讀性較高,日志量較少,但是以后恢復數據可能會是錯誤數據

        mixed

   4, event二進制的最小記錄單元

      對於DDL,DCL,一個事務就是一個event

      對於DML,一個事務就被分為了四個event:

          begin;

          DML1

          DML2

          commit;

      event組成:開始位置 + 事件內容 +結束位置

   5,日志文件查看

      log_bin參數設置的路徑,可以找到二進制日志

      show binary logs;

      show master status;

   6,日志內容查看

      show master status;

      show master status in 'mysql-bin.000002';

 

      錄入數據,看事件信息:

      create database testdb;

      create table t1(id int);

      insert into t1 values(1);

      commit;

      show binlog events in 'mysql-bin.000002;

 

      查看binlog文件詳細內容:

      mysqlbinlog /data/mysql/mysql-bin.000002;

      mysqlbinlog --base64-output=decode-rows      -vvvv /data/mysql/mysql-bin.000002;

      mysqlbinlog -d testdb /data/mysql/mysql-bin.000002;

   7,日志截取

      mysqlbinlog --start-position   --stop-position

      恢復:

      set sql_log_bin=0;

      source /tmp/binlog.sql

      set sql_log_bin=1;

   8,二進制日志恢復數據

    數據庫的故障(損壞),原因:

      1,軟件損壞了

      2,數據損壞了

      3,硬件損壞,數據文件,數據頁

      4,邏輯損壞

      5,SQL導致的誤刪除,誤修改

    只要擁有全量的binlog,就可以把數據庫恢復到任意的時間點

 

3,慢日志(slow_log)

  1,作用:

    記錄慢SQL語句的日志

  2,開啟慢日志,默認沒開啟

    配置:

    開啟慢日志:

      slow_query_log=1

    文件位置以及名字:

      slow_query_log_file=/data/mysql/slow.log

    設定慢查詢時間:

      long_query_time=0.01

    沒走索引的語句也記錄:

      log_queries_not_using_indexes  

    

    服務器端配置,幾條語句加進去就可以了

      vim /etc/my.cnf

        slow_query_log=1

        slow_query_log_file=/data/mysql/slow.log

        long_query_time=0.01

        log_queries_not_using_indexes

      /etc/init.d/mysql  restart

   3,分析慢日志

     mysqldumpslow

     mysqldumpslow  -s c -t  10 /data/mysql/slow.log

備份恢復

1,備份類型

  熱備:在數據庫正常業務是,備份數據,並且能夠一致性恢復

  冷備:關閉數據庫業務,數據庫沒有任何變更的情況下,進行備份數據

  溫備:鎖表備份,只能查詢不能修改

2,備份方式,工具

  邏輯備份:基於SQL語句進行備份:mysqldump,mysqlbinlog

  物理備份:基於磁盤文件備份:cp,xtrabackup(XBK)

3,備份策略

  1,全備:全庫備份

  2,增量:備份變化的數據

  備份周期:多久全備,多久增量

  

 

4,恢復備份

 

5,故障恢復

6,遷移

 

 

主從復制

前提:

  1,准備2個以上的mysql實例,有主有從

     2,每台實例server_id不同

  3,主庫方面創建專用的復制用戶

  4,主庫必須開啟二進制日志

  5,從庫需要初始化數據,保證和主庫數據在一個時間點上數據一致

1,搭建主從復制

  1,准備多個mysql實例(3307(master),3308(slave1),3309(slave2))

    具體環境配置文檔(待QAQ續)  

  2,主庫必須授權一個專門用作主從復制的用戶

    在創建一個復制用戶

    mysql  -S /data/3307/mysql.sock

    grant  replication slave on *.* ro repl@'10.0.0.%' indextified  by '123';

  3,全備主庫數據,恢復到從庫

    mysqldump -S /data/3307/mysql.sock -A  -R  --triggers  --master-data=2 --single-transaction >/tmp/full.sql

    

    mysql  -S /data/3308mysql.sock

    set sql_log_bin=0;

    source  /tmp/full.sql

  4,開啟主從復制

    mysql -S /data/3308/mysql.sock

    命令兩條:

      忘記了請記得讓我們的help小姐姐來幫你QAQ: help change master to

      CHANGE MASTER TO

        MASTER_HOST='10.0.0.51',         填寫主庫ip

        MASTER_USER='repl',          填寫主庫復制用戶名

        MASTER_PASSEORD='123',          填寫主庫復制用戶密碼

        MASTER_[PORT=3307,          填寫主庫端口號

        MASTER_LOG_FILE='mysql-bin.000001',  填寫需要復制二進制日志名

        MASTER_LOG_POS=325,         填寫需要復制的二進制日志復制的起點

        MASTER_CONNECT_RETRY=10;      重連重試次數

        

        啟動復制線程:

          start slave;

           查看主從狀態:

            show slave status \G

          當你看到這兩條命令為Yes,那么恭喜你成功了!

            Slave_IO_Running:Yes

            Slave_SQL_Running:Yes

 2,主從復制存在原因

    1,輔助備份

       解決物理損壞

    2,演變高可用架構

       在主庫發生故障時,自動進行故障轉移,對於應用透明

    3,演變高性能架構

      讀寫分離

      分布式

 

 3,延時從庫

 

 4,過濾復制

  控制過濾

    從主庫方面控制:復制指定的庫到從庫,對主庫業務數據進行垂直拆分

    從從庫方面控制:只接收主庫某個庫復制過來的內容   

 

  1,從主庫方面控制

    show master status;

    Binlog_Do_DB=白名單,在此參數中的庫,記錄二進制日志

    Binlog_Ignore_DB=黑名單,在此參數中的庫,不記錄二進制日志

 

  2,從庫方面控制

    Replicate_Do_DB:  白名單,在此參數中的庫,復制

    Replicate_Ignore_DB:  黑名單,在此參數中的庫,不復制

    Replicate_Do_Table:  白名單,在此參數中的表,復制

    Replicate_Ignore_Table:  黑名單,在此參數中的表,不復制

    模糊的表名字    

    Replicate_Wild_Do_Table:  wolrd.t*

    Replicate_Wild_Ignore_Table:

    寫法:

    vim /data/3308/my.cnf

    replicate_do_db=world

    replicate_do_db=oldboy

 

5,主從復制之架構擴展GTID復制

1,環境准備

  環境准備Centos拿db01克隆兩台虛擬機

  干掉原來數據庫,並清理/application/mysql/data下所有數據,保證環境一致,干凈

    pkill mysqld

    rm -rf  /application/mysql/data*

  1,備份三台機器/etc/my.cnf文件

    mv/etc/my.cnf  /tmp

  2,書寫配置文件:

    master:10.0.0.51

    vim/etc/my.cnf  

    

    [mysqld]

    dasedir=/application/mysql

    datadir=/application/mysql/data

    socket=/tmp/mysql.sock

    log-error=/var/log/mysql.log

    log-bin=/data/mysql/mysql-bin

    binlog_format=row

    skip-name-resolve

    server-id=51

    gtid-more=on

    enforce-gtid-consistency=true

    log-slave-updates=1

    [client]

    socket=/tmp/mysql.sock

    

    slave1:10.0.0.52

    vim /etc/my.cnf

    [mysqld]

    dasedir=/application/mysql

    datadir=/application/mysql/data

    socket=/tmp/mysql.sock

    log-error=/var/log/mysql.log

    log-bin=/data/mysql/mysql-bin

    binlog_format=row

    skip-name-resolve

    server-id=52

    gtid-more=on

    enforce-gtid-consistency=true

    log-slave-updates=1

    [client]

    socket=/tmp/mysql.sock

 

    slave2:10.0.0.53

    vim /etc/my.cnf

    [mysqld]

    dasedir=/application/mysql

    datadir=/application/mysql/data

    socket=/tmp/mysql.sock

    log-error=/var/log/mysql.log

    log-bin=/data/mysql/mysql-bin

    binlog_format=row

    skip-name-resolve

    server-id=53

    gtid-more=on

    enforce-gtid-consistency=true

    log-slave-updates=1

    [client]

    socket=/tmp/mysql.sock

 

  3,重新初始化三台機器數據

    /application/mysql/scripts/mysql_install_db  --basedir=/application/mysql/ --datadir=/application/mysql/data  --user=mysql

  4,分別啟動三台數據庫服務器

    etc/init.d/mysqld start

 

 2,GTID介紹

  GTID是對於一個已提交事務的編號,並且是一個全局唯一的編號

   官方定義:

   GTID=source_id :transaction_id

  7E11FA47-31CA-19E1-9E56-C43AA21293967:29

  

  1,什么是sever_uuid和Server-id區別?

  source_id  也叫uuid   默認是在第一次啟動數據庫時,自動生成的

  /application/mysql/data/auto.cnf

  手動刪除掉此文件,重啟數據庫,可以生成新的

 

  2,重要參數

  gtid-mode=on            --啟動gtid類型,否則就是普通的復制架構

  erforce-gtid-consistency=true     --強制GTID的一致性

  log-slave-updates=1          --slave更新是否記入日志

 

  3,基於GTID的復制構建

    master:51

    slave:52,53

    51:

    grant  replication  slave  on  *.* to  repl@'10.0.0.%' identified by '123';

    52\53:

    source bak.sql

    change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1;

    start  slave;

    change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1; 

 

 

高可用以及讀寫分離

 

 

分布式系統

 

 

 

 

數據庫優化

  搜索引擎優化

  SQL語句優化


免責聲明!

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



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