如果您對數據庫感興趣,可以添加 DBA解決方案QQ群:895979329
1、簡介
相當于Linux文件系統,只不過比文件系統強大
2、功能了解
數據讀寫
數據安全和一致性
提高性能
熱備份
自動故障恢復
高可用方面支持
等.
3、存儲引擎種類(筆試)
3.1 介紹(Oracle MySQL)
InnoDB
MyISAM
MEMORY
ARCHIVE
FEDERATED
EXAMPLE
BLACKHOLE
MERGE
NDBCLUSTER
CSV
3.2 引擎種類查看
show engines;
存儲引擎是作用在表上的,也就意味著,不同的表可以有不同的存儲引擎類型。
PerconaDB:默認是XtraDB
MariaDB:默認是InnoDB
其他的存儲引擎支持:
TokuDB
RocksDB
MyRocks
以上三種存儲引擎的共同點:壓縮比較高,數據插入性能極高
現在很多的NewSQL,使用比較多的功能特性.
3.3 簡歷案例---zabbix監控系統架構整改
環境: zabbix 3.2 mariaDB 5.5 centos 7.3
現象 : zabbix卡的要死 , 每隔3-4個月,都要重新搭建一遍zabbix,存儲空間經常爆滿.
問題 :
1. zabbix 版本
2. 數據庫版本
3. zabbix數據庫500G,存在一個文件里
優化建議:
1.數據庫版本升級到5.7版本,zabbix升級更高版本
2.存儲引擎改為tokudb
3.監控數據按月份進行切割(二次開發:zabbix 數據保留機制功能重寫,數據庫分表)
4.關閉binlog和雙1
5.參數調整....
優化結果:
監控狀態良好
為什么?
1. 原生態支持TokuDB,另外經過測試環境,5.7要比5.5 版本性能 高 2-3倍
2. TokuDB:insert數據比Innodb快的多,數據壓縮比要Innodb高
3.監控數據按月份進行切割,為了能夠truncate每個分區表,立即釋放空間
4.關閉binlog ----->減少無關日志的記錄.
5.參數調整...----->安全性參數關閉,提高性能.
3.4 InnoDB個MyISAM存儲引擎的替換
環境: centos 5.8 ,MySQL 5.0版本,MyISAM存儲引擎,網站業務(LNMP),數據量50G左右
現象問題: 業務壓力大的時候,非???經歷過宕機,會有部分數據丟失.
問題分析:
1.MyISAM存儲引擎表級鎖,在高并發時,會有很高鎖等待
2.MyISAM存儲引擎不支持事務,在斷電時,會有可能丟失數據
職責
1.監控鎖的情況:有很多的表鎖等待
2.存儲引擎查看:所有表默認是MyISAM
解決方案:
1.升級MySQL 5.6.10版本
2. 遷移所有表到新環境
3. 開啟雙1安全參數
4、InnoDB存儲引擎介紹
image.png
在MySQL5.5版本之后,默認的存儲引擎,提供高可靠性和高性能。
4.1 優點
1、事務(Transaction)
2、MVCC(Multi-Version Concurrency Control多版本并發控制)
3、行級鎖(Row-level Lock)
4、ACSR(Auto Crash Safey Recovery)自動的故障安全恢復
5、支持熱備份(Hot Backup)
6、Replication: Group Commit , GTID (Global Transaction ID) ,多線程(Multi-Threads-SQL )
4.2 筆試題
請你列舉MySQL InnoDB存儲優點?
請你列舉 InooDB和MyIsam的區別?
5. 存儲引擎查看
5.1 使用 SELECT 確認會話存儲引擎
SELECT @@default_storage_engine;
## 5.2 存儲引擎(不代表生產操作)
會話級別:
set default_storage_engine=myisam;
全局級別(僅影響新會話):
set global default_storage_engine=myisam;
重啟之后,所有參數均失效.
如果要永久生效:
寫入配置文件
vim /etc/my.cnf
[mysqld]
default_storage_engine=myisam
存儲引擎是表級別的,每個表創建時可以指定不同的存儲引擎,但是我們建議統一為innodb.
5.3 SHOW 確認每個表的存儲引擎:
SHOW CREATE TABLE City\G;
SHOW TABLE STATUS LIKE 'CountryLanguage'\G
5.4 INFORMATION_SCHEMA 確認每個表的存儲引擎
[world]>select table_schema,table_name ,engine from information_schema.tables where table_schema not in ('sys','mysql','information_schema','performance_schema');
Master [world]>show table status;
Master [world]>show create table city;
5.5 修改一個表的存儲引擎
db01 [oldboy]>alter table t1 engine innodb;
注意:此命令我們經常使用他,進行innodb表的碎片整理
5.6 平常處理過的MySQL問題--碎片處理
環境:centos7.4,MySQL 5.7.20,InnoDB存儲引擎
業務特點:數據量級較大,經常需要按月刪除歷史數據.
問題:磁盤空間占用很大,不釋放
處理方法:
以前:將數據邏輯導出,手工drop表,然后導入進去
現在:
對表進行按月進行分表(partition,中間件)
業務替換為truncate方式
5.6 擴展:如何批量修改
需求:將zabbix庫中的所有表,innodb替換為tokudb
select concat("alter table zabbix.",table_name," engine tokudb;") from
information_schema.tables where table_schema='zabbix' into outfile '/tmp/tokudb.sql';
6、InnoDB存儲引擎物理存儲結構
6.0 最直觀的存儲方式(/data/mysql/data)
ibdata1:系統數據字典信息(統計信息),UNDO表空間等數據
ib_logfile0 ~ ib_logfile1: REDO日志文件,事務日志文件。
ibtmp1: 臨時表空間磁盤位置,存儲臨時表
frm:存儲表的列信息
ibd:表的數據行和索引
6.1 表空間(Tablespace)
6.1.1、共享表空間
需要將所有數據存儲到同一個表空間中 ,管理比較混亂
5.5版本出現的管理模式,也是默認的管理模式。
5.6版本以,共享表空間保留,只用來存儲:數據字典信息,undo,臨時表。
5.7 版本,臨時表被獨立出來了
8.0版本,undo也被獨立出去了
具體變化參考官方文檔:
https://dev.mysql.com/doc/refman/5.6/en/innodb-architecture.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-architecture.html
https://dev.mysql.com/doc/refman/5.8/en/innodb-architecture.html
6.1.2 共享表空間設置
共享表空間設置(在搭建MySQL時,初始化數據之前設置到參數文件中)
[(none)]>select @@innodb_data_file_path;
[(none)]>show variables like '%extend%';
innodb_data_file_path=ibdata1:512M:ibdata2:512M:autoextend
innodb_autoextend_increment=64
6.1.3 獨立表空間
從5.6,默認表空間不再使用共享表空間,替換為獨立表空間。
主要存儲的是用戶數據
存儲特點為:一個表一個ibd文件,存儲數據行和索引信息
基本表結構元數據存儲:
xxx.frm
最終結論:
元數據 數據行+索引
mysql表數據 =(ibdataX+frm)+ibd(段、區、頁)
DDL DML+DQL
MySQL的存儲引擎日志:
Redo Log: ib_logfile0 ib_logfile1,重做日志
Undo Log: ibdata1 ibdata2(存儲在共享表空間中),回滾日志
臨時表:ibtmp1,在做join union操作產生臨時數據,用完就自動
6.1.4 獨立表空間設置問題
db01 [(none)]>select @@innodb_file_per_table;
+-------------------------+
| @@innodb_file_per_table |
+-------------------------+
| 1 |
+-------------------------+
alter table city dicard tablespace;
alter table city import tablespace;
6.1.5 真實的學生案例
案例背景:
硬件及軟件環境:
聯想服務器(IBM)
磁盤500G 沒有raid
centos 6.8
mysql 5.6.33 innodb引擎 獨立表空間
備份沒有,日志也沒開
開發用戶專用庫:
jira(bug追蹤) 、 confluence(內部知識庫) ------>LNMT
故障描述:
斷電了,啟動完成后“/” 只讀
fsck 重啟,系統成功啟動,mysql啟動不了。
結果:confulence庫在 , jira庫不見了
學員求助內容:
求助:
這種情況怎么恢復?
我問:
有備份沒
求助:
連二進制日志都沒有,沒有備份,沒有主從
我說:
沒招了,jira需要硬盤恢復了。
求助:
1、jira問題拉倒中關村了
2、能不能暫時把confulence庫先打開用著
將生產庫confulence,拷貝到1:1虛擬機上/var/lib/mysql,直接訪問時訪問不了的
問:有沒有工具能直接讀取ibd
我說:我查查,最后發現沒有
我想出一個辦法來:
表空間遷移:
create table xxx
alter table confulence.t1 discard tablespace;
alter table confulence.t1 import tablespace;
虛擬機測試可行。
處理問題思路:
confulence庫中一共有107張表。
1、創建107和和原來一模一樣的表。
他有2016年的歷史庫,我讓他去他同時電腦上 mysqldump備份confulence庫
mysqldump -uroot -ppassw0rd -B confulence --no-data >test.sql
拿到你的測試庫,進行恢復
到這步為止,表結構有了。
2、表空間刪除。
select concat('alter table ',table_schema,'.'table_name,' discard tablespace;') from information_schema.tables where table_schema='confluence' into outfile '/tmp/discad.sql';
source /tmp/discard.sql
執行過程中發現,有20-30個表無法成功。主外鍵關系
很絕望,一個表一個表分析表結構,很痛苦。
set foreign_key_checks=0 跳過外鍵檢查。
把有問題的表表空間也刪掉了。
3、拷貝生產中confulence庫下的所有表的ibd文件拷貝到準備好的環境中
select concat('alter table ',table_schema,'.'table_name,' import tablespace;') from information_schema.tables where table_schema='confluence' into outfile '/tmp/discad.sql';
4、驗證數據
表都可以訪問了,數據挽回到了出現問題時刻的狀態(2-8)
8、事務的ACID特性
Atomic(原子性)
所有語句作為一個單元全部成功執行或全部取消。不能出現中間狀態。
Consistent(一致性)
如果數據庫在事務開始時處于一致狀態,則在執行該事務期間將保留一致狀態。
Isolated(隔離性)
事務之間不相互影響。
Durable(持久性)
事務成功完成后,所做的所有更改都會準確地記錄在數據庫中。所做的更改不會丟失。
9、事務的生命周期(事務控制語句)
9.1 事務的開始
begin
說明:在5.5 以上的版本,不需要手工begin,只要你執行的是一個DML,會自動在前面加一個begin命令。
9.2 事務的結束
commit:提交事務
完成一個事務,一旦事務提交成功 ,就說明具備ACID特性了。
rollback :回滾事務
將內存中,已執行過的操作,回滾回去
9.3 自動提交策略(autocommit)
db01 [(none)]>select @@autocommit;
db01 [(none)]>set autocommit=0;
db01 [(none)]>set global autocommit=0;
注:
自動提交是否打開,一般在有事務需求的MySQL中,將其關閉
不管有沒有事務需求,我們一般也都建議設置為0,可以很大程度上提高數據庫性能
(1)
set autocommit=0;
set global autocommit=0;
(2)
vim /etc/my.cnf
autocommit=0
9.4 隱式提交語句
用于隱式提交的 SQL 語句:
begin
a
b
begin
SET AUTOCOMMIT = 1
導致提交的非事務語句:
DDL語句: (ALTER、CREATE 和 DROP)
DCL語句: (GRANT、REVOKE 和 SET PASSWORD)
鎖定語句:(LOCK TABLES 和 UNLOCK TABLES)
導致隱式提交的語句示例:
TRUNCATE TABLE
LOAD DATA INFILE
SELECT FOR UPDATE
9.5 開始事務流程:
1、檢查autocommit是否為關閉狀態
select @@autocommit;
或者:
show variables like 'autocommit';
2、開啟事務,并結束事務
begin
delete from student where name='alexsb';
update student set name='alexsb' where name='alex';
rollback;
begin
delete from student where name='alexsb';
update student set name='alexsb' where name='alex';
commit;
10. InnoDB 事務的ACID如何保證?
10.0 一些概念
redo log ---> 重做日志 ib_logfile0~1 50M , 輪詢使用
redo log buffer ---> redo內存區域
ibd ----> 存儲 數據行和索引
buffer pool --->緩沖區池,數據和索引的緩沖
LSN : 日志序列號
磁盤數據頁,redo文件,buffer pool,redo buffer
MySQL 每次數據庫啟動,都會比較磁盤數據頁和redolog的LSN,必須要求兩者LSN一致數據庫才能正常啟動
WAL : write ahead log 日志優先寫的方式實現持久化
臟頁: 內存臟頁,內存中發生了修改,沒寫入到磁盤之前,我們把內存頁稱之為臟頁.
CKPT:Checkpoint,檢查點,就是將臟頁刷寫到磁盤的動作
TXID: 事務號,InnoDB會為每一個事務生成一個事務號,伴隨著整個事務.
image
10.1 redo log
10.1.1 Redo是什么?
redo,顧名思義“重做日志”,是事務日志的一種。
10.1.2 作用是什么?
在事務ACID過程中,實現的是“D”持久化的作用。對于AC也有相應的作用
10.1.3 redo日志位置
redo的日志文件:iblogfile0 iblogfile1
10.1.4 redo buffer
redo的buffer:數據頁的變化信息+數據頁當時的LSN號
LSN:日志序列號 磁盤數據頁、內存數據頁、redo buffer、redolog
10.1.5 redo的刷新策略
commit;
刷新當前事務的redo buffer到磁盤
還會順便將一部分redo buffer中沒有提交的事務日志也刷新到磁盤
10.1.6 MySQL CSR——前滾
MySQL : 在啟動時,必須保證redo日志文件和數據文件LSN必須一致, 如果不一致就會觸發CSR,最終保證一致
情況一:
我們做了一個事務,begin;update;commit.
1.在begin ,會立即分配一個TXID=tx_01.
2.update時,會將需要修改的數據頁(dp_01,LSN=101),加載到data buffer中
3.DBWR線程,會進行dp_01數據頁修改更新,并更新LSN=102
4.LOGBWR日志寫線程,會將dp_01數據頁的變化+LSN+TXID存儲到redobuffer
5. 執行commit時,LGWR日志寫線程會將redobuffer信息寫入redolog日志文件中,基于WAL原則,
在日志完全寫入磁盤后,commit命令才執行成功,(會將此日志打上commit標記)
6.假如此時宕機,內存臟頁沒有來得及寫入磁盤,內存數據全部丟失
7.MySQL再次重啟時,必須要redolog和磁盤數據頁的LSN是一致的.但是,此時dp_01,TXID=tx_01磁盤是LSN=101,dp_01,TXID=tx_01,redolog中LSN=102
MySQL此時無法正常啟動,MySQL觸發CSR.在內存追平LSN號,觸發ckpt,將內存數據頁更新到磁盤,從而保證磁盤數據頁和redolog LSN一值.這時MySQL正長啟動
以上的工作過程,我們把它稱之為基于REDO的"前滾操作"
11.2 undo 回滾日志
11.2.1 undo是什么?
undo,顧名思義“回滾日志”
11.2.2 作用是什么?
在事務ACID過程中,實現的是“A” 原子性的作用
另外CI也依賴于Undo
在rolback時,將數據恢復到修改之前的狀態
在CSR實現的是,將redo當中記錄的未提交的時候進行回滾.
undo提供快照技術,保存事務修改之前的數據狀態.保證了MVCC,隔離性,mysqldump的熱備
11.3 概念性的東西:
redo怎么應用的
undo怎么應用的
CSR(自動故障恢復)過程
LSN :日志序列號
TXID:事務ID
CKPT(Checkpoint)
11.4 鎖
“鎖”顧名思義就是鎖定的意思。
“鎖”的作用是什么?
在事務ACID過程中,“鎖”和“隔離級別”一起來實現“I”隔離性和"C" 一致性 (redo也有參與).
悲觀鎖:行級鎖定(行鎖)
誰先操作某個數據行,就會持有<這行>的(X)鎖.
樂觀鎖: 沒有鎖
11.5 隔離級別
影響到數據的讀取,默認的級別是 RR模式.
transaction_isolation 隔離級別(參數)
負責的是,MVCC,讀一致性問題
RU : 讀未提交,可臟讀,一般部議敘出現
RC : 讀已提交,可能出現幻讀,可以防止臟讀.
RR : 可重復讀,功能是防止"幻讀"現象 ,利用的是undo的快照技術+GAP(間隙鎖)+NextLock(下鍵鎖)
SR : 可串行化,可以防止死鎖,但是并發事務性能較差
補充: 在RC級別下,可以減輕GAP+NextLock鎖的問題,但是會出現幻讀現象,一般在為了讀一致性會在正常select后添加for update語句.但是,請記住執行完一定要commit 否則容易出現所等待比較嚴重.
例如:
[world]>select * from city where id=999 for update;
[world]>commit;
11.6 架構改造項目
項目背景:
2臺 IBM X3650 32G ,原來主從關系,2年多沒有主從了,"小問題"不斷(鎖,宕機后的安全)
MySQL 5.1.77 默認存儲引擎 MyISAM
數據量: 60G左右 ,每周全備,沒有開二進制日志
架構方案:
1. 升級數據庫版本到5.7.20
2. 更新所有業務表的存儲引擎為InnoDB
3. 重新設計備份策略為熱備份,每天全備,并備份日志
4. 重新構建主從
結果:
1.性能
2.安全方面
3.快速故障處理
12 InnoDB存儲引擎核心特性-參數補充
12.1 存儲引擎相關
12.1.1 查看
show engines;
show variables like 'default_storage_engine';
select @@default_storage_engine;
12.1.2 如何指定和修改存儲引擎
(1) 通過參數設置默認引擎
(2) 建表的時候進行設置
(3) alter table t1 engine=innodb;
12.2. 表空間
12.2.1 共享表空間
innodb_data_file_path
一般是在初始化數據之前就設置好
例子:
innodb_data_file_path=ibdata1:512M:ibdata2:512M:autoextend
12.2.2 獨立表空間
show variables like 'innodb_file_per_table';
12.3. 緩沖區池
12.3.1 查詢
select @@innodb_buffer_pool_size;
show engine innodb status\G
innodb_buffer_pool_size
一般建議最多是物理內存的 75-80%
12.4. innodb_flush_log_at_trx_commit (雙一標準之一)
12.4.1 作用
主要控制了innodb將log buffer中的數據寫入日志文件并flush磁盤的時間點,取值分別為0、1、2三個。
12.4.2 查詢
select @@innodb_flush_log_at_trx_commit;
12.4.3 參數說明:
1,每次事物的提交都會引起日志文件寫入、flush磁盤的操作,確保了事務的ACID;flush 到操作系統的文件系統緩存 fsync到物理磁盤.
0,表示當事務提交時,不做日志寫入操作,而是每秒鐘將log buffer中的數據寫入文件系統緩存并且秒fsync磁盤一次;
2,每次事務提交引起寫入文件系統緩存,但每秒鐘完成一次fsync磁盤操作。
--------
The default setting of 1 is required for full ACID compliance. Logs are written and flushed to disk at each transaction commit.
With a setting of 0, logs are written and flushed to disk once per second. Transactions for which logs have not been flushed can be lost in a crash.
With a setting of 2, logs are written after each transaction commit and flushed to disk once per second. Transactions for which logs have not been flushed can be lost in a crash.
-------
12.5. Innodb_flush_method=(O_DIRECT, fdatasync)
image
https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_method
12.5.1 作用
控制的是,log buffer 和data buffer,刷寫磁盤的時候是否經過文件系統緩存
12.5.2 查看
show variables like '%innodb_flush%';
12.5.3 參數值說明
O_DIRECT :數據緩沖區寫磁盤,不走OS buffer
fsync :日志和數據緩沖區寫磁盤,都走OS buffer
O_DSYNC :日志緩沖區寫磁盤,不走 OS buffer
12.5.4 使用建議
最高安全模式
innodb_flush_log_at_trx_commit=1
Innodb_flush_method=O_DIRECT
最高性能:
innodb_flush_log_at_trx_commit=0
Innodb_flush_method=fsync
12.6. redo日志有關的參數
innodb_log_buffer_size=16777216
innodb_log_file_size=50331648
innodb_log_files_in_group = 3
13.擴展(自己擴展,建議是官方文檔。)
RR模式(對索引進行刪除時):
GAP: 間隙鎖
next-lock: 下一鍵鎖定
例子:
id(有索引)
1 2 3 4 5 6
GAP:
在對3這個值做變更時,會產生兩種鎖,一種是本行的行級鎖,另一種會在2和4索引鍵上進行枷鎖
next-lock:
對第六行變更時,一種是本行的行級鎖,在索引末尾鍵進行加鎖,6以后的值在這時是不能被插入的。
總之:
GAP、next lock都是為了保證RR模式下,不會出現幻讀,降低隔離級別或取消索引,這兩種鎖都不會產生。
IX IS X S是什么?