MySQL實戰45講學習筆記:第二講

1、重要的日誌模塊:redo log

一、經過酒店掌櫃記帳思路刨析redo log工做原理

二、InnoDB 的 redo log 是固定大小的

 

只要賒帳記錄在了粉板上或寫了帳本上,以後即便掌櫃忘記了,
好比停業幾天,回覆生意後依然能夠經過帳本和粉板上的數據明確賒帳帳目mysql

有了redo log,InnoDB就能夠保證即便數據庫發生異常重啓,以前提交的記錄都不會丟失,這個能力成爲crash-safe2、重要的日誌模塊:binlogsql

2、重要的日誌模塊binlog

一、redo和三點區別binlog

redo是物理的,binlog是邏輯的;如今因爲redo是屬於InnoDB引擎,因此必需要有binlog,由於你可使用別的引擎數據庫

 

二、binlog幾大模式

 

通常採用row,由於遇到時間,從庫可能會出現不一致的狀況,可是row更新先後都有,會致使日誌變大
最後2個參數,保證事務成功,日誌必須落盤,這樣,數據庫crash後,就不會丟失某個事務的數據了bash

三、企業場景如何選擇binglog:

一、互聯網公司,使用MySQL的功能相對少(存儲過程、觸發器、函數) session

選擇默認的語句模式,Statement Level(默認) 

二、公司若是用到使用MySQL的特殊功能(存儲過程、觸發器、函數) oracle

則選擇Mixed模式 

三、公司若是用到使用MySQL的特殊功能(存儲過程、觸發器、函數)又但願數據最大化一直,此時最好選擇Row level模式app

四、行模式和語句模式的區別

五、  ROW模式下binlog日誌記錄效果

[root@db01]# mysqlbinlog --base64-output="decode-rows" --verbose mysql-bin.000248

/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;

/*!40019 SET @@session.max_insert_delayed_threads=0*/;

/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;

DELIMITER /*!*/;

# at 4

#160628 11:06:52 server id 1  end_log_pos 107   Start: binlog v 4, server v 5.5.49-log created 160628 11:06:52 at startup

# Warning: this binlog is either in use or was not closed properly.

ROLLBACK/*!*/;

# at 107

#160628 11:07:09 server id 1  end_log_pos 177   Query   thread_id=1     exec_time=0     error_code=0

SET TIMESTAMP=1467083229/*!*/;

SET @@session.pseudo_thread_id=1/*!*/;

SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;

SET @@session.sql_mode=0/*!*/;

SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;/*!\C utf8 *//*!*/;

SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;

SET @@session.lc_time_names=0/*!*/;

SET @@session.collation_database=DEFAULT/*!*/;

BEGIN

/*!*/;

# at 177

# at 223

#160628 11:07:09 server id 1  end_log_pos 223   Table_map: `oldboy`.`sc` mapped to number 33

#160628 11:07:09 server id 1  end_log_pos 785   Update_rows: table id 33 flags: STMT_END_F

### UPDATE `oldboy`.`sc`

### WHERE

###   @1=1

###   @2=1001

3、update 語句的執行流程圖

一、update語句的執行流程圖

圖中綠色框表示是在內粗執行,紅色框表示是在執行器中執行運維

二、 流程說明

1.首先客戶端經過tcp/ip發送一條sql語句到server層的SQL interfacetcp

2.SQL interface接到該請求後,先對該條語句進行解析,驗證權限是否匹配函數

3.驗證經過之後,分析器會對該語句分析,是否語法有錯誤等

4.接下來是優化器器生成相應的執行計劃,選擇最優的執行計劃

5.以後會是執行器根據執行計劃執行這條語句。在這一步會去open table,若是該table上有MDL,則等待。若是沒有,則加在該表上加短暫的MDL(S),

(若是opend_table太大,代表open_table_cache過小。須要不停的去打開frm文件)

6.進入到引擎層,首先會去innodb_buffer_pool裏的data dictionary(元數據信息)獲得表信息

7.經過元數據信息,去lock info裏查出是否會有相關的鎖信息,並把這條update語句須要的鎖信息寫入到lock info裏(鎖這裏還有待補充)

8.而後涉及到的老數據經過快照的方式存儲到innodb_buffer_pool裏的undo page裏,而且記錄undo log修改的redo

(若是data page裏有就直接載入到undo page裏,若是沒有,則須要去磁盤裏取出相應page的數據,載入到undo page裏)

9.在innodb_buffer_pool的data page作update操做。並把操做的物理數據頁修改記錄到redo log buffer裏

因爲update這個事務會涉及到多個頁面的修改,因此redo log buffer裏會記錄多條頁面的修改信息。

由於group commit的緣由,此次事務所產生的redo log buffer可能會跟隨其它事務一同flush而且sync到磁盤上

10.同時修改的信息,會按照event的格式,記錄到binlog_cache中。(這裏注意binlog_cache_size是transaction級別的,不是session級別的參數,

一旦commit以後,dump線程會從binlog_cache裏把event主動發送給slave的I/O線程)

11.以後把這條sql,須要在二級索引上作的修改,寫入到change buffer page,等到下次有其餘sql須要讀取該二級索引時,再去與二級索引作merge
(隨機I/O變爲順序I/O,可是因爲如今的磁盤都是SSD,因此對於尋址來講,隨機I/O和順序I/O差距不大)

12.此時update語句已經完成,須要commit或者rollback。這裏討論commit的狀況,而且雙1

13.commit操做,因爲存儲引擎層與server層之間採用的是內部XA(保證兩個事務的一致性,這裏主要保證redo log和binlog的原子性),
因此提交分爲prepare階段與commit階段

14.prepare階段,將事務的xid寫入,將binlog_cache裏的進行flush以及sync操做(大事務的話這步很是耗時)

15.commit階段,因爲以前該事務產生的redo log已經sync到磁盤了。因此這步只是在redo log裏標記commit

16.當binlog和redo log都已經落盤之後,若是觸發了刷新髒頁的操做,先把該髒頁複製到doublewrite buffer裏,把doublewrite buffer裏的刷新到共享表空間,而後纔是經過page cleaner線程把髒頁寫入到磁盤中

其實在實現上5是調用了6的過程了的,因此是一回事。MySQL server 層和InnoDB層都保存了表結構,因此有書上描述時會拆開說。

4、兩階段提交

一、保證數據庫的一致性:

必需要保證2份日誌一致,使用的2階段式提交;其實感受像事務,不是成功就是失敗,不能讓中間環節出現,也就是一個成功,一個失敗
若是有一天mysql只有InnoDB引擎了,有redo來實現複製,那麼感受oracle的DG就誕生了,物理的速度也將遠超邏輯的,畢竟只記錄了改動向量

 二、binlog能不能去掉?

老師,今天MYSQL第二講中提到binlog和redo log, 我感受binlog不少餘,按理是否是隻要redo log就夠了?[費解] 

一個緣由是,redolog只有InnoDB有,別的引擎沒有。
另外一個緣由是,redolog是循環寫的,不持久保存,binlog的「歸檔」這個功能,redolog是不具有的。

三、運維同窗的實戰疑惑

老師您好,我以前是作運維的,經過binlog恢復誤操做的數據,可是實際上,咱們會後知後覺,誤刪除一段時間了,才發現誤刪除,此時,我把以前誤刪除的binlog導入,再把誤刪除以後binlog導入,會出現問題,好比主鍵衝突,並且binlog導數據,不一樣模式下時間也有不一樣,可是通常都是row模式,時間仍是好久,有沒什麼方式,時間短且數據一致性強的方式

其實恢復數據只能恢復到誤刪以前到一刻,
誤刪以後的,不能只靠binlog來作,由於業務邏輯可能由於誤刪操做的行爲,插入了邏輯錯誤的語句,
因此以後的,跟業務一塊兒,從業務快速補數據的。只靠binlog補出來的每每不完整

四、怎樣讓數據庫恢復到半個月內任意一秒的狀態?

1 prepare階段

2 寫binlog

3 commit

當在2以前崩潰時

重啓恢復:後發現沒有commit,回滾。備份恢復:沒有binlog 。一致

當在3以前崩潰

重啓恢復:雖沒有commit,但知足prepare和binlog完整,因此重啓後會自動commit。備份:有binlog. 一致

5、思考題(同窗們的經典留言)

一、Jason同窗

備份時間週期的長短,感受有2個方便

首先,是恢復數據丟失的時間,既然須要恢復,確定是數據丟失了。若是一天一備份的話,只要找到這天的全備,加入這天某段時間的binlog來恢復,若是一週一備份,假設是週一,而你要恢復的數據是週日某個時間點,那就,須要全備+週一到週日某個時間點的所有binlog用來恢復,時間相比前者須要增長不少;看業務能忍受的程度

其次,是數據庫丟失,若是一週一備份的話,須要確保整個一週的binlog都無缺無損,不然將沒法恢復;而一天一備,只要保證這天的binlog都無缺無損;固然這個能夠經過校驗,或者冗餘等技術來實現,相比之下,上面那點更重要

二、justd同窗的形象比喻

一、一個完整的交易過程:

一、帳本記上 賣一瓶可樂(redo log爲 prepare狀態),
二、而後收錢放入錢箱(bin log記錄)
三、而後回過頭在帳本上打個勾(redo log置爲commit)表示一筆交易結束。

二、若是收錢時交易被打斷

一、回過頭來整理這次交易,發現只有記帳沒有收錢,則交易失敗,刪掉帳本上的記錄(回滾);
二、若是收了錢後被終止,而後回過頭髮現帳本有記錄(prepare)並且錢箱有本次收入(bin log),則繼續完善帳本(commit),本次交易有效。
相關文章
相關標籤/搜索