關於數據庫行鎖與表鎖的認識


MySQL

MySQL(InnoDB存儲引擎)默認是自動提交事務的,所以這個測試,需要先將MySQL的autocommit設置為0,關閉自動提交,需要自己手動提交事務

-- 關閉自動提交
set autocommit=0;
-- 開啟事務
begin;

這里我主要針對的是悲觀鎖,其實也就是行鎖和表鎖,SQL 加上 FOR UPDATE 即可

行鎖

這個時候,我們再開啟一個客戶端訪問MySQL,輸入同一條加鎖的SQL查詢

這個時候是沒有任何結果的,因為t_card表已經加鎖了(這個時候其實加的是行鎖),所以cardid=‘1’ 這一行的其他加鎖操作是無效的

但是不加鎖查詢這一條記錄卻是可以的

也就是說雖然這一條記錄所在的行被鎖定了,但是並不影響我們正常的查詢,當然了針對這一行的DML操作也是無效的

那如果我們對除了cardid=‘1’ 的其他行操作會怎樣呢?

對於其他的行DML是完全沒問題的,所以我在前面才說這是行鎖,因為只有我們的cardid=‘1’的行被鎖了

好吧,我們放過cardid=‘1’這一行吧

提交事務之后,另一邊的加鎖SQL才會生效

表鎖

上面我們測試的只是行鎖,那表鎖,或者說怎樣才會發生表鎖?

沒錯,我們不根據主鍵查詢,而是查詢所有的記錄,MySQL就對整張表加鎖了,這不就是表鎖了嘛。對於這張表的任何記錄進行DML都是無效的

同時我們對於這張表的任何行進行加鎖SQL操作是無效的,那普通的SQL查詢又怎樣呢?

還好,這不妨礙我們的普通查詢,畢竟查詢是與鎖這東西沒什么緣分的

結論

只要有鎖存在的地方(無論是一行還是整張表),我們對有鎖的地方進行任何加鎖SQL都是無效的,當然了DML也是無效的;但是我們的普通查詢是沒有問題的,同時對於沒有鎖的行也是可以進行DML操作的

至於如何解除鎖,可以查看這篇博客: https://zhengdl126.iteye.com/blog/1570865 。最后記得把MySQL的autocommit = 1

Oracle

Oracle是需要我們手動提交事務的,所以,我們不需要任何設置即可測試

只有提交事務之后,另一邊才會生效,同樣的普通查詢是沒有問題的。如果不根據主鍵查詢,就會鎖整張表。最后的結論是與MySQL一致的

查看哪張表被鎖以及解鎖

-- 查看哪張表被鎖
SELECT object_name, machine, s.sid, s.serial#, logon_time, locked_mode
FROM gv$locked_object l, dba_objects o, gv$session s 
WHERE l.object_id = o.object_id 
AND l.session_id = s.sid;

-- 解鎖(根據上邊SQL查詢結果得到sid和serial#)
--alter system kill session 'sid,serial#'; 
ALTER system kill session '23,1647'; 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM