1. 程式人生 > 實用技巧 >mysql常用日誌

mysql常用日誌

事務的日誌

1. redo log,重做日誌,是事務日誌的一種

作用
在事務ACID過程中,實現的是'D'持久化的作用。(#儲存在磁碟)
REDO:記錄的是,記憶體資料頁的'變化過程'
特性:WAL(Write Ahead Log)日誌優先寫

文字描述

#修改,建立,刪除
1)首先將表中 id=1的行所在'資料頁'載入到記憶體中data buffer page('資料緩衝區')
2)MySQL例項在記憶體中將 id=1的資料頁'改'成 id=2
3)id=1變成 id=2的'變化過程會記錄到',redo記憶體區域,也就是redo buffer page中('重做緩衝區')
4)當敲下'commit'命令的瞬間,MySQL會將redo buffer page'寫入磁碟'區域redo log,返回ok
#過程
ibdata1 --> data buffer page --> redobuffer page -->redo log
#資料庫重啟或者隔一段時間,redo log中的日誌會寫入到ibdata1(.ibd)中

#查詢
1.首先將表中id=1的行所在資料頁載入到記憶體中data buffer page
2.將redo log中id=1變成id=2的變化過程取載入到redo buffer page
3.通過data buffer page和redo buffer page得到一個結果
#過程
ibdata1 --> data buffer page '???' redo buffer page <-- redo log

2.undo log,回滾日誌,也是事務日誌的一種

作用
在事務ACID過程中,實現的是'A'原子性的作用。當然CI的特性也和undo有關

#redo log 和undo log 都是事務的日誌,不是資料庫命令的日誌

斷電的三種情況(如何恢復記憶體中的資料)

1.執行了commit,啟動資料庫,資料恢復,id=2(CSR)
2.沒有執行commit,但是資料儲存到了redo log(過了一段時間),id=2,但是因為undo buffer page中沒有記錄commit,所以 id=1
3.沒有執行commit,資料沒有儲存到redo log, id=1

#源資料+變化過程=修改後的內容

redo和undo的儲存位置

#redo位置
[root@db02 ~]# ll /usr/local/mysql/data/
-rw-rw---- 1 mysql mysql 50331648 Aug 15 06:34 ib_logfile0
-rw-rw---- 1 mysql mysql 50331648 Mar  6  2017 ib_logfile1

#undo位置
[root@db02 ~]# ll /usr/local/mysql/data/
-rw-rw---- 1 mysql mysql 79691776 Aug 15 06:34 ibdata1		#共享表空間
-rw-rw---- 1 mysql mysql 79691776 Aug 15 06:34 ibdata2

事務中的鎖

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

#檢視mysql儲存引擎
mysql> show create table cs;
| cs    | CREATE TABLE `cs` (
  `id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |

#mysql innodb儲存引擎支援鎖,pyisam不支援鎖

#建立指定innodb儲存引擎的表
mysql> create table suo(id int) engine=innodb;

#鎖
db03 tty1
mysql> create table suo1(id int);
mysql> insert suo1 values(1);
mysql> select * from suo1;
+------+
| id   |
+------+
|    1 |
+------+
mysql> update suo1 set id=2 where id=1;
mysql> select * from suo1;
+------+
| id   |
+------+
|    2 |
+------+

db03 tty2
mysql> update suo1 set id=3 where id=1;
mysql> select * from suo1;
+------+
| id   |
+------+
|    2 |
+------+


#mysql裡面誰先提交誰為準,Redis裡面誰後提交誰為準

innoDB中鎖的類別

排他鎖:在我'修改時',別人不能修改(#行級鎖)
共享鎖:保證在多事務工作期間,'資料查詢時'不會被阻塞。

樂觀鎖:多事務操作時,資料可以同時修改,誰先提交,以誰為準(#購票)
悲觀鎖:多事務操作時,資料只有一個人可以修改(#購物車+購票)

多版本併發控制(多鎖一起用)

1.只阻塞修改類操作(排他鎖),不阻塞查詢類操作(共享鎖)
2.樂觀鎖的機制(誰先提交誰為準)

鎖的粒度

1.myisam		表級鎖
2.innoDB		行級鎖,效率更高

隔離

事務中的隔離級別

1.RU級別:READ UNCOMMITTED(獨立提交):'未提交讀',允許事務檢視其他事務所進行的未提交更改,
問題1.不安全,2.會出現髒讀

2.RC級別:READ COMMITTED:允許事務檢視其他事務所進行的已提交更改,檢視'不需要重新進入資料庫'
3.RR級別:REPEATABLE READ:允許事務檢視其他事務所進行的已提交更改,檢視資料需要'有時重新進入資料庫'('InnoDB 的預設級別')

4.序列化:SERIALIZABLE:將一個事務的結果與其他事務'完全隔離'(最大程度的隔離)

#檢視隔離級別
mysql> show variables like '%iso%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |  #RR級別,系統預設
+---------------+-----------------+

#設定隔離級別(RU RC #RR)
[root@db03 ~]# vim /etc/my.cnf
#log_bin=mysql-bin
transaction_isolation=read-uncommit
transaction_isolation=read-commit
[root@db03 ~]# /etc/init.d/mysqld restart
mysql> show variables like '%iso%';
+---------------+------------------+
| Variable_name | Value            |
+---------------+------------------+
| tx_isolation  | READ-UNCOMMITTED |  #RU級別
+---------------+------------------+
mysql> update suo1 set id=1 where id=100;
mysql> select * from suo1;
+------+
| id   |
+------+
|    1 |
+------+
mysql> rollback;
mysql> select * from suo1;
+------+
| id   |
+------+
|  100 |	#如果id=1已經被使用,那麼這種現象即為髒讀	
+------+

名詞:
1.RU級別會出現'髒讀':RU級別,執行事務修改資料,被讀取,但是資料最終回滾了,查詢到的資料就是髒
2.幻讀:刪除所有表資料,刪除的同時有人插入資料,檢視資料時'以為是'沒刪乾淨
3.不可重複讀:修改資料後被讀取,被讀取之後再次修改資料,兩次資料不一致(#訪問次數)

檢視隔離級別

#檢視隔離級別
mysql> show variables like '%iso%';

設定隔離級別

#設定RU級別
[root@db03 ~]# vim /etc/my.cnf
transaction_isolation=read-uncommit

#設定RC級別
[root@db03 ~]# vim /etc/my.cnf
transaction_isolation=read-commit

mysql日誌

mysql 錯誤日誌

1.錯誤日誌'預設是關閉的'
2.錯誤日誌檔案預設路徑是 $datadir/主機名.err

檢視錯誤日誌路徑
0)初始化之後
rm -rf /usr/local/mysql/data/ibdata*
./mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data/
/etc/init.d/mysqld start
1)命令列
[root@db02 ~]# mysql -e "show variables like '%log_err%'"
+---------------------+---------------------------------+
| Variable_name       | Value                           |
+---------------------+---------------------------------+
| log_error           | 							 |
+---------------------+---------------------------------+
2)SQL語句
mysql> show variables like 'log_err';

#配置錯誤日誌
    [root@db02 ~]# vim /etc/my.cnf
    [mysqld]
    server_id=1
    basedir=/usr/local/mysql
    datadir=/usr/local/mysql/data
    port=3306
    socket=/tmp/mysql.sock
    skip-name-resolve
    log_err=/usr/local/mysql/data/mysql.err  (#相對路徑的話,放到data目錄)

    [mysql]
    socket=/tmp/mysql.sock

#檢視錯誤日誌
less /usr/local/mysql/data/mysql.err

#作用
mysql資料庫啟動不了的時候,檢視報錯

#購買了阿里雲主機,安裝mysql後,第一時間修改mysql錯誤日誌,來指定mysql錯誤日誌的格式

mysql查詢日誌

1.查詢日誌預設是'關閉的'
2.查詢日誌'檔案默路徑'是 $datadir/主機名.log

檢視查詢日誌路徑
    mysql> show variables like '%general%';
    +------------------+--------------------------------+
    | Variable_name    | Value                          |
    +------------------+--------------------------------+
    | general_log      | OFF                            |	#
    | general_log_file | /usr/local/mysql/data/db02.log |
    +------------------+--------------------------------+

配置查詢日誌
    [root@db02 ~]# vim /etc/my.cnf
    [mysqld]
    log_err=/usr/local/mysql/data/mysql.err
    general_log=on/1
    general_log_file=/usr/local/mysql/data/db02.log

    [mysql]
    socket=/tmp/mysql.sock
    
#檢視查詢日誌
less /usr/local/mysql/data/db02.log

#作用
記錄sql語句執行過的命令(#一般不用 Ctrl+R)

二進位制日誌

1.二進位制檔案'預設是關閉的'
2.二進位制配置'路徑和名字'由配置檔案決定,一般儲存在 $datadir/mysql-bin 命名(預設)

1.二進位制日誌管理操作

1)開啟二進位制日誌

配置bin_log
3.配置binlog
    [root@db02 ~]# vim /etc/my.cnf
    [mysqld]
    server_id
    log_bin=/usr/local/mysql/data/mysql-bin
	#log-bin=/usr/local/mysql/data/mysql-bin

#mysql5.7(log_bin)只支援下劃線_ ,5.6支援 - _
#mysql5.7必須指定server_id
#binlog生成預設大小是120(重新整理後是143),也是binlog當前的位置點
#資料庫重啟會生成新的mysql-bin.00000x
#企業全備和增備一起用

2)檢視二進位制日誌

#物理檢視
[root@db02 ~]# ll /usr/local/mysql/data/
-rw-rw---- 1 mysql mysql      120 Jul 21 19:24 mysql-bin.000001
-rw-rw---- 1 mysql mysql       39 Jul 21 19:24 mysql-bin.index
[root@db03 ~]# mysql -uroot -p123 -e'show variables like "%log_bin%"'

#資料庫檢視
mysql> show variables like '%bin%'		#檢視like命令和預設
| log_bin                                 | OFF                  |
show variables like 'log_bin'
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin                         | OFF   |		#預設關閉
| log_bin_basename                |       |
| log_bin_index                   |       |
| log_bin_trust_function_creators | OFF   |
| log_bin_use_v1_row_events       | OFF   |
| sql_log_bin                     | ON    |
+---------------------------------+-------+

3)事件

1.什麼是事件
	1)在binlog中最小的記錄單元為event('一個SQL命令')
	2)一個'事務'會被拆分成多個事件(event)

2.事件(event)特性
    1)每個event都有一個'開始位置'(start position)和'結束位置'(stop position)。
    2)所謂的位置就是event對整個二進位制的檔案的'相對位置'。(相對於120)
    3)對於一個二進位制日誌中,'前120個'position是'檔案格式資訊預留空間'。
    4)MySQL第一個記錄的事件,都是從120開始的。
#檢視bin_log

物理檢視
[root@db03 ~]# ll /service/mysql/data/
-rw-rw---- 1 mysql mysql      120 Jul 20 21:40 mysql-bin.000001
-rw-rw---- 1 mysql mysql      143 Jul 20 21:52 mysql-bin.000002	#最新(143)

SQL語句檢視
[root@db03 ~]# vim /etc/my.cnf
log_bin=mysql-bin
server_id=2
mysql> show master status;
+------------------+----------+
| File             | Position |
+------------------+----------+
| mysql-bin.000010 |      120 |

#重啟資料庫(修改模式)會生成新的bin_log,預設的bin_log大小變成143,寫入了一點系統記錄

4)重新整理binlog

1)flush logs;		#會產生新的log-bin.00000x  #可以和全備一起用
2)重啟資料庫時會重新整理
3)二進位制日誌上限,預設1G(可以使用 max_binlog_size=xx修改)

5)刪除binlog

1.根據存在時間刪除日誌
#臨時生效
mysql> set global expire_logs_days=7;
#永久生效
[root@db01 data]# vim /etc/my.cnf
[mysqld]
expire_logs_days = 7

2.使用purge命令刪除(刪除從現在起 3天前)
mysql> purge binary logs before now() -interval 3 day;

3.根據檔名刪除(只保留10)
PURGE BINARY LOGS TO 'mysql-bin.000010';

4.使用reset master(重置binlog,刪除所有的binlog)(會導致主從複製卡住)
mysql> reset master; 

#不能使用rm刪除binlog,因為索引裡仍有該索引的記錄
[root@db03 data]# cat mysql-bin.index 
./mysql-bin.000001
./mysql-bin.000002
./mysql-bin.000003

#沒有備份的情況下,刪除binlog的話無法找回

2.二進位制日誌作用

1.記錄已提交的DML事務語句,並拆分為多個事件('event執行單元')來進行記錄
2.記錄所有DDL、DCL等語句,總之,二進位制日誌會'記錄'所有對資料庫發生修改的操作

3.如果我擁有資料庫搭建開始,'有所有的二進位制日誌',那麼我可以'把資料恢復到任意時刻'
但是一般使用'全備和增備'恢復資料庫資料
4.利用bin_log進行資料的備份與恢復
5.資料的主從複製

#檢視幫助
[root@db03 ~]# mysqldump --help

#使用mysqldump命令需要指定 -S /tmp/mysql.sock

1)資料庫的備份與恢復

1>新增資料
mysql> create database binlog;
mysql> use binlog
mysql> create table binlog(id int);
mysql> insert binlog values(1),(2),(3);
mysql> insert binlog values(4);
mysql> insert binlog values(5);

mysql> select * from binlog;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
2>刪除資料
#誤刪除兩條資料
mysql> delete from binlog where id=5;
mysql> delete from binlog where id=4;
mysql> delete from bl where id=5 or id=4;
3>通過binlog恢復資料
#檢視二進位制日誌找到位置點
[root@db02 data]# mysqlbinlog mysql-bin.000002
...
...
# at 4
...
...
# at 120 (位置點)
create database bl
/*!*/;
# at 208
use `bl`/*!*/;
SET TIMESTAMP=1595361536/*!*/;
create table bbl(id int)
/*!*/;

#將位置點之間的資料取出
[root@db02 data]# mysqlbinlog --start-position=631 --stop-position=978 mysql-bin.000002 > /tmp/hf.sql

#將資料匯入回去
[root@db02 data]# mysql < /tmp/45.sql

#檢視
select * from binlog

#一個事務可以包含多個位置點
#企業資料庫不會隨便重啟,所以binlog可能會很大
#通過binlog恢復資料是不現實的,因為企業中的binlog很大(不好操作)
#企業中不會超過一個月的binlog,但是binlog資料量依然很大

2)使用binlog配合資料庫升級(企業資料庫的切換)

1.準備一臺新的資料庫,版本為5.6.38
2.舊資料庫備份資料(同時匯出多個庫)(要想使用--master-data=2,資料庫必須配置bin_log)
	[root@db03 ~]# mysqldump -uroot -p123 --triggers -R --master-data=2 -B ku linux9 myisam qiudao qiudaodsb tmp world xiangqing >/tmp/full.sql
3.將備份的資料庫傳到新資料庫
	[root@db03 ~]# scp /tmp/full.sql 172.16.1.52:/tmp/
4.修改sql中的儲存引擎
	[root@db02 data]# sed -i 's#MyISAM#InnoDB#g' /tmp/full.sql
5.將修改後的sql檔案匯入新資料
	[root@db02 data]# mysql < /tmp/full.sql
	
	
6.將程式碼中的資料庫地址修改為新的資料庫地址
7.通過binlog將資料遷移過程中新生成的資料取出
	[root@db03 data]# mysqlbinlog -uroot -p123 --start-position=120 --stop-position=465 mysql-bin.000014 > /tmp/bu.sql
	[root@db03 data]# scp /tmp/bu.sql 172.16.1.52:/tmp/
8.將新資料匯入新庫
	[root@db02 data]# mysql < /tmp/bu.sql
	select * from xx

#解決新資料寫入的方法
1.先匯入'舊資料',將web中程式碼的地址修改為新庫,再通過binlog將'新資料'匯出再匯入新庫就可以了
2.先做舊庫和新庫做'主從複製',再根據位置點匯入'舊資料',再'切庫',再斷開主從(切庫會導致資料少量丟失)

報錯

mysql> insert bbl values(1);
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.