苦海無邊
基於mysql8.0.2
A.mysql常用命令
- 查詢版本
mysql -v
客戶端未連接
select version();
,\s
,status;
客戶端已連接 - 查詢隔離級別
show variables like '%isolation%';
通用方法
select @@transaction_isolation;
v8.0.2
select @@tx_isolation;
老一點的版本,具體不清楚啊,略惆悵 - 修改隔離級別
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED | SERIALIZABLE }
- 查詢當前數據庫:
SELECT database();
- 查詢所有數據庫:
show databases;
- 使用數據庫a:
use a;
- 開啓一個事務:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
,begin;
- 查詢當前會話是否自動提交:
select @@autocommit;
,show variables like 'autocommitt;'
- 設置自動提交狀態:
set autocommit=[0,1];
,0:不自動;1:自動 - 新增列:
alter table xxxx add column c_name c_type c_default;
B.mysql配置解析
C.mysql知識點解析
1.count(*)工作原理
對於innodb,它是索引組織表,主鍵索引樹的葉子節點是數據,而普通索引樹的葉子節點是主鍵值。對於 count(*) 這樣的操作,MySQL 優化器會找到最小的那棵樹來遍歷。
不記錄表數據行數的原因:innodb的事務設計是通過多版本併發控制(MVCC)來實現的;每一行都需要判斷自己是否對會話可見,因此需要一條一條的去讀出判斷
show table status
命令查詢,結果中有字段 TABLE_ROWS
來顯示錶當前行數。該命令查詢很快,但注意:該值爲採樣估算值,不可直接使用;官方誤差可能達到40%到50%
幾種計數效率:count(字段)<count(主鍵 id)<count(1)≈count()
count()專門做了優化,並不會把全部字段取出來,count(*) 肯定不是 null,按行累加。
count(字段)需要對字段進行非空判斷,不爲空才累加;
count(1)不需要對數據進行解析,按行累加;
count(*)是一個耗時操作,獲取計數的解決方案:
- 緩存系統計數:通過緩存來對數據的增減進行計數,缺點: 可能導致計數誤差;— 多系統協調的弊端,當然在正常情況下,可以保證最終一致性;
- 數據庫保存計數:建立專門的統計表通過事務來保證一致性;也可以通過觸發器來完成該動作;
2.Order by工作原理
order by 分爲 全字段排序
和 rowId排序
:
- 全字段排序
會根據排序字段的索引,獲取到要查詢的字段,然後放入sort buffer中進行排序;當數據量較大時(由參數 sort_buffer_size 控制
)會通過臨時文件拆分的方式(分治,歸併)來進行排序;
在索引建立時,可以聯合查詢字段進行索引創建,可以減少回表;同時可能讓符合條件的數據本身即爲有序的,則不需要排序;這極大地提升了性能;
-- 示例:
-- 索引 index(city, name, age),天然有序
select city,name,age from t where city='杭州' order by name limit 1000 ;
- rowId排序
當排序行數據長度 > max_length_for_sort_data
時,採用 排序字段 + id 的方式放入sort buffer排序;再通過回表的方式將最終結果返回客戶端;
- 確認是否使用臨時文件:
/* 打開optimizer_trace,只對本線程有效 */
SET optimizer_trace='enabled=on';
/* @a保存Innodb_rows_read的初始值 */
select VARIABLE_VALUE into @a from performance_schema.session_status where variable_name = 'Innodb_rows_read';
/* 執行語句 */
select city, name,age from t where city='杭州' order by name limit 1000;
/* 查看 OPTIMIZER_TRACE 輸出 */
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G
-- number_of_tmp_files 表示的是,排序過程中使用的臨時文件數
-- examined_rows 表示參與排序的行數
-- sort_mode > packed_additional_fields 在排序過程中還是要按照實際長度來分配空間的。
/* @b保存Innodb_rows_read的當前值 */
select VARIABLE_VALUE into @b from performance_schema.session_status where variable_name = 'Innodb_rows_read';
/* 計算Innodb_rows_read差值:表示整個執行過程掃描行數, innodb值會比實際值多1 */
select @b-@a;
D.mysql問題彙總
1.解析語句:insert into tableA
(A, B, C) values (B, A, 2) on duplicate key update C=C | 2;
insert … on duplicate 語句,確保了在事務內部,執行了這個 SQL 語句後,就強行佔住了這個行鎖,
確保了之後的操作是在行鎖保護下的讀操作。
當有兩個事務同時插入時,保證當前事務的值爲倆事務的按位或值;
2.爲什麼varchar字段長度常設置成功255
官方概念:VARCHAR類型的值存儲格式爲1到2個字節的長度前綴加上數據內容。長度前綴表示數據內容的字節數。當數據所需最大長度不超過255字節時,長度前綴爲1個字節,當數據所需最大長度超過255個字節時,長度前綴爲2個字節。
原因:我們知道 1byte = 8bit;剛好夠用來表示[0, 255],因此長度超過255時,需要多一個字節來表示長度;爲了節省空間,常設置長度爲不大於255的值;