一,連接層功能:
1,TCP/IP或者Socket的鏈接方式
2,驗證用戶名密碼功能
3,連接線程(客服):接收SQL語句,返回執行結果
二,SQL層
1,語法檢查模塊,檢查上層發過來的SQL語句,進行語法檢查
2,權限檢查模塊,檢測當前登錄用戶是否有權限操作數據庫對象
3,語義檢查模塊,識別語句種類
5,優化器,基於執行代價(系統資源的消耗作為維度(cpu、內存、IO),管理員可以通過間接的方法,干擾優化器的選擇)
6,執行器,按照優化器選擇的“最優”的執行計划,執行SQL語句。得出結論:某某磁盤的某某位置,發送給存儲引擎層。
7,提供查詢緩存:有局限性。一般會用Redis產品來替代
8,記錄查詢日志
SQL語句的分類:
DDL:數據定義語言
DCL:數據控制語言
DML:數據操作語言
DQL:數據查詢語言
三,存儲引擎層:
和“磁盤”(文件系統)打交道的層次
根據SQL層執行的結果,去磁盤上找到對應的數據。結構化成表的模式,返回給用戶。
MySql邏輯結構組成:
一,庫(庫名字,庫屬性)
二,庫(庫名字,列(列名字,列屬性)表屬性,表數據)
MySQL索引
MySQL索引分類
存儲引擎管理
一,索引管理以及原理
1,索引的種類
B樹(B+tree B*tree b-tree)
B-tree:針對某個明確值的查詢
查找順序:根節點——>枝節點——>葉子節點
B+tree:針對明確的范圍的查詢
缺點:無法同時包含回表查詢以及其它列的查詢
輔助索引:(B TREE)
alter table t1 add index idx_num(telnum);
怎么生成的:
根據創建索引時,指定的列的值,進行排序后,存儲在葉子節點中
優點:
1,優化了查詢,減少CPU 內存 IO消耗
2,減少了文件排序
覆蓋索引:(聯合索引)
通過一個索引列把需要查詢的列都添加到索引樹里面去
直接在索引樹里面直接有,減少或盡量避免回表查詢操作
優點:減少回表查詢的操作的幾率
聚集索引 :
同一等級情況下效率最高
大部分情況下輔助索引和聚集索引結合使用
輔助索引:where 條件 有id列的時候,比如id=28
隨機讀 順序讀
建表時,如果有主鍵列,自動生成聚集索引
沒有主鍵列,會去找unique列
優點:
減少回表查詢
將隨機IO轉換成順序IO
加強了緩存的應用,查詢效率提升
2,R樹
3,hash索引
4,全文索引
2,B樹索引的類型
1,聚簇索引(cluster index):一般是基於主鍵的
2,輔助索引(普通輔助索引:回表查詢;覆蓋索引;不回表查詢;唯一性索引)
3,唯一索引
3,索引管理
索引的作用:在mysql數據庫中,索引是用來優化查詢的
除緩存之外,數據的查詢有兩種方式:
1,全表掃描
2,索引掃描
優化器索引掃描要優於全表掃描
索引管理:
索引就是一張表
創建索引的語句:
為某張表基於某列建索引:alter table 表名 add index idx_name(列名)
MySQL不走索引的情況(開發規范)
重點關注:
1,沒有查詢條件,或者查詢條件沒有建立索引
select * from tab ;全表掃描
select * from tab where 1=1;
在業務數據庫中,特別是數據庫量比較大的表,是沒有全表掃描這種需求的,當然我們也應該避免這種情況
1,對用戶查看是非常痛苦的
2,對服務器來說是毀滅性的
(1) select * from tab
SQL改寫成以下語句:
select * from tab order by price limit 10 ; 需要在price列上建立索引
(2) select * from tab where name=‘zhangsan'; name列沒有索引
2,查詢結果集是原表中的大部分數據,應該是25%以上。
查詢的結果集,超過了總數行數25%,優化器就會覺得沒有必要走索引了。
假如:tab表 id,name id:1-100w,id列有索引
select * from tab where id>50000;
3,索引本身失效,統計數據不真實
大量的操作插入刪除操作,對表內容變化比較頻繁的情況下,有可能會出現索引失效的情況。
4,查詢條件使用函數在索引上,或者列進行計算,運算包括(+,-,*,/,!等)
算數運算
函數運算
子查詢
例子:
錯誤的例子:select * from test where id-1=9;
正確的例子:select * from test where id=10;
5,隱式轉換導致索引失效,這一點應當引起重視,也是開發中經常遇到會犯的錯誤!
6,<>,not in 不走索引
單獨的 >,<,in有可能走,也有可能不走,和結果集有關,盡量結合業務添加limit
or或 in 盡量改成 union
7,like "%_"百分號在前面不走索引
%link%類的搜索需求,可以使用elasticsearch 專門做搜索服務的數據庫產品
8,單獨引用聯合索引里非第一位置的索引列,作為條件查詢時不走索引。
例子:
復合索引
DROP TABLE t1
CREATE TABLE t1(id INT,NAME VARCHAR(20),age INT , sex ENUM('m','f'),money INT );
ALTER TABLE t1 ADD INDEX t1_idx(money,age,sex);
DESC t1
SHOW INDEX FROM t1
走索引的情況測試:
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 AND sex='m';
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30 ;
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND sex='m'; ----->部分走索引
不走索引的情況;
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30;
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30 AND sex='m';
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE sex='m';
MySQL存儲引擎
查看存儲引擎:
show engines;
show create table world.city;
插件式,即插即用存儲引擎,是在表級別設定的。
mysql5.5以后默認的是InnoDB
InnoDB與MyISAM存儲引擎的區別:
MVCC: innoDB支持,MyISAM不支持
鎖(行級別): innodb支持,myisam表級別
外鍵: innodb支持,myisam不支持
事務: innodb支持,myisam不支持
熱備份: innodb支持,myisam溫備份
CSR(故障斷電自動恢復)innodb支持,myisam不支持
InnoDB
MVCC
鎖定粒度
外鍵
MyISAM
MEMORY(memory)
ARCHIVE(archive)
也可以使用第三方的存儲引擎
TokuDB ------>zabbix
myrocks
InnoDB存儲引擎的物理存儲方式:
表空間(TBS)的管理模式:
來自於Oracle
表存儲到磁盤上是以表空間的管理模式來存儲
共享表空間:類似於Oracle管理模式
獨立表空間:每個表單獨使用表空間存儲
5.5默認:共享表空間
5.6以后:默認管理模式獨立表空間存儲,共享表空間也存在
表空間存儲數據的分類:
共享表空間:ibdata1
存了什么?
系統數據
undo日志
磁盤臨時表
獨立表空間:
t1.ibd ----->t1表的數據和索引
t1.frm ------>t1表的列相關信息
表空間操作:
共享表空間:
我們建議,在數據庫初始化的時候就配置好
一般建議2-3個,512M
/etc/my.cnf
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
mysql_install_db
獨立表空間:一個表一個ibd文件,存儲表數據和索引
show variables like 'innodb_file_per_table';
事務
InnoDB存儲引擎核心特性:
1,事務
簡單來說:
事務會把業務流程中的多條語句放到一個執行(工作)單元里面,保證這多條語句要么全部成功,要么全部失敗。
保證交易類業務完整性
官方:
一組數據操作執行步驟,這些步驟被視為一個工作單元
用於對多個語句進行分組
可以在多個客戶機並發訪問同一個表中的數據時使用
所有步驟都成功或者都失敗
如果所有步驟正常,則執行
如果步驟出現錯誤或不完整,則取消
2,事務是保證數據的ACID特性
Atomic(原子性)
所有語句作為一個執行單元全部成功執行或全部取消執行。
保證了穩定性。
Consistent(一致性)
如果數據庫在事務開始時處於一致狀態,則在執行該VT事務期間將保留一致狀態。
Isolated(隔離性)
事物之間不相互影響
Durable(持久性)
事務成功完成后,所做的所有更改都會准確地記錄在VT數據庫中,所做的更改不會丟,即使數據庫宕機
3,標准的事務控制語句:
事務常見生命周期:
周期一:
begin; 開啟事務
DML
DML
commit; 結束事務
周期二: 開啟事務
begin;
DML
DML
rollback; 撤銷事務
常識:MySQL5.5版本以后不需要自己手動來寫begin語句,寫DML語句時自動生成
注意:正常的遵循事務的ACID特性的事務,對於autocommit=1,需要手動關閉,默認等於1處於開啟狀態,自動提交功能
臨時關閉,臨時生效
set autocommit=0;
set global autocommit=0;
永久關閉
在my.cnf設置
autocommit=0;
4,隱式提交
用於隱式提交的SQL語句:
START TRANSACTION
SET AUTOCOMMIT = 1
導致提交的非事務語句:
DDL語句: ALTER、CREATE、DROP
DCL語句: GRANT、REVOKE、SET PASSWORD
鎖定語句 LOCK TABLES 和 UNLOCK TABLES
導致隱式提交的語句:
TRUNCATE TABLES
LOAD DATA INFILE
SELECT FOR UPDATE
隱式提交的幾種情況:
情況一:
begin
DML1
DML2
begin
情況二:
begin
DDL
DDL
情況三:
begin
DCL
DDL
5,innodb存儲引擎物理存儲層
表空間(t1.ibd)----->
段 一個表就是一個段(除了分區表)
區 連續的多個頁
頁 page(16KB)
每個數據頁作為一個存儲單元
6,存儲引擎日志 -----物理層面
Redo:重做日志
Redo記錄的是內存數據頁的變化過程
Rudo:事務日志的一種,在事務ACID過程中,實現的是“D”持久化的作用,AC特性也和它有關
Rudo:CSR過程中實現前滾
存儲位置:數據路徑下存放,默認兩個日志,默認標准大小50M,輪詢覆蓋形式使用文件日志
通過這兩個參數控制,可以按照自己需求設定文件大小
innodb_log_file_size=50331648
innodb_log_files_in_group=2
ib_logfile0
ib_logfile1
查看標准大小:
mysql -uroot -p
show varables like '%log%';
LSN:日志序列號(也就是數據變化的版本號)
哪些地方會有日志序列版本號:
data page 磁盤數據頁
logfile
data buffer
redo log buffer 日志的內存區域
數據庫要求:啟動時,必須保證data page 與logfile 中LSN號一致才能正常打開數據庫,否則就會進行數據恢復
undo:回滾日志
undo記錄了什么?
undo:記錄數據頁變化之前的數據狀態以及TXID(數據頁的id)
undo:事務日志的一種,在事務ACID過程中,實現的是“ACI”原子性,一致性的作用
undo作用:
1,rollback
2,CSR過程中實現回滾
事務沒有進行commit提交的情況下:
先Rudo前滾
再undo回滾
四種隔離級別:
READ UNCOMMITTED 臟讀
允許事務查看其他事務所進行的未提交更改
READ COMMITTED 幻讀
允許事務查看其他事務所進行已提交更改
有可能出現幻讀的現象,企業中堅決避免
REPEATABLE READ******可重復讀,防止幻讀現象
確保每個事務的SELECT 輸出一致
InnoDB默認級別
SERIALIZABLE
將一個事務的結果與其他事務完全隔離
會阻塞其他事務的所有操作,只保證當前事務正常運行
Innodb事務鎖機制
鎖:顧名思義就是鎖定的意思
種類:行級鎖與表級鎖
作用:在事務ACID過程中,鎖和隔離級別一起來實現隔離性的作用
鎖的粒度:
MyIasm:低並發鎖 ——表級鎖
InooDB:高並發鎖 ——行級鎖
事務出現沖突,出現鎖爭用:也名沖突事務
沖突事務例子:
例子:
1,事務1想要把a=1修改成a=2,,而這時事務2想要把a=1修改成a=3,這種情況下
2,兩個事務同時更新一條數據
InnoDB體系結構擴展:
1,內存結構
2,線程結構
3,事務工作更詳細流程
4,InnoDB存儲引擎在安全和性能上的體現
5,Double Write
6,Db crash恢復流程
日志管理
1,錯誤日志
a,作用:
記錄啟動\關閉\日常運行過程中,狀態信息,警告,錯誤
b,配置:
默認就是開啟狀態:/數據路徑下/hostname.err
手動設定:
vim /etc/my.cnf
log_error=/var/log/mysql.log
重啟生效:
show variables like 'log_error';
c,查看日志內容
主要關注[error],看上下文
2,二進制日志:binlog
1,作用:
1,備份恢復
2,主從環境
2,binlog配置(5.7必須加server_id)
vim /etc/my.cnf
server_id=6
log_bin=/data/mysql/mysql-bin
binlog_format=row
重啟生效
注意:=/data/mysql 必須事先創建好,必須對mysql有權限
3,binlog記錄了什么?
記錄mysql數據庫所有變更類的SQL語句
DDL,DCL,記錄方式:SQL語句直接記錄
DML記錄三種方式: 只記錄已經commit的DML
row 5.7默認
特點:記錄數據行的變化,可讀性不高,日志量較大,記錄數據精確
statment 5.6默認
特點:可讀性較高,日志量較少,但是以后恢復數據可能會是錯誤數據
mixed
4, event二進制的最小記錄單元
對於DDL,DCL,一個事務就是一個event
對於DML,一個事務就被分為了四個event:
begin;
DML1
DML2
commit;
event組成:開始位置 + 事件內容 +結束位置
5,日志文件查看
log_bin參數設置的路徑,可以找到二進制日志
show binary logs;
show master status;
6,日志內容查看
show master status;
show master status in 'mysql-bin.000002';
錄入數據,看事件信息:
create database testdb;
create table t1(id int);
insert into t1 values(1);
commit;
show binlog events in 'mysql-bin.000002;
查看binlog文件詳細內容:
mysqlbinlog /data/mysql/mysql-bin.000002;
mysqlbinlog --base64-output=decode-rows -vvvv /data/mysql/mysql-bin.000002;
mysqlbinlog -d testdb /data/mysql/mysql-bin.000002;
7,日志截取
mysqlbinlog --start-position --stop-position
恢復:
set sql_log_bin=0;
source /tmp/binlog.sql
set sql_log_bin=1;
8,二進制日志恢復數據
數據庫的故障(損壞),原因:
1,軟件損壞了
2,數據損壞了
3,硬件損壞,數據文件,數據頁
4,邏輯損壞
5,SQL導致的誤刪除,誤修改
只要擁有全量的binlog,就可以把數據庫恢復到任意的時間點
3,慢日志(slow_log)
1,作用:
記錄慢SQL語句的日志
2,開啟慢日志,默認沒開啟
配置:
開啟慢日志:
slow_query_log=1
文件位置以及名字:
slow_query_log_file=/data/mysql/slow.log
設定慢查詢時間:
long_query_time=0.01
沒走索引的語句也記錄:
log_queries_not_using_indexes
服務器端配置,幾條語句加進去就可以了
vim /etc/my.cnf
slow_query_log=1
slow_query_log_file=/data/mysql/slow.log
long_query_time=0.01
log_queries_not_using_indexes
/etc/init.d/mysql restart
3,分析慢日志
mysqldumpslow
mysqldumpslow -s c -t 10 /data/mysql/slow.log
備份恢復
1,備份類型
熱備:在數據庫正常業務是,備份數據,並且能夠一致性恢復
冷備:關閉數據庫業務,數據庫沒有任何變更的情況下,進行備份數據
溫備:鎖表備份,只能查詢不能修改
2,備份方式,工具
邏輯備份:基於SQL語句進行備份:mysqldump,mysqlbinlog
物理備份:基於磁盤文件備份:cp,xtrabackup(XBK)
3,備份策略
1,全備:全庫備份
2,增量:備份變化的數據
備份周期:多久全備,多久增量
4,恢復備份
5,故障恢復
6,遷移
主從復制
前提:
1,准備2個以上的mysql實例,有主有從
2,每台實例server_id不同
3,主庫方面創建專用的復制用戶
4,主庫必須開啟二進制日志
5,從庫需要初始化數據,保證和主庫數據在一個時間點上數據一致
1,搭建主從復制
1,准備多個mysql實例(3307(master),3308(slave1),3309(slave2))
具體環境配置文檔(待QAQ續)
2,主庫必須授權一個專門用作主從復制的用戶
在創建一個復制用戶
mysql -S /data/3307/mysql.sock
grant replication slave on *.* ro repl@'10.0.0.%' indextified by '123';
3,全備主庫數據,恢復到從庫
mysqldump -S /data/3307/mysql.sock -A -R --triggers --master-data=2 --single-transaction >/tmp/full.sql
mysql -S /data/3308mysql.sock
set sql_log_bin=0;
source /tmp/full.sql
4,開啟主從復制
mysql -S /data/3308/mysql.sock
命令兩條:
忘記了請記得讓我們的help小姐姐來幫你QAQ: help change master to
CHANGE MASTER TO
MASTER_HOST='10.0.0.51', 填寫主庫ip
MASTER_USER='repl', 填寫主庫復制用戶名
MASTER_PASSEORD='123', 填寫主庫復制用戶密碼
MASTER_[PORT=3307, 填寫主庫端口號
MASTER_LOG_FILE='mysql-bin.000001', 填寫需要復制二進制日志名
MASTER_LOG_POS=325, 填寫需要復制的二進制日志復制的起點
MASTER_CONNECT_RETRY=10; 重連重試次數
啟動復制線程:
start slave;
查看主從狀態:
show slave status \G
當你看到這兩條命令為Yes,那么恭喜你成功了!
Slave_IO_Running:Yes
Slave_SQL_Running:Yes
2,主從復制存在原因
1,輔助備份
解決物理損壞
2,演變高可用架構
在主庫發生故障時,自動進行故障轉移,對於應用透明
3,演變高性能架構
讀寫分離
分布式
3,延時從庫
4,過濾復制
控制過濾
從主庫方面控制:復制指定的庫到從庫,對主庫業務數據進行垂直拆分
從從庫方面控制:只接收主庫某個庫復制過來的內容
1,從主庫方面控制
show master status;
Binlog_Do_DB=白名單,在此參數中的庫,記錄二進制日志
Binlog_Ignore_DB=黑名單,在此參數中的庫,不記錄二進制日志
2,從庫方面控制
Replicate_Do_DB: 白名單,在此參數中的庫,復制
Replicate_Ignore_DB: 黑名單,在此參數中的庫,不復制
Replicate_Do_Table: 白名單,在此參數中的表,復制
Replicate_Ignore_Table: 黑名單,在此參數中的表,不復制
模糊的表名字
Replicate_Wild_Do_Table: wolrd.t*
Replicate_Wild_Ignore_Table:
寫法:
vim /data/3308/my.cnf
replicate_do_db=world
replicate_do_db=oldboy
5,主從復制之架構擴展GTID復制
1,環境准備
環境准備Centos拿db01克隆兩台虛擬機
干掉原來數據庫,並清理/application/mysql/data下所有數據,保證環境一致,干凈
pkill mysqld
rm -rf /application/mysql/data*
1,備份三台機器/etc/my.cnf文件
mv/etc/my.cnf /tmp
2,書寫配置文件:
master:10.0.0.51
vim/etc/my.cnf
[mysqld]
dasedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
skip-name-resolve
server-id=51
gtid-more=on
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock
slave1:10.0.0.52
vim /etc/my.cnf
[mysqld]
dasedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
skip-name-resolve
server-id=52
gtid-more=on
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock
slave2:10.0.0.53
vim /etc/my.cnf
[mysqld]
dasedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
skip-name-resolve
server-id=53
gtid-more=on
enforce-gtid-consistency=true
log-slave-updates=1
[client]
socket=/tmp/mysql.sock
3,重新初始化三台機器數據
/application/mysql/scripts/mysql_install_db --basedir=/application/mysql/ --datadir=/application/mysql/data --user=mysql
4,分別啟動三台數據庫服務器
etc/init.d/mysqld start
2,GTID介紹
GTID是對於一個已提交事務的編號,並且是一個全局唯一的編號
官方定義:
GTID=source_id :transaction_id
7E11FA47-31CA-19E1-9E56-C43AA21293967:29
1,什么是sever_uuid和Server-id區別?
source_id 也叫uuid 默認是在第一次啟動數據庫時,自動生成的
/application/mysql/data/auto.cnf
手動刪除掉此文件,重啟數據庫,可以生成新的
2,重要參數
gtid-mode=on --啟動gtid類型,否則就是普通的復制架構
erforce-gtid-consistency=true --強制GTID的一致性
log-slave-updates=1 --slave更新是否記入日志
3,基於GTID的復制構建
master:51
slave:52,53
51:
grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
52\53:
source bak.sql
change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1;
start slave;
change master to msater_host ='10.0.0.51',master_user='repl',master_password='123',MASTER_AUTO_POSITION=1;
高可用以及讀寫分離
分布式系統