extra 這個欄位中的「using filesort」表示的就是需要排序,mysql 會給每個執行緒分配一塊記憶體用於排序,稱為 sort_buffer
select city,name,age from t where city='杭州' order by name limit 1000
從普通索引中找到 city='杭州'的主鍵id,去主鍵索引裡找行記錄,放入sort_buffer,重複,完成將sort_buffer中的資料按照name排序之後取出1000條返回
optimizer_trace可協助檢視排序是否使用到外部檔案的資訊
如果查詢要返回的字段很多的話,那麼 sort_buffer 裡面要放的字段數太多,這樣記憶體裡能夠同時放下的行數很少,要分成很多個臨時檔案,排序的效能會很差
max_length_for_sort_data,是 mysql 中專門控制用於排序的行資料的長度的乙個引數,如果小於字段總長度,則先排序先保留排序欄位和索引字段,最後返回1000條id再去主鍵索引補充其餘字段資訊
mysql 之所以需要生成臨時表,並且在臨時表上做排序操作,其原因是原來的資料都是無序的
index city_user(city, name) -> 從普通索引中找到city='杭州'的主鍵id,去主鍵索引裡找行記錄,直接返回,只需要掃瞄1000行返回,因為索引有序,少了排序的過程
city_user_age(city, name, age) -> 覆蓋索引是指,索引上的資訊足夠滿足查詢請求,不需要再回到主鍵索引上去取資料
1. 隨機選取,order by rand() limit 3; 使用了記憶體臨時表
extra 字段顯示 using temporary,表示的是需要使用臨時表;using filesort,表示的是需要執行排序操作
rowid 名字的來歷。實際上它表示的是:每個引擎用來唯一標識資料行的資訊,對於有主鍵的 innodb 表來說,這個 rowid 就是主鍵 id,對於沒有主鍵的 innodb 表來說,這個 rowid 就是由系統生成的,emory 引擎不是索引組織表。在這個例子裡面,你可以認為它就是乙個陣列。因此,這個 rowid 其實就是陣列的下標
堆排序 vs 歸併排序,取部分max/min vs 全域性有序
2. 得到max/min id,用隨機演算法生成隨機id,查id=隨機id的返回,可能由於空洞導致不平均
3. 得到總行數,取隨機一行,limit y,1;按順序乙個乙個地讀出來,丟掉前 y 個,然後把下乙個記錄作為返回結果,因此這一步需要掃瞄 y+1 行。再加上,第一步掃瞄的 c 行,總共需要掃瞄 c+y+1 行,執行代價比隨機演算法 1 的代價要高
對索引欄位做函式操作,可能會破壞索引值的有序性,因此優化器就決定放棄走樹搜尋功能
即使是對於不改變有序性的函式,也不會考慮使用索引
在 mysql 中,字串和數字做比較的話,是將字串轉換成數字,where cast(tradid as signed int) = 110717 也會影響索引使用
兩個表的字符集不同,乙個是 utf8,乙個是 utf8mb4,所以做表連線查詢的時候用不上關聯欄位的索引,where convert(traideid using utf8mb4)=$l2.tradeid.value;,修改字符集或where d.tradeid=convert(l.tradeid using utf8) and l.id=2;
查詢長時間不返回?
- show processlist 可能鎖了,殺掉持有程序;sys.schema_table_lock_waits 這張表,我們就可以直接找出造成阻塞的 process id,把這個連線用 kill 命令斷開即可
- 等 flush,flush tables 關閉 mysql 裡所有開啟的表
- 等行鎖 lock in share mode,記錄時要加讀鎖,如果這時候已經有乙個事務在這行記錄上持有乙個寫鎖,我們的 select 語句就會被堵住,連線被斷開的時候,會自動回滾這個連線裡面正在執行的執行緒
- 查詢慢
session b 更新完 100 萬次,生成了 100 萬個回滾日誌 (undo log)。帶 lock in share mode 的 sql 語句,是當前讀,因此會直接讀到 1000001 這個結果,所以速度很快;而 select * from t where id=1 這個語句,是一致性讀,因此需要從 1000001 開始,依次執行 undo log,執行了 100 萬次以後,才將 1 這個結果返回
for update當前讀加寫鎖
幻讀,乙個事務在前後兩次查詢同乙個範圍的時候,後一次查詢看到了前一次查詢沒有看到的行
在可重複讀隔離級別下,普通的查詢是快照讀,是不會看到別的事務插入的資料的。因此,幻讀在「當前讀」下才會出現。上面 session b 的修改結果,被 session a 之後的 select 語句用「當前讀」看到,不能稱為幻讀。幻讀僅專指「新插入的行」
鎖的設計是為了保證資料的一致性。而這個一致性,不止是資料庫內部資料狀態在此刻的一致性,還包含了資料和日誌在邏輯上的一致性
即使把所有的記錄都加上鎖,還是阻止不了新插入的記錄,這也是為什麼「幻讀」會被單獨拿出來解決的原因
行鎖只能鎖住行,但是新插入記錄這個動作,要更新的是記錄之間的「間隙」。因此,為了解決幻讀問題,innodb 只好引入新的鎖,也就是間隙鎖 (gap lock)
間隙鎖和行鎖合稱 next-key lock,每個 next-key lock 是前開後閉區間,間隙鎖之間不衝突,間隙鎖的引入,可能會導致同樣的語句鎖住更大的範圍,這其實是影響了併發度的
間隙鎖是在可重複讀隔離級別下才會生效的
隔離級別設定為讀提交的話,就沒有間隙鎖了。但同時,你要解決可能出現的資料和日誌不一致問題,需要把 binlog 格式設定為 row
學習記錄 MySQL實戰45講 27 29
一主多從,一般用於讀寫分離,主庫負責所有的寫入和一部分讀,其他的讀請求則由從庫分擔,a 和 a 互為主備 主備切換 基於位點的主備切換,從庫需要change master到主庫並提供對應的檔名和日誌偏移量,等待新主庫 a 把中轉日誌 relay log 全部同步完成 在 a 上執行 show mas...
學習記錄 MySQL實戰45講 31 33
傳統的高可用架構是不能預防誤刪資料的,因為主庫的乙個 drop table 命令,會通過 binlog 傳給所有從庫和級聯從庫,進而導致整個集群的例項都會執行這個命令 a.誤刪行 flashback 工具通過閃回把資料恢復回來 修改 binlog 的內容,拿回原庫重放,insert delete,u...
實戰mysql45講 MySQL實戰45講
作者簡介 林曉斌,網名 丁奇 前阿里資深技術專家,曾負責阿里雲rds核心開發團隊和運維團隊,並推動了alisql分支開源。作為活躍的mysql社群貢獻者,丁奇專注於資料儲存系統 mysql原始碼研究和改進 mysql效能優化和功能改進,熱衷於解決mysql疑難問題。課程亮點 你將獲得 前阿里資深技術...