MySQL邏輯架構
- 最上層服務: 連接處理,授權認證,安全等
- 第二層架構:包含了大多數的核心服務功能,包括:查詢解析、分析、優化、緩存、內置函數,所有跨存儲引擎的功能都在這一層實現,比如:存儲過程、觸發器、視圖等
- 第三層架構:存儲引擎,負責MySQL的數據存儲和提取
鎖
- 讀寫鎖
- 共享鎖/讀鎖
- 排它鎖/寫鎖: 優先級高於讀鎖,一個寫請求可能會被插在讀鎖隊列前面
- 鎖粒度
- 表鎖:alter table 之類語句會使用表鎖
- 行級鎖
事務
隔離級別
- READ UNCOMMITTED 未提交讀,事務中的未提交修改對其他事務可見,容易髒讀,一般不用
- READ COMMITTED 提交讀/不可重複讀
- REPEATABLE READ 可重複讀(MySQL默認事務隔離級別),引起幻讀(當某個事務在讀取範圍內數據時,另一事務在範圍內插入了新數據,某事務再次讀取時,會產生幻行),MVCC解決了幻讀的問題
- SERIALIZABLE 可串行化 ,最高的隔離級別,
多版本併發控制 MVCC
- MVCC只存在於可重複讀、提交讀兩個隔離級別下
- 樂觀併發控制、悲觀併發控制
- MVCC是通過在每行記錄後面保存兩個列來實現的(行的創建時間系統版本號,行的過期/刪除時間系統版本號),每開始一個新的事務,系統版本號就會遞增,事務的版本號就是該事務開始時刻的系統版本號。
- 以InnoDB爲例:
SELECT: 只查找版本號小於等於當前事務的數據行;行的刪除版本要麼未定義,要麼大於當前事務版本號。
INSERT:爲新插入行保存當前系統版本號爲行版本號。
DELETE:爲刪除行保存當前系統版本號爲行刪除標識。
UPDATE:爲新插入行保存當前系統版本號爲行版本號,同時保存當前系統版本號爲原來行的行刪除標識。
還有啥
- 加快alter table 操作速度
- 常見的alter方法都是新建空表,從舊錶中查出數據插入新表,然後廢除舊錶
- 其實並不是所有的alter操作都會引起表重建。
- 列的默認值存在表的.frm文件中,可以直接修改這個文件,這個語句會直接修改.frm文件而不涉及表數據
# 快速修改列默認值方法:
alter table film alter column end_time set default 5;
- 修改表默認編碼方式
不推薦,只對新的字段生效,老的字段不會做改動
ALTER TABLE tb1 DEFAULT CHARACTER SET=utf8mb4 COLLATE utf8mb4_general_ci;
不推薦,只單獨修改表裏面某個字段的字符集類型不推薦:
ALTER TABLE tb1 change c c varchar(50) CHARACTER SET utf8mb4 not null default 'only for test' ;
推薦:這種寫法老的字段也修改成utf8mb4:
ALTER TABLE tb1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
- 修改註釋
修改註釋實際只修改.frm文件,不會改動ibd文件的,操作執行的很快。
alter table tb_name modify `column_name` default null comment '編號***'
alter table tb_name comment '用戶表'
- 分頁優化
常見的分頁寫法
select * from students limit 10000,20;
# 這樣會將查出的10000行丟棄掉
優化:
可以取前一頁的最大行數的id,然後根據這個id來限制下一頁的起點。
例如:上一頁最大的id是87654321。sql可以採用如下的寫法:
select id,name from students where id> 87654321 limit 20
- MYSQL會在索引中儲存null值,Oracle不會
- MySQL限制了每個關聯操作最多只能有61張表,如果希望查詢快且併發性好,單個查詢最好在12個表以內做關聯
- 緩存表對優化搜索很有效,對於緩存表,可以使用不同的存儲引擎,比如MyISAM,會得到更小的索引佔用空間,還可以全文搜索。
索引
一般我們說的索引大多數指的是B-Tree 索引,B-Tree 索引意味着所有的值都是按照順序存儲的,且每一個葉子頁到根的距離相同,它之所以快,是因爲搜索是從索引的根節點開始搜索, 而在根節點的槽中存放了指向子節點的指針。
- 此處有一張表
索引爲 name, job_number, hired_time, 請暫時忽略索引的合理性,僅僅作爲聯合索引的講述
CREATE TABLE employe (
name varchar(20) not null,
job_number int not null,
gender enum('m', 'f') not null,
hired_time date not null,
key(name, job_number, hired_time)
)
B-Tree 適合的索引查找類型:
- 全值匹配
比如: 搜索姓名Ann,工號爲123456,入職時間爲2018-11-11的員工 - 鍵值範圍查詢(由於索引列是順序組織起來的,所以特別適合範圍查找)
比如:搜索姓在Anna和David之間的員工,此時只使用了索引的第一列name - 鍵前綴查找(只適用於左前綴的查找)
比如:搜索姓名爲Ann的員工或搜索姓名以A開頭的員工 - 全值匹配+範圍匹配
比如:查詢姓名爲Ann,工號大於12345的員工
關於B-Tree的限制
- 如果不是按照索引列的最前綴開始查找,則無法使用索引
比如:查找名字以a結尾的員工 - 不能跳過索引中的列
比如:搜索名字爲Ann, 入職時間爲2018-01-01至今的員工,跳過了工號這一列,則索引實際只會使用第一列name或者hired_time,這個就看MYSQL內部的優化選擇了 - 如果查詢中涉及到某個列的範圍查詢,那剩餘右邊的列都無法使用索引優化查找
比如:搜索姓名爲Ann,且工號在A12至C123之間的,入職時間爲2018-11-01的員工,此處工號爲範圍查詢,所以入職時間這一類無法使用索引查詢
其他
- 索引必須是獨立的列,不能是表達式/函數等
- 前綴索引能使索引更小、更快,缺點是不能做 order by 和 group by
- 當不需要考慮排序和分組時,選擇性高的列在前面是很好的
- 覆蓋索引:一個查詢的字段全是索引
- MySQL不能在索引中執行like操作