王志國 周笑宇* 蘇仕斌
(1.中國人民解放軍聯勤保障部隊第九六三醫(yī)院 黑龍江省佳木斯市 154002)
(2.中國人民解放軍總醫(yī)院醫(yī)學創(chuàng)新研究部 北京市 100853)
數據庫是多個用戶使用的共享資源。 當多個用戶同時訪問同一數據庫時,多個事務將同時訪問數據庫中的相同數據,此時,多個用戶很有可能共同進行對于該數據庫的查詢、修改等操作。如果對于并發(fā)操作不加以管理,則可能會讀寫錯誤的數據,并破壞數據庫四大特性中的一致性。 鎖是數據庫對并發(fā)訪問的、在指定權限下可以進行共同訪問的管理的機制,它用于保護以合理的方式被修改的數據。 當事務提交或者回滾后,對于該單位進行釋放資源,此時其他用戶可以正常的更新數據。
Oracle 關于鎖的機制是輕量級的,它直接將鎖作為數據塊的屬性,存儲在數據塊的頭中,而不是建立用于數據鎖管理的鎖列表。鎖是數據塊本身的一個屬性,每個數據塊本身將數據的信息存儲在自己的數據塊中。這個地方叫做ITL。每當此數據塊上有活動事務時,它的信息都會記錄在該數據塊中,以供后續(xù)操作查詢,確保事務的一致性。在oracle 數據庫中,沒有實際屬于對象或數據的鎖。鎖的信息是物理屬性的一部分,而不是邏輯屬性。
2.1.1 DML 鎖DML 鎖(數據鎖),用于確保數據庫數據的完全度,其中包括行級鎖(TX 鎖)、表級鎖(TM 鎖)。
2.1.2 DDL 鎖
DDL鎖(數據字典鎖),用于保護數據庫創(chuàng)建的對象的完整組成,如視圖、索引、存儲過程等。其中包排他DDL 鎖(Exclusive DDL lock)、共享DDL 鎖(Share DDL lock)、可中斷解析鎖(Breakable parse locks)。
2.2.1 行級鎖
行級鎖指對正在被修改的行進行鎖定,其他用戶可以其他沒有被鎖定的數據行。當數據庫執(zhí)行刪除、更新等操作時,會自動將該事務在表中的操作行上獲得獨占鎖。當事務啟動第一次修改時,它將獲得TX鎖(事務鎖),并將保持該鎖,直到事務被提交(COMMIT)或被回滾(ROLLBACK)。
在使用以下語句時,Oracle 會自動應用行級鎖:insert, update, delete, select…for update
2.2.2 表級鎖
表級鎖用于確保表的結構在其他事務對于進行該表操作時不會改變。當用戶對表執(zhí)行 DDL 或 DML 操作時,oracle 數據庫會自動給該表加一個表級鎖。當行級鎖被事務操作后,事務會自動繼承該行級鎖上級的表級鎖(共享鎖), 以防止其他事務生成的DDL 語句,通過DDL 操作,來影響記錄行的更新。
圖1:同時用兩個賬戶對同一條數據執(zhí)行更新
圖2:查詢當前的TX 鎖和TM 鎖
圖3:查詢object_id
圖4:scott 用戶進行回滾操作
圖5:scott 用戶回滾后查詢v$lock 視圖
表級鎖按照鎖定的強度,可以分為以下的五個類型:
(1)行共享:禁止其他的排他鎖對表進行鎖定;
(2)行排他:禁止使用除該排他鎖之外的其他共享鎖、排他鎖;
圖6:system 用戶進行回滾操作
圖7:system 用戶回滾后查詢v$lock 視圖
(3)共享鎖:對當前操作的表進行鎖定,僅允許非該用戶的其他用戶進行查詢操作,并且禁止其他用戶插入、更新和刪除行;
在出現以下條件之一時,共享鎖就會被當前所持有的事務進行釋放:
A、當事務被ROLLBACK 或COMMIT。
B、數據庫被完全退出。
C、程序被強行關閉或停止。
(4)共享排他鎖:禁止使用共享鎖,以及限制級別更高的的數據鎖;
(5)排他鎖:數據庫中所有鎖中對于權限限制最高的鎖,僅允許非當前用戶查詢該表的行。禁止修改和鎖定表。
分別采用兩個不同的賬號登錄同一數據庫,對oracle 數據庫中自帶的scott 用戶下的emp 表進行更新操作,如圖1 所示。
可以很明顯的看出,此時第二個賬戶并沒有進行update 操作,這是因為執(zhí)行update 命令時,oracle 數據庫會自動將該行數據添加行級鎖,使其他用戶無法更新該行數據。為了驗證該說法,此時查詢v$lock 視圖,如圖2 所示。
可以很明顯的看出,v$lock 視圖中,添加了關于該行語句的TX 鎖和TM 鎖,為了進一步確認上述鎖是由emp 表所產生的,我們通過查詢dba_objects 表來進行進一步的驗證,如圖3 所示。
明顯看到,該進程ID 號是由于對于dba_object 表進行加鎖所產生的,為了進一步驗證說法,此時對兩個事務均進行回滾操作,如圖4 所示。
此時可以很明顯的看出,當第一個用戶中的update 被回滾后,TX 鎖瞬間被解鎖,資源被釋放,才使得第二個用戶的update 得以成功執(zhí)行,此時查看一下v$lock 視圖,可以發(fā)現,此時TX 鎖的ID 號已經改變,且原來的ID 號已經消失,如圖5 所示。
如圖6 所示。
此時查詢v$lock 視圖,可以很明顯的發(fā)現,所有的TX 鎖和TM 鎖均已經消失,如圖7 所示。
死鎖是指在兩個或多個進程執(zhí)行過程中,由于資源競爭或通信原因而導致的阻塞現象。如果沒有外力,只能互相等待分配資源,所有的進程都無法繼續(xù)運行。
在兩個或多個任務中,如果每個任務都互相對于其他已經被試圖鎖定的任務進行了加鎖的操作,此時這些任務會互相等待對方進行資源分配,造成互相之間影響的阻塞現象,因此產生了死鎖。例如:事務A 對于行 1 的共享鎖進行獲取。事務 B 對于行 2 的共享鎖進行獲取。此時事務A,因為等待事務B 完成并釋放事務A 對于行2現有的共享鎖,從而產生了排他鎖,此時事務B,因為等待事務A完成并釋放事務B 對于行2 現有的共享鎖,從而也產生了排他鎖。但是由于事務A 等待事務B 完成之后才能進行釋放該行級鎖,事務B 也在等待事務A 完成之后才能釋放該行級鎖,兩個事務互相阻塞,產生了閉環(huán),所以造成了死鎖。這就是死鎖中的循環(huán)依賴:事務 A 和事務B 之間相互依賴,從而產生了閉環(huán),導致了死鎖的產生。
根據Oracle 數據庫的機制,該數據庫會自動發(fā)現數據庫中產生的死鎖,并通過破壞死鎖條件之一進行釋放部分資源,從而對某個事務的全部鎖進行釋放,或直接消除代價最小的事務,從而可以使其他單位的事務繼續(xù)運行。
(1)在UPDATE 和DELETE 后,應及時的進行COMMIT 或ROLLBACK 操作,以免表或行的鎖定時間過長,造成死鎖。
(2)當多個事務同時對于某個數據表進行操作時,此時不要使用共享鎖。相反,請使用共享更新鎖,以便其他用戶可以使用行級鎖來提高并行性。
(3)在高應用程序負載期間不適合修改相關的數據結構(表,視圖,觸發(fā)器,存儲過程等)。
Oracle 數據庫之所以能成為全世界最廣泛使用的數據庫之一,原因之一就是因為它對于事務的原子性、一致性、隔離性、持久性的保障,而鎖是oracle 數據庫為了確保數據的一致性、實現并發(fā)控制的非常重要的技術。在日常oracle 數據庫的維護和開發(fā)中,要深刻理解鎖的概念,并確保開發(fā)過程中不要出現死鎖,這樣才能確保數據更加健壯、穩(wěn)定。