關於mysql不得不說的一些事情

基於mysql8.0.2

A.mysql常用命令

  1. 查詢版本
    mysql -v 客戶端未連接
    select version();\sstatus; 客戶端已連接
  2. 查詢隔離級別
    show variables like '%isolation%'; 通用方法
    select @@transaction_isolation; v8.0.2
    select @@tx_isolation; 老一點的版本,具體不清楚啊,略惆悵
  3. 修改隔離級別
    SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL { REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED | SERIALIZABLE }
  4. 查詢當前數據庫:SELECT database();
  5. 查詢所有數據庫:show databases;
  6. 使用數據庫a: use a;
  7. 開啓一個事務:START TRANSACTION WITH CONSISTENT SNAPSHOT;begin;
  8. 查詢當前會話是否自動提交:select @@autocommit;show variables like 'autocommitt;'
  9. 設置自動提交狀態:set autocommit=[0,1];,0:不自動;1:自動
  10. 新增列: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(*)是一個耗時操作,獲取計數的解決方案:

  1. 緩存系統計數:通過緩存來對數據的增減進行計數,缺點: 可能導致計數誤差;— 多系統協調的弊端,當然在正常情況下,可以保證最終一致性;
  2. 數據庫保存計數:建立專門的統計表通過事務來保證一致性;也可以通過觸發器來完成該動作;

2.Order by工作原理

order by 分爲 全字段排序rowId排序

  1. 全字段排序
    會根據排序字段的索引,獲取到要查詢的字段,然後放入sort buffer中進行排序;當數據量較大時(由參數 sort_buffer_size 控制)會通過臨時文件拆分的方式(分治,歸併)來進行排序;
    在索引建立時,可以聯合查詢字段進行索引創建,可以減少回表;同時可能讓符合條件的數據本身即爲有序的,則不需要排序;這極大地提升了性能;
-- 示例:
-- 索引 index(city, name, age),天然有序
select city,name,age from t where city='杭州' order by name limit 1000  ;
  1. 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的值;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章