MySQL自學筆記 MySQL 基礎 SQL SQL通用語法 SQL分類 DDL數據操作 數據類型 DML數據操作 DQL數據操作 DCL數據控制 函數 約束 多表查詢 事務 進階 存儲引擎 **索引**(重點) SQL優化 視圖 存儲過程 鎖 InnoDB引擎 事務原理 MVCC
MySQL
課程連接
數據庫:存儲數據的倉庫,數據是有組織的進行存儲(DataBase, DB)
數據庫管理系統:操縱和管理數據庫的大型軟件(DataBase Management System, DBMS)
SQL : 操作關系型數據庫 的編程語言,定義了一套操作關系型數據庫的統一標準(Structured Query Language, SQL)
基礎
關系型數據庫(RDBMS)
概念:建立在關系模型基礎上,有多張相互連接的二維表 組成的數據庫 使用表存儲數據,格式統一,便于維護 使用SQL語言操作,標準統一,使用方便 MySQL啟動
net
start mysql80net stop mysql80
* MySQL客戶端連接
mysql
[ - h
127.0 .0 .1 ] [ - p
3306 ] - u root
- p
SQL
SQL通用語法
SQL語句可以單行或多行書寫,以分號結尾 SQL語句可以使用空格/縮進來增強語句的可讀性 MySQL數據庫的SQL語句不區分大小寫,關鍵字建議使用大寫 注釋
SQL分類
DDL (Data Definition Language) 數據定義語言,用來定義數據庫對象(數據庫、表、字段等) DML(Data Manipulation Language) 數據操作語言,用來對數據庫表中的數據進行增刪改查 DQL(Data Query Language) 數據查詢語言,用來查詢數據庫中標的記錄 DCL(Data Control Language) 數據控制語言,用來創建數據庫用戶、控制數據庫的訪問權限
DDL數據操作
SHOW DATABASES ; SELECT DATABASE ( ) ;
CREATE DATABASE [ IF NOT EXISTS ] 數據庫名
[ DEFAULT CHARSET 字符集(UTF8MB4)
] [ COLLATE 排序規則
] ;
DROP DATABASE [ IF EXISTS ] 數據庫名
;
USE 數據庫名
;
show tables ; desc 表名
; show create table 表名
;
create table 表名
( 字段
1 字段
1 類型
[ comment 字段
1 注釋
] , 字段
2 字段
2 類型
[ comment 字段
2 注釋
] , 字段
3 字段
3 類型
[ comment 字段
3 注釋
] , . . . . . . 字段n 字段n類型
[ comment 字段n注釋
] ) [ comment 表注釋
] ;
alter table 表名
add 字段名 類型
( 長度
) [ comment 注釋
] [ 約束
] ; alter table 表名
modify 字段名 新數據類型
( 長度
) ; alter table 表名 change 舊字段名 新字段名 類型
( 長度
) [ comment 注釋
] [ 約束
] ; alter table 表名
drop 字段名
; alter table 表名
rename to 新表名
; drop table [ if exists ] 表名
; truncate table 表名
;
數據類型
DML數據操作
INSERT INTO 表名
( 字段名
1 ,字段名
2 ,
. . . ) VALUES ( 值
1 ,值
2 , . . . ) ; INSERT INTO 表名
VALUES ( 值
1 ,值
2 , . . . ) ; INSERT INTO 表名
( 字段名
1 ,字段名
2 ,
. . . ) VALUES ( 值
1 ,值
2 , . . ) , ( 值
1 ,值
2 , . . ) , ( 值
1 ,值
2 , . . ) ; INSERT INTO 表名
VALUES ( 值
1 ,值
2 , . . . ) , ( 值
1 ,值
2 , . . . ) , ( 值
1 ,值
2 , . . . ) ;
UPDATE 表名
SET 字段名
1 = 值
1 , 字段名
2 = 值
2 , . . . [ WHERE 條件
] ; DELETE FROM 表名
[ WHERE 條件
] ;
DQL數據操作
SELECT 字段
1 , 字段
2. . . FROM 表名
; SELECT * FROM 表名
; SELECT 字段
1 [ AS 別名
1 ] , 字段
2 [ AS 別名
2 ] . . . FROM 表名
; SELECT DISTINCT 字段列表
FROM 表名
;
SELECT 字段列表
FROM 表名
WHERE 條件列表
; BETWEEN [ MAX
] AND [ MIN
] ; VALUE1
IN ( VALUE2
, VALUE3
, ) ; IS NULL 和
IS NOT NULL ; LIKE '_ _' ; LIKE '%X' ;
count max min avg sum
SELECT 聚合函數
( 字段列表
) FROM 表名
;
SELECT 字段列表
FROM 表名
[ WHERE 條件
] GROUP BY 分組字段名
[ HAVING 分組后過濾條件
] ;
SELECT 字段列表
FROM 表名
ORDER BY 字段
1 排序方式
1 , 字段
2 排序方式
2 ; ASC 升序 默認值
DESC 降序
SELECT 字段列表
FROM 表名
LIMIT 起始索引
, 查詢記錄數
;
SELECT - > FROM - > WHERE - > GROUP BY - > HAVING - > ORDER BY - > LIMIT FROM - > WHERE - > GROUP BY - > HAVING - > SELECT - > ORDER BY - > LIMIT
DCL數據控制
USE mysql
; SELECT * FROM user ; CREATE USER '用戶名' @'主機名' IDENTIFIED
BY '密碼' ; ALTER USER '用戶名' @'主機名' IDENTIFIED
WITH mysql_native_password
BY '新密碼' ; DROP USER '用戶名' @'主機名' ;
SHOW GRANTS
FOR '用戶名' @'主機名' ; GRANT 權限列表
ON 數據庫名
. 表名
TO '用戶名' @'主機名' ; REVOKE 權限列表
ON 數據庫名。表名
FROM '用戶名' @'主機名' ;
函數
SELECT 函數
( 參數
) ;
約束
AUTO_INCREMENT 使約束字段遞增
CREATE TABLE 表名
( 字段名 數據類型
, . . . [ CONSTRAINT ] [ 外鍵名稱
] FOREIGN KEY ( 外鍵字段名
) REFERENCES 主表
( 主表列名
) ) ; 或
ALTER TABLE 表名
ADD CONSTRAINT [ 外鍵名稱
] FOREIGN KEY ( 外鍵字段名
) REFERENCES 主表
( 主表列名
) ; ALTER TABLE 表名
DROP FOREIGN KEY 外鍵名稱
;
ALTER TABLE 表名
ADD CONSTRAINT [ 外鍵名稱
] FOREIGN KEY ( 外鍵字段名
) REFERENCES 主表
( 主表列名
) ON UPDATE 行為
ON DELETE 行為
;
多表查詢
實現:在多的一方建立外鍵,指向一的一方的主鍵實現:建立第三張中間表,中間表至少包含兩個外鍵,分別關聯兩方主鍵實現:在任意一方加入外鍵,關聯另外一方的主鍵,并且設置外鍵為唯一的
( UNIQUE )
內連接:相當于查詢A、B交集部分數據
SELECT DISTINCT 字段列表
FROM 表
1 ,表
2 WHERE 連接條件
. . . ; DISTINCT 對查詢結果去重
SELECT 字段列表
FROM 表
1 [ INNER ] JOIN 表
2 ON 連接條件
. . . ; 外連接:左外連接:查詢左表所有數據,以及兩張表交集部分數據
SELECT 字段列表
FROM 表
1 LEFT [ INNER ] JOIN 表
2 ON 連接條件
. . . [ WHERE 條件
] ; 右外連接:查詢右表所有數據,以及兩張表交集部分數據
SELECT 字段列表
FROM 表
1 RIGHT [ INNER ] JOIN 表
2 ON 連接條件
. . . [ WHERE 條件
] ; 自連接:當前表與自身的連接查詢,自連接必須使用表別名對于
UNION 查詢,是把多次查詢的結果合并起來,形成一個新的查詢結果集
SELECT 字段列表
FROM 表A
. . . UNION [ ALL ] SELECT 字段列表
FROM 表B
. . . ; 注意:對于聯合查詢的多張表的列數必須保持一致,字段類型也需要保持一致
UNION ALL 會將全部的數據直接合并在一起,
UNION 會對合并之后的數據去重
SQL 語句中嵌套
SELECT 語句,稱為嵌套查詢,又稱為子查詢
SELECT * FROM t1
WHERE column1
= ( SELECT column1
FROM t2
) ; 子查詢外部的語句可以是
INSERT / UPDATE / SELECT / DELETE 的任何一個根據子查詢結果不同,分為:標量子查詢(子查詢結果為單個值)列子查詢(子查詢結果為一列)行子查詢(子查詢結果為一行)表子查詢(子查詢結果為多行多列)根據子查詢位置,分為:
WHERE 之后、
FROM 之后、
SELECT 之后。
事務
SELECT @
@autoaommit ; SET @
@autocommit = 0 ; COMMIT ; ROLLBACK ; START TRANSACTION 或
BEGIN COMMIT ; ROLLBACK ;
原子性
( Atomicity
) :事務是不可分割的最小操作單元,要么全部成功,要么全部失敗一致性
( Consistency
) :事務完成時,必須使所有的數據保持一致狀態隔離性
( Isolation ) :數據庫系統提供的隔離機制,保證事務在不受外部并發操作影響的獨立環境下運行持久性
( Durability
) :事務一旦提交或回滾,他對數據庫中的數據的改變是永久的
臟讀:一個事務讀取到另外一個事務還沒有提交的數據不可重復讀:一個事務先后讀取同一條記錄,但兩次讀取的數據不同,成之為不可重復讀幻讀:一個事務按照條件查詢數據時,沒有對應的數據行,但是在插入數據時,又發現這行數據已經存在,好像出現了’幻影‘
上表從上到下隔離級別越來越高,性能越來越差,安全性越來越高
SELECT @
@TRANSACTION_ISOLATION ; SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {隔離級別}
進階
存儲引擎
--連接層:最上層是一些客戶端和連接服務,主要完成一些類似于連接處理、授權認證、及相關的安全方案。服務器也會為安全接入的每個客戶端驗證它所具有的操作權限--服務層:第二層架構主要完成大多數的核心服務功能,如SQL接口,并完成緩存的查詢,SQL的分析和優化,部分內置函數的執行。所有跨存儲引擎的功能也在這一層實現,如過程、函數等--引擎層:存儲引擎真正的負責了MySQL中數據的存儲和提取,服務器通過API和存儲引擎進行通信。不同的存儲引擎具有不同的功能,這樣我們可以根據自己的需要,來選取合適的存儲引擎--存儲層:主要將數據存儲在文件系統之上,并完善與存儲引擎的交互
CREATE TABLE 表名
( ) ENGINE = 存儲引擎
[ COMMENT 表注釋
] ; SHOW ENGINE ;
innoDB 是一種兼顧高可靠性和高性能的通用存儲引擎,在MySQL5
. 5 之后,是默認存儲引擎DML操作遵循ACID模型,支持事務行級鎖,提高并發訪問性能支持外鍵
FOREIGN KEY 約束,保證數據的完整性和正確性xxx
. idb: xxx表示表名,
innoDB 引擎的每張表都會對應這樣一個表空間文件,存儲該表的表結構(frm sdi)、數據和索引。參數:innodb_file_per_table
#MySAM早期的默認存儲引擎#特點不支持事務,不支持外鍵支持表鎖,不支持行鎖訪問速度快#文件xxx.sdi --存儲表結構信息xxx.MYD --存儲數據xxx.MYI --存儲索引#Memory其數據表存儲在內存中,由于受到硬件問題、或斷點問題的影響,只能將這些表作為臨時表或緩存使用#特點內存存放hash索引#文件xxx.sdi
索引 (重點)
MySQL的索引是在存儲引擎層實現的,不同的存儲引擎有不同的結構,主要包含一下幾種:
二叉樹缺點:順序插入時,會形成一個鏈表,查詢性能大大降低。大數據量情況下,層級較深,檢索速度慢
紅黑樹:大數據量情況下,層級較深,檢索速度慢
B-Tree:以一顆最大度數(max-degree)為5階的B-Tree為例(每個節點最多存儲4個key,5個指針),樹的度數指的是一個節點的子節點個數
? 與B-Tree區別:所有的數據都會出現在葉子節點;葉子節點形成一個單向列表。
哈希索引就是采用一定的hash算法,將鍵值換算成新的hash值,映射到對應的槽位上,然后存儲在hash 表中。如果兩個(或多個)鍵值,映射到一個相同的槽位上,他們就產生了hash沖突(hash碰撞),可以通過鏈表解決。
特點:hash索引只能用于對等比較(=、in),不支持范圍查詢(between、> 、< ...)無法利用索引完成排序操作;查詢效率高,通常只需要一次檢索就可以了,效率通常高于B+Tree索引
? 在MySQL中,支持hash索引的值Memory引擎,而innoDB中具有自適應hash功能,hash索引是存儲引擎根據B+Tree索引在指定條件下自動構建的。
為什么InnoDB存儲引擎選擇使用B+Tree索引結構?
1、相對于二叉樹,層級更少,搜索效率高
2、對于B-Tree,無論是葉子節點還是非葉子節點,都會保存數據,這樣導致一頁存儲的鍵值減小,指針跟著減小,同樣保存大量的數據,只能增加樹的高度,導致性能降低
3、相對于Hash索引,B+Tree支持范圍匹配和排序操作
索引分類
在InnoDB引擎中,根據索引的存儲形式,又可以分為一下兩種:
回表查詢:先走二級索引找到對應的主鍵值,再根據主鍵值走聚集索引找到對應的行數據
CREATE [ UNIQUE | FULLTEXT
] INDEX index_name
ON table_name
( index_col_name
, . . . ) ; SHOW INDEX FROM table_name
; DROP INDEX index_name
ON table_name
;
MySQL客戶端連接成功后,通過下面指令可以提供服務器狀態信息。查看當前數據庫的
INSERT \
UPDATE \
DELETE \
SELECT 的訪問頻次:
SHOW [ SESSION | GLOBAL ] STATUS LIKE 'Com_____' ;
慢查詢日志記錄了所有執行時間超過指定參數(long_query_time 默認
10 秒)的所有
SQL 語句的日志。MySQL的慢查詢日志默認沒有開啟,需要在MySQL的配置文件(
/ etc
/ mysql
/ mysql
. conf
. d
/ mysqld
. cnf)中配置如下信息,可以使用 vi
/ vim修改:slow_query_log
= 1 ; long_query_time
= 2 ; slow_query_log_file
= / var
/ log
/ mysql
/ mysql
- slow
. log
SHOW VARIABLES
LIKE 'slow_query_log' ; tail
- f mysql
- slow
. log重啟MySQL systemctl restart mysql關閉MySQL systemctl stop mysql
show profiles能夠在做
SQL 優化時幫助我們了解時間都耗費到哪里去了。通過have_profiling參數,能夠看到當前MySQL是否支持profile操作:
SELECT @
@have_profiling ; SELECT @
@profiling ; SET profiling
= 1 ; SHOW profiles
; show profile
for query query_id
; show profile cpu
for query query_id
;
EXPLAIN 或者
DESC 命令獲取MySQL如何執行
SELECT 語句的信息,包括在
SELECT 語句執行過程中表如何連接和連接的順序。語法:
EXPLAIN SELECT 字段列表
FROM 表名
WHERE 條件
;
id:
SELECT 查詢的序列號,表示查詢中執行
SELECT 子句或者是操作表的順序(id相同,執行順序從上到下;id不同,值越大,越優先執行);select_type: 表示
SELECT 的類型,常見的取值有
SIMPLE (簡單表,即不使用表連接或者子查詢)、
PRIMARY (主查詢,即外層查詢)、
UNION (
UNION 中第二個或者后面的查詢語句)、SUBQUERY
( SELECT / WHERE 之后包含了子查詢
) 等;
type : 表示連接類型,性能由好到差的連接類型為
NULL 、system 、const 、eq_ref、ref、range、
index 、
all ; possible_key: 顯示可能應用在這張表上的索引,一個或多個;
key : 實際使用的索引,如果為
NULL ,則沒有使用索引;key_len: 表示索引中引用的字節數,該值為索引字段最大可能長度,并非實際使用長度,在不損失精確性的前提下,長度越短越好;
rows : MySQL認為必須要執行查詢的行數,在
innoDB 引擎的表中,是一個估計值,可能并不總是準確的;filtered: 表示返回結果的行數占需讀取行數的百分比,filtered的值越大越好;Extra: 額外的信息。
索引使用
最左前綴法則:如果索引了多列(聯合索引),要遵循最左前綴法則。其指的是查詢從索引的最左列開始,并且不跳過索引中的列,與索引時字段的位置沒有關系。如果跳過某一列,索引將部分失效(后面的字段索引失效),這個與創建索引時的順序有關。 范圍查詢:聯合索引中,出現范圍查詢(>,<),范圍查詢右側的列索引失效。盡量使用(>=,<=)。 索引列運算:不要在索引列上進行運算操作,索引將失效。 字符串不加引號:字符串類型字段使用索引時,如果不加引號,索引將失效。 模糊查詢:如果僅僅是尾部模糊匹配(like ‘xx%’),索引不會失效。如果頭部模糊匹配(like ‘%xx’),索引失效。 or 連接條件:用or分割開的條件,如果or前的條件中的列有索引,而后面的列中沒有索引,那么涉及的索引都會失效。即使左側有索引,右側有聯合索引,右側相當于沒有索引,依然or兩側索引失效。 數據分布影響:如果MySQL評估使用索引比全表掃描更慢,則不使用索引。 SQL提示
use index : 建議使用某個索引,最終取決于MySQL
explain select 字段列表
from 表名
use index ( 索引名
) where 條件
; ignore index : 不要使用某個索引
explain select 字段列表
from 表名
ignore index ( 索引名
) where 條件
; force index : 必須使用某個索引
explain select 字段列表
from 表名
force index ( 索引名
) where 條件
;
覆蓋索引:在查詢使用了索引,并且需要返回的字段或列,在該索引中都能找到。盡量使用覆蓋索引,減少
select * using index condition :查找使用了索引,但需要回表查詢數據
using where ; using index : 查找使用了索引,但是需要的數據都在索引列中能找到,所以不需要回表查詢
當字段類型為字符串(
varchar , text 等)時,有時候需要索引很長的字符串,這會讓索引變得很大,查詢時,浪費大量的磁盤IO,影響查詢效率。此時可以只將字符串的一部分前綴建立索引,這樣大大節約索引空間,提升效率。
create index idx_name
on table_name
( column ( n
) ) ; 可以根據索引的選擇性來決定,而選擇性是指不重復的索引值和數據表的記錄總數的壁紙,索引選擇性越高,查詢效率就越高,唯一索引的選擇性為
1 。
select count ( distinct 字段
) / count ( * ) from 表名
; select count ( distinct substring
( 字段,
start ,length
) ) / count ( * ) from 表名
;
單列索引:一個索引只包含單個列聯合索引:一個索引包含多列如果存在多個查詢條件,建議建立聯合索引,使用時注意最左前綴法則
SQL優化
insert into table_name
values ( ) , ( ) , ( ) . . . . . ; start transaction ; insert into . . . ; . . . insert into . . . ; commit ; 主鍵數據順序插入要比亂序效率高如果一次性插入大量數據,使用
insert 性能較低,此時可以使用MySQL數據庫提供的
load 指令進行插入:mysql
select @
@local - infile ; set local - infile = 1 ; load data local infile '文件位置' into table '表名' fields terminated by '數據分隔符' lines terminated by '換行符 \n' ;
在
InnoDB 存儲引擎中,表數據都是根據主鍵順序組織存放的,這種存儲方式的表稱為索引組織表(
index organized
table , IOT)頁可以為空,也可以存儲一半,也可以存儲
100 % 。每個頁包含
2 - N行數據(如果一行數據過大,會行溢出),根據主鍵排列。至少包含兩行數據的原因是,如果只存放一列,而數據又是順序組織存放,就形成了鏈表如果主鍵數據亂序存放,可能發生頁分裂現象當刪除一行記錄時,實際上記錄并沒有被物理刪除,只是記錄被標記為刪除并且它的空間變得允許被其他記錄聲明使用。當頁中刪除的記錄達到MERGE_THRESHOLD
( 默認為頁的
50 % ) ,
InnoDB 會開始尋找最靠近的頁(前或后)看看是否可以將兩個頁合并以優化空間使用。MERGE_THRESHOLD: 合并頁的閾值,可以在創建表或創建索引時指定。滿足業務需求的情況下,盡量降低主鍵的長度;插入數據時,盡量選擇順序插入,選擇使用
auto_increment 自增主鍵;盡量不要使用uuid做主鍵或者其他自然主鍵,如身份證號;業務操作時,避免對主鍵修改。
Using filesort :通過表的索引或全表掃描,讀取滿足條件的數據行,然后在緩沖區sort buffer中完成排序操作,所有不是通過索引直接返回排序結果的排序都叫filesort
. Using index : 通過有序索引順序掃描直接返回有序數據,這種情況為
using index ,不需要額外排序,效率高根據排序字段建立合適的索引,多字段排序時,可建立聯合索引,遵循最左前綴法則;盡量使用覆蓋索引;多字段排序,一個升序一個降序,此時需要注意聯合索引在創建時的規則(
asc / desc );如果不可避免出現filesort,大數據量排序時,可以適當增大排序緩沖區大小sort_buffer_size
( 默認
256 k
) 。
在分組操作時,可以通過索引來提高效率;分組操作時,索引的使用也要滿足最左前綴法則。
一般分頁查詢時,通過創建 覆蓋索引 能夠比較好提高性能,可以通過覆蓋索引加子查詢形式進行優化
myisam引擎把一個表的總數存在了磁盤上,因此執行
count ( * ) 的時候會直接返回這個數,效率較高
innoDB 引擎執行
count ( * ) 時,需要把數據一行一行地從引擎里面讀出來,然后累積計數優化思路:自己計數
InnoDB的行鎖是針對索引加的鎖,不是針對記錄加的鎖,并且該索引不能失效,否則會從行鎖升級為表鎖在使用update修改數據時,盡量使用索引作為條件,防止在事務并發操作時,行鎖升級為表鎖,影響運行效率
視圖
CREATE [ OR REPLACE ] VIEW 視圖名稱
[ ( 列名列表
) ] AS SELECT 語句
[ WITH [ CASCADED | LOCAL ] CHECK OPTION ] ; 查看創建視圖語句:
SHOW CREATE VIEW 視圖名稱
; 查看視圖數據:
SELECT * FROM 視圖名稱
. . ; 1 ) CREATE [ OR REPLACE ] VIEW 視圖名稱
[ ( 列名列表
) ] AS SELECT 語句
[ WITH [ CASCADED | LOCAL ] CHECK OPTION ] ; 2 ) ALTER VIEW 視圖名稱
[ ( 列名列表
) ] AS SELECT 語句
[ WITH [ CASCADED | LOCAL ] CHECK OPTION ] ; DROP VIEW [ IF EXISTS ] 視圖名稱,
. . . ;
1 、聚合函數或窗口函數(
SUM ( ) MIN ( ) MAX ( ) COUNT ( ) )
2 、
DISTINCT 3 、
GROUP BY 4 、
HAVING 5 、
UNION 或者
UNION ALL 視圖不僅可以簡化用戶對數據的理解,也可以簡化他們的操作。那些被經常使用的查詢可以被定義為視圖,從而使得用戶不必為以后的操作指定全部的條件。數據庫可以授權,但不能授權到數據庫特定的行或特定的列上。通過視圖用戶只能查詢和修改他們所能見到的數據。視圖可以幫助用戶屏蔽真實表結構變化帶來的影響。
存儲過程
CREATE PROCEDURE 存儲過程名
( [ 參數列表
] ) BEGIN END ; CALL 名稱
( [ 參數
] ) ; SELECT * FROM INFORMATION_SCHEMA
. ROUTINES
WHERE ROUTINE_SCHEMA
= '數據庫名' ; SHOW CREATE PROCEDURE 存儲過程名稱
; DROP PROCEDURE [ IF EXISTS ] 存儲過程名稱
; 在命令行中,執行存儲過程的
SQL 時,需要通過關鍵字
delimiter 指定
SQL 語句的結束符
系統變量時MySQL服務器提供,不是用戶定義的,屬于服務器層面。分為全局變量
( GLOBAL ) 、會話變量
( SESSION ) SHOW [ SESSION | GLOBAL ] VARIABLES
; SHOW [ SESSION | GLOBAL ] VARIABLES
LIKE '...' ; SHOW @@
[ SESSION | GLOBAL ] 系統變量名
; SET [ SESSION | GLOBAL ] 系統變量名
= 值
; SHOW @@
[ SESSION | GLOBAL ] 系統變量名
= 值
; 如果沒有指定
SESSION / GLOBAL ,默認為
SESSION ;MySQL服務器重新啟動之后,所設置的全局參數會失效,如果想不失效,配置 my
. cnf用戶定義變量是根據用戶需要自己定義的變量,用戶變量不用提前聲明,在用的時候直接用
"@變量名" 使用。其作用域為當前連接會話
SET @var_name = value , [ @var_name = value ] , . . . ; SET @var_name :
= value , [ @var_name = value ] , . . . ; SELECT @var_name :
= value , [ @var_name = value ] , . . . ; SELECT 字段名
/ 聚合函數
INTO @var_name FROM 表名
; SELECT @var_name ; 用戶自定義變量無需進行聲明或初始化,只不過獲取到的值為
NULL 局部變量是根據需要定義在局部生效的變量,訪問之前,需要
DECLARE 聲明??捎米鞔鎯^程內的局部變量和輸入參數,局部變量的范圍是在其內部聲明的
BEGIN . . . END 塊
DECLARE 變量名 變量類型
[ DEFAULT value ] ; SET 變量名
= 值
; SET 變量名 :
= 值
; SELECT 字段名
INTO 變量名
FROM 表名
. . . ;
IN :該類參數作為輸入,也就是需要調用時傳入值 ,默認
OUT :該類參數作為輸出,也就是需要調用時傳出值,需要定義用戶變量接收
INOUT :既可以作為輸入參數,又可以作為輸出參數
CREATE PROCEDURE 存儲過程名
( [ IN / OUT / INOUT 參數名 參數類型
] ) BEGIN SQL END ;
IF 條件
1 THEN . . . ELSEIF 條件
2 THEN . . . ELSE . . . END IF ; CASE case_value
WHEN when_value1
THEN 語句
[ WHEN when_value1
THEN 語句
] . . . [ ELSE 語句
] END CASE ; CASE WHEN 條件表達式
1 THEN 語句
[ WHEN 條件表達式
2 THEN 語句
] . . . [ ELSE 語句
] END CASE ; WHILE 條件
DO SQL 邏輯
END WHILE ; REPEAT SQL 邏輯UNTIL 條件
END REPEAT ; LEAVE ITERATE [ begin_label:
] LOOP SQL 邏輯
END LOOP [ end_label
] ; LEAVE label
; ITERATE label
;
游標(
CURSOR )是用來存儲查詢結果集的數據類型,在存儲過程和函數中可以使用游標對結果集進行循環處理。游標的使用包括游標的聲明、
OPEN 、
FETCH 、和
CLOSE DECLARE 游標名稱
CURSOR FOR 查詢語句
; OPEN 游標名稱
; FETCH 游標名稱
INTO 變量
[ , 變量
] . . ; CLOSE 游標名稱
; 變量的聲明要在游標聲明之前
DECLARE handler_action
HANDLER FOR condition_value
[ , condition_value
] . . . 邏輯語句
; CONTINUE :繼續執行當前程序
EXIT :終止執行當前程序SQLSTATE sqlstate_value :狀態碼 如‘
02000 ’SQLWARNING :所有以
01 開頭的 SQLSTATE代碼的簡寫
NOT FOUND :所有以
02 開頭的 SQLSTATE代碼的簡寫SQLEXCEPTION :所有沒有被 SQLWARNING和
NOT FOUND捕獲的 SQLSTATE代碼的簡寫
CREATE FUNCTION 函數名
( [ 參數列表
] ) RETURNS type ( 參數列表的數據類型
) [ characteristic
. . . ] BEGIN RETURN . . . ; END ; DETERMINISTIC :相同的輸入參數總是產生相同的結果
NO SQL :不包含
SQL 語句
READS SQL DATA :包含讀取數據的語句,但不包含寫入數據的語句
INSERT 型觸發器:NEW表示將要或者已經新增的數據
UPDATE 型觸發器:OLD表示修改之前的數據,NEW表示將要或已經修改后的數據
DELETE 型觸發器:OLD表示將要或者已經刪除的數據
CREATE TRIGGER trigger_nameBEFORE
/ AFTER INSERT / UPDATE / DELETE ON table_name
FOR EACH ROW BEGIN trigger_statement
; END ; SHOW TRIGGER ; DROP TRIGGER [ 數據庫名
. ] trigger_name
;
鎖
鎖是計算機協調多個進程或線程并發訪問某一資源的資質。
flush
tables with read lock ; mysqldump
- h遠程ip
- uroot
- p密碼 數據庫
> 備份文件
; unlock tables ; 1 、如果在主庫上備份,那么在備份期間都不能執行更新,業務基本上停止。
2 、如果在從庫上備份,那么在備份期間從庫不能執行主庫同步過來的二進制日志,會導致主從延遲。在
InnoDB 引擎中,可以在備份時加 mysqldump
lock tables 表名
. . . read ; unlock tables ; / 斷開客戶端連接
lock tables 表名
. . . write ; unlock tables ; / 斷開客戶端連接 讀鎖不會組測其他客戶端的讀操作,但是會阻塞寫。寫鎖會阻塞其他客戶端的讀操作,又會阻塞其他客戶端的寫操作。MDL加鎖過程是系統自動控制,無序顯式使用,在訪問一張表的時候會自動加上。MDL鎖主要作用是維護表元數據一致性,在表上有活動事務時候,不可以對元數據進行寫操作。為了避免DML與DDL沖突,保證讀寫的正確性。在MySQL5
. 5 中引入MDL,當對一張表進行增刪改查時,加MDL讀鎖(共享);對表結構進行變更操作時,加MDL寫鎖(排他)。
select object_type
, object_schema
, object_name
, lock_type
, lock_duration
from perfromance_schema
. metadata_locks
;
為了避免DML在執行時,加的行鎖與表鎖的沖突,在
innoDB 中引入了意向鎖,使得表鎖不用檢查每行數據是否加鎖,使用意向鎖來減少表鎖的檢查與表鎖共享鎖兼容,與表鎖排他鎖互斥與表鎖均互斥,意向鎖之間不互斥
select object_type
, object_schema
, object_name
, lock_type
, lock_duration
from perfromance_schema
. data_locks
;
1 、行鎖(record
lock ):鎖定單個行記錄,防止其他事務對此行進行
update 和
delete 。在RC、RR隔離級別下都支持
2 、間隙鎖(gap
lock ):鎖定索引記錄間隙(不含該記錄),確保索引記錄間隙不變,防止其他事務在該間隙
insert ,產生幻讀。在RR隔離級別下都支持
3 、臨鍵鎖(
next - key lock ) : 行鎖與間隙鎖的組合,同時鎖住數據,并鎖住數據前面的間隙。在RR隔離級別下都支持
1 、共享鎖(S):允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。
2 、排他鎖(X):允許獲取其他排他鎖的事務更新數據,阻止其他事務獲得相同數據集的共享鎖和排他鎖默認情況下,
InnoDB 在
REPEATABLE READ 事務隔離級別運行,
InnoDB 使用NEXT_KEY鎖進行搜索和索引掃描,以防止幻讀。
1 、針對唯一索引進行檢索,對已存在的記錄進行等值匹配時,將會自動優化為行鎖
2 、
InnoDB 的行鎖是針對索引加的鎖,不通過索引條件檢索數據,那么引擎將對表中的所有記錄加鎖,此時就會升級為表鎖
select object_type
, object_schema
, object_name
, lock_type
, lock_duration
from perfromance_schema
. data_locks
;
1 、索引上的等值查詢(唯一索引),給不存的記錄加鎖時,優化為間隙鎖。
2 、索引上的等值查詢(普通索引),向右遍歷時最后一個值不滿足查詢需求時,臨鍵鎖退化為間隙鎖
3 、索引上的范圍查詢(唯一索引)間隙鎖唯一目的是防止其他事務插入間隙。間隙鎖可以共存,一個事務采用的間隙鎖不會組織另一個事務在同一間隙上采用間隙鎖
InnoDB引擎
邏輯存儲結構
表空間(ibd文件),一個MySQL實例可以對應多個表空間,用于存儲記錄、索引等數據。 段,分數據段(leaf node segment)、索引段(non-leaf node segment)、回滾段(rollback segment)、InnoDB是索引組織表,數據段就是B+樹的葉子節點,索引段即為B+樹的非葉子節點。段用來管理多個區。 區,表空間的單元結構,每個區的大小為1M。默認情況下,存儲引擎頁大小為16K,一個區中有64個連續的頁。 頁,存儲引擎磁盤管理的最小單元,每個頁的大小默認為16K。為保證頁的連續性,存儲引擎每次從磁盤申請4-5個區。 行,存儲引擎數據是按行進行存放的。
架構
內存架構
Buffer Pool :緩沖池是主內存中的一個區域,里面可以緩存磁盤上經常操作的真實數據,在執行增刪改查操作時,先操作緩沖池中的數據(若沒有數據,從磁盤加載并緩存),然后再以一定頻率刷新到磁盤,從而減少磁盤iIO,加快處理速度。
緩沖池以頁為單位,底層采用鏈表數據結構管理頁。根據狀態頁分為三種類型:
free page: 空閑頁,未被使用 liean page: 被使用的頁,數據沒有被修改過 dirty page: 臟頁,被使用,數據被修改過,頁中數據與磁盤的數據產生不一致 Change Buffer :更改緩沖區(針對非唯一二級索引頁),在執行DML語句時,如果這些數據頁沒有在緩沖池中,不會直接操作磁盤,而會將數據變更存在更改緩沖區中,在未來數據被讀取時,再將數據合并恢復到緩沖池中,最后將合并后的數據刷新到磁盤中。
Adaptive Hash Index :自適應哈希索引,用于優化對緩沖池數據的查詢。存儲引擎會監控表上各索引頁的查詢,如果觀察到哈希索引可以提升速度,則建立哈希索引。無需干涉,系統根據情況自動建立
參數: adaptive_hash_index – 查看是否開啟
Log Buffer :日志緩沖區,用來保存要寫入磁盤中的日志數據(redo log、undo log),默認大小為16MB,日志緩沖區的日志會定期刷新到磁盤。如果需要更新、插入或刪除許多行的事務,增加日志緩沖區的大小可以節省磁盤IO。
innodb_log_buffer_size innodb_flush_log_at_trx_commit
磁盤架構
System Tablespace :系統表空間時更改緩沖區的存儲區域。如果表是在系統表空間而不是每個表文件或通用表空間中創建的,它也可能包含表和索引數據。
innodb_data_file_path
File-Per-Table Tablespace :每個表的文件表空間包含單個存儲引擎表的數據和索引,并存儲在文件系統上的單個數據文件中。
innodb_file_per_table
General Tablespace :通用表空間,需要通過用戶自己創建,在創建表時,可以指定該表空間。
CREATE TABLESPACE space_name
ADD DATAFILE
'file_name.ibd' ENGINE = InnoDB ; CREATE TABLE . . . ( ) TABLESPACE space_name
;
Undo Tablespace :撤銷表空間,MySQL實例在初始化時會自動創建兩個默認的undo表空間,初始大小16M,用于存儲undo log 日志。
Temporaty Tablespace :存儲引擎會話臨時表空間和全局臨時表空間,存儲用戶創建的臨時表等數據。
Doublewrite Buffer Files :雙寫緩沖區,存儲引擎將數據頁從Buffer Pool刷新到磁盤前,先將數據頁寫入雙寫緩沖區文件中,便于系統異常恢復數據。 xxx.dblwr文件
Redo Log :重做日志,是用來實現事務的持久性。該日志文件由兩部分組成:重做日志緩沖以及重做日志文件,前者是在內存中,后者在磁盤中。當事務提交之后會把所有修改信息都會存放到該日志中,用于在刷新臟頁到磁盤,發生錯誤時,進行數據恢復。
后臺線程
Read thread
Write thread Log thread
Insert buffer thread
事務原理
Redo Log :重做日志,是用來實現事務的持久性。該日志文件由兩部分組成:重做日志緩沖以及重做日志文件,前者是在內存中,后者在磁盤中。當事務提交之后會把所有修改信息都會存放到該日志中,用于在刷新臟頁到磁盤,發生錯誤時,進行數據恢復。
Undo log :回滾日志,用于記錄數據被修復前的信息,作用包含兩個:提供回滾和MVCC(多版本并發控制)
undo log與redo log記錄物理日志不一樣,它是邏輯日志。可以認為當
delete 一條記錄時,undo log中會記錄一條對應的
insert 記錄,反之亦然,當
update 一條記錄時,它記錄一條對應相反的
update 記錄。當執行roolback時,就可以從undo log中的邏輯記錄讀取到相應的內容并進行回滾。
undo log銷毀:在事務執行時發生,事務提交時,并不會立即刪除undo log,因為這些日志可能用于MVCC
undo log存儲:undo log采用段的方式進行管理和記錄,存放在前面介紹的
rollback segment回滾段中,包含
1024 個undo log segment。
MVCC
讀取的時記錄的最新版本,讀取時還要保證其他并發事務不能修改當前記錄,會對讀取的記錄進行加鎖。如:
select . . . lock in share mode ( 共享鎖
) 、
select . . . for update 、
update 、
insert 、
delete ( 排他鎖
) 都是一種當前讀。
簡單的select(不加鎖)就是快照讀,讀取的時記錄數據的可見版本,有可能是歷史數據,不加鎖,是非阻塞讀。
Read Committed : 每次
select ,都生成一個快照讀。
Repeatable Read : 開啟事務后第一個
select 語句才是快照讀的地方。
Serializable : 快照讀會退化為當前讀
全稱Multi-Version Concurrency Control,多版本并發控制。指維護一個數據的多個版本,使得讀寫操作沒有沖突,快照讀為MySQL實現MVCC提供了一個非阻塞讀功能。MVCC的具體實現,還需要依賴與數據庫記錄的三個隱式字段、undo log、readView。
DB_TRX_ID :最近修改事務ID,記錄插入這條記錄或最后一次修改該記錄的事務ID
DB_ROLL_PTR :回滾指針,指向這條記錄的上一個版本,用于配合undo log,指向上一個版本
DB_ROW_ID : 隱藏主鍵,如果表結構沒有指定主鍵,將會生成該隱藏字段
當
insert 時候,產生的日志旨在回滾時需要,在事務提交后,可被立即刪除。
當
update 、
delete 時候,產生的 undo log日志不僅在回滾時需要,在快照讀時也需要,不會被立即刪除
不同事務或相同事務對同一條記錄進行修改,會導致記錄的日志生成一條記錄版本鏈表,鏈表頭部是最近的舊記錄,鏈表尾部是最早的舊記錄
m_ids: 當前活躍的事務ID集合
min_trx_id: 最小活躍事務
max_trx_id: 預分配事務ID,當前最大事務ID
+ 1 (因為事務ID時自增的)
creator_trx_id: 讀視圖創建者的事務ID
READ COMMITTED : 在事務中每一次執行快照讀時生成讀視圖
REPEATABLE READ :僅在事務中第一次執行快照讀時生成讀視圖,后續復用該讀視圖
總結
以上是生活随笔 為你收集整理的MySQL学习笔记-从基础到进阶 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。