背景問題
再講 binlog 之前,我們先來回顧下主流關系型數據庫的默認隔離級別,是默認隔離級別,不是事務有哪幾種隔離級別,別會錯題意了
1、Oracle、SQL Server 的默認隔離級別是什么,MySQL 的呢 ?
2、為什么 MySQL 的默認隔離級別是 RR ?
這個問題其實不太嚴謹,我們知道UMySQL 5.5 才將 InnoDB 代替 MyISAM 成為 MySQL 默認的存儲引擎,而事務才有隔離級別一說,MyISAM 本就不支持事務,那么這個問題在 MySQL 5.5 之前根本就不成立。
嚴謹點來說,應該是:為什么 MySQL 5.5 及之后版本的事務默認隔離級別是 RR,或者是:為什么 InnoDB 的事務默認隔離級別是 RR
對於問題1,我相信大家都能回答的上來,Oracle,SqlServer 的默認隔離級別是 都已提交( Read Commited,簡稱 RC) ,而 MySQL 的默認隔離級別是 可重復讀( Repeatable Read, 簡稱 RR)
但是對於問題2,相信有很多小伙伴就會支支吾吾了:呃...,這個...,昂昂昂昂昂,太久了我記憶都不太好了...
調皮的小伙伴可能就開始岔開話題了:你講 binlog 就講 binlog 啦,扯什么默認隔離級別,難道 MySQL 的默認隔離級別還與 binlog 有關 ?
想知道呀? 那得加錢
具體它倆是不是有關,樓主也不知道,我們一起往下看
binlog 格式
binlog 全稱:binary log,即mysql二進制日志,有時候也稱歸檔日志,記錄了對 MySQL 數據庫執行了更改的所有操作,包括表結構變更(CREATE、ALTER、DROP TABLE…)、表數據修改(INSERT、UPDATE、DELETE...),但不包括 SELECT 和 SHOW 這類操作,因為這類操作對數據本身並沒有修改;若更改操作並未導致數據庫變化,那么該操作也會寫入 binlog,例如
create table tbl_t1(name varchar(32)); insert into tbl_t1 values('zhangsan'); update tbl_t1 set name = 'lisi' where name = '123'; show master status\G; show binlog events in 'mysql-bin.000002'\G;
此時的:update tbl_t1 set name = 'lisi' where name = '123'; 並未引起數據庫的變化,但還是被記錄到了 binlog 中
binlog 的格式有三種:STATEMENT、ROW、MIXED,一開始只有 STATEMENT,后面慢慢衍生出了 ROW、MIXED
MySQL 5.1.5 之前 binlog 的格式只有 STATEMENT,5.1.5 開始支持 ROW 格式的 binlog,從 5.1.8 版本開始,MySQL 開始支持 MIXED 格式的 binlog
MySQL 5.7.7 之前,binlog 的默認格式都是 STATEMENT,在 5.7.7 及更高版本中,binlog_format 的默認值才是 ROW
三種格式的 binlog 各長什么樣,它們有什么區別,各有什么優劣,我們往下看
STATEMENT
從 MySQL 第一個版本,到目前最新的 8.0.x,STATEMENT 一直堅挺在 binlog 的格式中,只是從 5.7.7 開始,它退居幕后,頭把交椅給了 ROW
binglog 與我們開發中的代碼日志是不一樣的,它包含兩類文件
索引文件:文件名.index,記錄了哪些日志文件正在被使用,內容如下
日志文件:文件名.00000*
記錄了對 MySQL 數據庫執行了更改的所有操作
因為 binlog 的日志文件是二進制文件,不能用文本編輯器直接打開,需要用特定的工具來打開,MySQL 提供了 mysqlbinlog 來幫助我們查看日志文件內容
mysqlbinlog 可選參數很多, mysqlbinlog.exe -- help
mysqlbinlog.exe Ver 3.3 for Win64 at x86 Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Dumps a MySQL binary log in a format usable for viewing or for piping to the mysql command line client. Usage: mysqlbinlog.exe [options] log-files -?, --help Display this help and exit. --base64-output[=name] Determine when the output statements should be base64-encoded BINLOG statements: 'never' disables it and works only for binlogs without row-based events; 'decode-rows' decodes row events into commented SQL statements if the --verbose option is also given; 'auto' prints base64 only when necessary (i.e., for row-based events and format description events); 'always' prints base64 whenever possible. 'always' is deprecated, will be removed in a future version, and should not be used in a production system. --base64-output with no 'name' argument is equivalent to --base64-output=always and is also deprecated. If no --base64-output[=name] option is given at all, the default is 'auto'. --character-sets-dir=name Directory for character set files. -d, --database=name List entries for just this database (local log only). --debug-check Check memory and open file usage at exit . --debug-info Print some debug info at exit. -D, --disable-log-bin Disable binary log. This is useful, if you enabled --to-last-log and are sending the output to the same MySQL server. This way you could avoid an endless loop. You would also like to use it when restoring after a crash to avoid duplication of the statements you already have. NOTE: you will need a SUPER privilege to use this option. -F, --force-if-open Force if binlog was not closed properly. (Defaults to on; use --skip-force-if-open to disable.) -f, --force-read Force reading unknown binlog events. -H, --hexdump Augment output with hexadecimal and ASCII event dump. -h, --host=name Get the binlog from server. -l, --local-load=name Prepare local temporary files for LOAD DATA INFILE in the specified directory. -o, --offset=# Skip the first N entries. -p, --password[=name] Password to connect to remote server. -P, --port=# Port number to use for connection or 0 for default to, in order of preference, my.cnf, $MYSQL_TCP_PORT, /etc/services, built-in default (3306). --protocol=name The protocol to use 