innodb 引擎 行鎖與表鎖
行鎖與表鎖是基於索引來說的(且索引要生效)
不帶索引 (表鎖)要全表掃描
1. 執行select @@autocommit; 查看結果 0是不自動提交事務,1是自動提交事務, mysql默認是自動提交
2. set autocommit = 0;設置為不開啟自動提交
3. 通過開多個tab窗口模擬不通的session 執行數據庫
新建一張person表
窗口1 模擬第一個session
在此窗口先執行設置0,在單獨執行update語句
窗口2 模擬第二個session
執行該條語句可以看到 sql一直執行 卡住了,因為它是在等待上一個事務執行完釋放表鎖
經過一段時間后看到如下結果
這個錯跟我們生產上報的錯一樣,用pinpoint監控的
------------------------------------------------------
執行update 和insert 都是一樣的結果 在等待表鎖,雖然我操作的不是同一行數據。
如果我把窗口1的事務提交則窗口2會從卡的狀態成功執行結束
窗口1的commit;
窗口2的session的則立馬執行完畢,
這個場景模擬的是表鎖,當session1 拿到表鎖后,別的事務的session執行(insert,update,delete) 是拿不到鎖的會進行鎖等待。
通過命令 看到了當前處於等待的語句
把name字段添加索引(行鎖)不用全表掃描直接定位到行 ,使用主鍵也是用的行鎖
添加索引,然后通過執行計划查看索引是生效的
在回到之前的問題,窗口1 再次執行相同的sql 不提交事務,此時執行窗口2
窗口2 直接執行完畢,此時行鎖生效,我操作的不是同一行,結果生效了
以上是innodb引擎的表鎖 和行鎖 ,順便驗證一下默認的事務隔離級別(讀已提交的)
開一個窗口3 代表session3
事務執行前
刪掉剛才的索引 drop index namex_name on person;
窗口1 執行,當前事務下的結果改變了
窗口3驗證 窗口1的事務沒提交前 別的事務是讀不到這個事務的,如果把窗口1的事務提交 怎窗口3能順利讀取, 這同時說明了2個隔離級別 -----------讀已提交的 和不可重讀
事務的可串行化可參考:https://blog.csdn.net/nangeali/article/details/75578787 事務內的查詢都是帶鎖的(表鎖)
表鎖與行鎖 以上自己通過數據庫執行 直觀的驗證了一遍,可以看如下這邊文章的文字描述來抽象這個驗證
參考:https://blog.csdn.net/lz710117239/article/details/71762617
https://blog.csdn.net/u014635472/article/details/79712931 或者 https://www.cnblogs.com/wodebudong/articles/7976474.html
總結: 普通的 曾刪改 是表鎖,加入索引的曾刪改 是行鎖,執行 查詢是不加任何鎖的, 不是有些博客所說的 表鎖升級為行鎖 。