久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL中binlog有什么用

209次閱讀
沒有評論

共計 5575 個字符,預計需要花費 14 分鐘才能閱讀完成。

這篇文章將為大家詳細講解有關 MySQL 中 binlog 有什么用,丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

一、binlog 文件和文件的邏輯、物理表現(xiàn)形式
1. binlog 文件

binlog 文件主要包括:

mysql-bin.000001

mysql-bin.index

其中:

mysql-bin.index 內保存著 server 中未 purge 的 binlog 文件,以“文本”形式保留的。

2.binlog 文件格式

mysql-bin.index 沒啥可說的,我們專門看一下二進制 binlog 文件。

binlog 文件格式有以下特點:

binlog 是由 event 組成,event 是 binlog 的邏輯最小單元。

文件頭的頭四個字節(jié)為 BINLOG_MAGIC(fe 62 69 6e)

緊接著這四個字節(jié)的是 descriptor event:FORMAT_DESCRIPTION_EVENT

文件的末尾是 log-rotation event: ROTATE_EVENT

這兩個 event 中間是各種不同的 event,每個 event 代表 Master 上不同的操作。

下面對基本比較關鍵的概念進行說明:

BINLOG_MAGIC

利用 hexdump -C 讀取 mysql-bin.000005 的內容,

這里分別以十六進制和 ASCII 碼展示顯示,我們可以看到 binlog 的頭四個字節(jié)是固定的:fe 62 69 6e,后三個字符 ASCII 碼為 bin,指明展示一個 binlog 文件。這四個字節(jié)成為 BINLOG_MAGIC。

event

mysqlbinlog -vvv 讀取 mysql-bin.000011 的內容示例:

這里可以看到,第一個 event 是 FORMAT_DESCRIPTION_EVENT,它記錄了這個 binlog 的版本 (MySQL 5.0 以后 binlog 的版本都是 4)。最后一個 event,是 ROTATE_EVENT,它記錄了切換到下一個 binlog 文件的文件名。

在它們兩個之間是各種其他的 event,目前的 event 類型有:

enum Log_event_type { 
    UNKNOWN_EVENT= 0, 
    START_EVENT_V3= 1, 
    QUERY_EVENT= 2, 
    STOP_EVENT= 3, 
    ROTATE_EVENT= 4, 
    INTVAR_EVENT= 5, 
    LOAD_EVENT= 6, 
    SLAVE_EVENT= 7, 
    CREATE_FILE_EVENT= 8, 
    APPEND_BLOCK_EVENT= 9, 
    EXEC_LOAD_EVENT= 10, 
    DELETE_FILE_EVENT= 11, 
    NEW_LOAD_EVENT= 12, 
    RAND_EVENT= 13, 
    USER_VAR_EVENT= 14, 
    FORMAT_DESCRIPTION_EVENT= 15, 
    XID_EVENT= 16, 
    BEGIN_LOAD_QUERY_EVENT= 17, 
    EXECUTE_LOAD_QUERY_EVENT= 18, 
    TABLE_MAP_EVENT = 19, 
    PRE_GA_WRITE_ROWS_EVENT = 20, 
    PRE_GA_UPDATE_ROWS_EVENT = 21, 
    PRE_GA_DELETE_ROWS_EVENT = 22, 
    WRITE_ROWS_EVENT = 23, 
    UPDATE_ROWS_EVENT = 24, 
    DELETE_ROWS_EVENT = 25, 
    INCIDENT_EVENT= 26, 
    HEARTBEAT_LOG_EVENT= 27, 
    IGNORABLE_LOG_EVENT= 28,
    ROWS_QUERY_LOG_EVENT= 29,
    WRITE_ROWS_EVENT = 30,
    UPDATE_ROWS_EVENT = 31,
    DELETE_ROWS_EVENT = 32,
    GTID_LOG_EVENT= 33,
    ANONYMOUS_GTID_LOG_EVENT= 34,
    PREVIOUS_GTIDS_LOG_EVENT= 35, 
    ENUM_END_EVENT 
    /* end marker */ 
  };
 

當然,內部已經(jīng)有部分 event 被棄用了,我們不一一列舉,這里只簡單介紹幾個平時經(jīng)常見到的:

QUERY_EVENT:用于具體的 SQL 文本。如果 binlog_format=statement 方式下,insert,update,delete 等各種 SQL 都是以 Query event 記錄下來的。

WRITE_ROWS_EVENT,UPDATE_ROWS_EVENT,DELETE_ROWS_EVENT:在 binlog_format=row 方式下,insert,update,delete 操作的行信息分別以這三種 event 記錄下來。

GTID_LOG_EVENT:5.6 的 GTID 模式下,每個事務的 GTID 序號被記錄到這種 EVENT 中。

PREVIOUS_GTIDS_LOG_EVENT:5.6 的 GTID 模式下,這個 event 記錄了生成這個 binlog 之前,MySQL 已經(jīng)執(zhí)行的所有事務的 GTID 集合

二、slave io 在源碼中是怎么連上 Master 的

這里主要描述源碼中的函數(shù)調用關系

1. slave 如何注冊并請求 master 的 binlog

slave io 線程對應的入口函數(shù)為 sql/rpl_slave.cc:handle_slave_io()

該函數(shù)核心主要是做了以下三個事情:

safe_connect(thd, mysql, mi)

register_slave_on_master(mysql, mi, suppress_warnings)

request_dump(thd, mysql, mi, suppress_warnings)

event_len= read_event(mysql, mi, suppress_warnings);

也就是說,它先以標準的連接方式連上 master MySQL,然后把自己注冊到 master 上去,接著調用 request_dump 向 master 請求 binlog 數(shù)據(jù),最后一個一個 event 讀取并存放到本地 relay log 中。

safe_connect

連接 MySQL 的標準方式,MySQL c 的 connector 也是用這種方式連接 MySQL server 的。

register_slave_on_master

slave 把自己的 slave_id,IP,端口,用戶名提交給 Master,用于注冊自己到 Master 上去。

request_dump

根據(jù) GTID 來進行判斷,如果是 GTID 模式,那么把本地執(zhí)行的 GTID 集合及其他相關信息傳給 master;如果不是 GTID 模式,那么就把 master log file 和 Pos 傳給主庫。主庫如何根據(jù)這些信息來發(fā)送 binlog 的 event,參考下節(jié)。

read_event

read_event 調用了 cli_safe_read(),cli_safe_read() 調用了 my_net_read(),等待主庫將 binlog 數(shù)據(jù)發(fā)過來

也就是說,read_event 被動的從網(wǎng)絡中接受主庫發(fā)過來的信息。

2. master 如何處理 slave 的 binlog 請求

MySQL 處理各種命令的核心函數(shù)為:sql/sql_parse.cc:dispatch_command

該函數(shù)會根據(jù)用戶的請求來確定做什么事情,

COM_REGISTER_SLAVE 則調用 register_slave(thd, (uchar*)packet, packet_length) 注冊 slave

COM_BINLOG_DUMP_GTID 則調用 com_binlog_dump_gtid(thd, packet, packet_length);

COM_BINLOG_DUMP 則調用 com_binlog_dump(thd, packet, packet_length);

我們這里以 com_binlog_dump 為例介紹 master 怎么發(fā)送 binlog event 給 slave 的。

com_binlog_dump 核心代碼為:

kill_zombie_dump_threads(slave_uuid);

mysql_binlog_send(thd, thd- strdup(packet + 10), (my_off_t) pos, NULL)

kill_zombie_dump_threads() 函數(shù):如果新的 server_id 相同的 slave 注冊上來,master 會移除跟該 slave 的 server_id 匹配的的 binlog dump 線程

com_binlog_dump() 會調用 mysql_binlog_send() 來打開文件,將文件指針挪到指定位置,讀取文件,將一個個的 event 按照事件順序發(fā)給 slave。

綜上

MySQL 復制需要 slave 先注冊到 Master,再向 Master 提交 binlog 和 POS,請求發(fā)送 binlog。Master 接收到請求后,先做一系列驗證,打開本地 binlog 文件,按照內部 event 的順序,依序發(fā)給 slave。

三、sql 線程在源碼中是怎么讀取二進制信息,應用到本地 MySQL 的

sql 線程在 5.6 引入了 db 級別的并行,所以有兩個入口

1

2

handle_slave_worker

 handle_slave_sql

handle_slave_worker 線程是主要干活的函數(shù),handle_salve_sql 函數(shù)作為協(xié)調器會啟動和分配 worker 線程。

handle_slave_sql 函數(shù)主要調用了 slave_worker_exec_job。

slave_worker_exec_job 的主要功能:

job_item= pop_jobs_item(worker, job_item); ev= static_cast Log_event* (job_item- data);

error= ev- do_apply_event_worker(worker);

該函數(shù)做到事情其實就是 從 handle_salve_sql() 獲得具體的 event(ev),然后調用 ev- do_apply_event_worker(worker),利用 c ++ 的多態(tài)特性,調用真正的 event 的 do_apply_event 虛函數(shù),以便將不同的 event 的操作在本地做一遍。

這里需要大家回顧一下 event 的概念了,event 是 binlog 的最小單元,所有的 event 的父類是 Log_event(抽象基類),它定義了一系列虛函數(shù),其中就包括我們這里調用的函數(shù):

這里舉一個 insert 語句對應的的 Write_rows_log_event 例子,簡單說明一下數(shù)據(jù)是怎么應用到本地 MySQL 的。

Write_rows_log_event,Update_rows_log_event 和 Delete_rows_log_event 的 do_apply_event 都是調用的它的基類 Rows_log_event 的 do_apply_event。

Rows_log_event 的 do_apply_event 主要功能如下:

m_table= const_cast relay_log_info* >

error= (this- *do_apply_row_ptr)(rli);

get_table() 先從 table map 中獲得對應的 table 的信息,然后調用 do_apply_row_ptr 函數(shù)指針指向的函數(shù)來將 event 對應操作應用到本地 MySQL。

do_apply_row_ptr 函數(shù)指針可能指向以下幾種不同的函數(shù):

do_hash_scan_and_update

do_index_scan_and_update

do_table_scan_and_update

do_apply_row

Write_rows_log_event 是 insert,不用查找數(shù)據(jù),所以它調用的是 do_apply_row。

do_apply_row 主要的功能就是調用了 do_exec_row …. 汗

do_exec_row 是 Write_rows_log_event 自己實現(xiàn)的,它的主要功能是調用了 write_row …. 汗

write_row 也是 Write_rows_log_event 自己實現(xiàn)的,它的主要功能是:m_table- file- ha_start_bulk_insert(estimated_rows); 也就是說,它直接把這一行數(shù)據(jù)交給了存儲引擎,讓存儲引擎把數(shù)據(jù)給插進去。

四、binlog_format=ROW 格式下,MySQL 是怎么用二進制保存各種不同的數(shù)據(jù)類型的

在 sql/log_event.cc:log_event_print_value() 函數(shù)中詳細描述了 MySQL 的各種數(shù)據(jù)類型的二進制表現(xiàn)形式,摘錄如下

這里有幾個比較有意思的地方:

MYSQL_TYPE_STRING 類型,它的 length 占用的字節(jié)數(shù)是不固定的。如果 string 長度不到大于 255,則需要占用 2 個字節(jié),所以,MySQL 在定義 String 類型的字段時,255 是一個坎,如果字段不可能超過 255 個字節(jié),不建議定義長度的時候超過 255,否則 MySQL 存儲數(shù)據(jù)時會白白浪費一個字節(jié)。

MYSQL_TYPE_DATETIME 類型。它存儲的格式就是把年 - 月 - 日 時:分:秒按順序存儲下來的,比如:2015-10-10 22:45:55 存儲下來就存儲為 20151010224545。這種存儲格式比較浪費,所以字節(jié)數(shù)相比 timestamp 占用的也比較多。

關于“MySQL 中 binlog 有什么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

正文完
 
丸趣
版權聲明:本站原創(chuàng)文章,由 丸趣 2023-07-27發(fā)表,共計5575字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網(wǎng)絡搜集發(fā)布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 玉溪市| 香格里拉县| 子长县| 泸定县| 彭泽县| 清苑县| 阿拉善右旗| 梅州市| 扶风县| 修武县| 桓仁| 永济市| 香格里拉县| 秦皇岛市| 通海县| 葫芦岛市| 沐川县| 曲阳县| 凤阳县| 临颍县| 柞水县| 苏尼特右旗| 富宁县| 吕梁市| 黑山县| 昆山市| 郎溪县| 红安县| 霍城县| 师宗县| 静宁县| 玛纳斯县| 阿克陶县| 拜城县| 穆棱市| 洪泽县| 辛集市| 聂拉木县| 元谋县| 沙洋县| 本溪市|