前言部分,我們引出了鎖。讀寫和寫寫之間可能都需要加鎖,但是讀讀之間是不需要的。 有沒有什麼想法,我們前幾天才看了reentrantreadwritelock的實現,資料庫其實跟它差不了太多。
在資料庫中,讀操作需要獲取共享鎖(shared locks),一般簡稱為s鎖;寫操作需要獲取獨佔鎖(exclusive locks),一般簡稱為x鎖。而且鎖之間的互斥關係跟 reentrantreadwritelock 也可以說基本一致,只是這裡不存在重入次數,將執行緒的概念換成了事務。
相容性xsx
不相容不相容
s不相容
相容鎖定讀
上邊介紹完了鎖,我們其實可以發現如果按上邊所說,仍然不能解決銀行存錢場景中的,事務1獲取s鎖讀取了資料,此時事務2仍然可以獲取事務的s鎖繼續讀取,那麼,我們就在讀取記錄時獲取該記錄的x鎖。上述兩種不同的讀取加鎖方式的實現分別如下
select ... lock in share mode;
這是讀取時獲取s鎖
select ... for update
這樣讀取後會為讀取到的記錄加x鎖
寫操作delete
先獲取指定記錄的x鎖,再進行刪除標記(應該了解不會刪除記錄而只是打標記吧~
update
更新如果更新了記錄的鍵值對需要先獲取x鎖刪掉記錄再進行insert新紀錄;沒變鍵值對的話直接獲取x鎖進行原地修改
insert
隱式鎖,既不是s鎖也不是x鎖。
上邊說了針對記錄的行鎖,同樣還有表鎖,其實相對於行鎖,無非就是作用範圍變大了,由單條記錄變為了整個表,除此之外的相容性規則完全一樣。不過注意表鎖和行鎖間的互斥,比如乙個事務獲得整個表的s鎖,別的事務既可以獲得這個表的s鎖,也可以獲得表中某條記錄的s鎖,至於s鎖,就別想了,我們說了,規則跟上邊一樣,不再贅述。
表鎖種需要注意的只有乙個意向鎖,即如果我們想給表加x鎖,此時表任意一條記錄都能有s鎖或者x鎖,如果我們想給表加s鎖,表中任意一條記錄都不能有x鎖。那麼,問題來了,我們怎麼直到表中任意一條記錄有沒有鎖呢?
不可能遍歷吧?當然不可能,實際上是當事務準備在某條記錄加x鎖時,就會在表上加乙個ix鎖;當事務準備在某條記錄加s鎖時,就會在表上加乙個is鎖.這樣當別的事務來,一看表有ix或者is就知道這個表中的記錄有沒有x鎖或者s鎖了。ix和is只是代表表中有記錄持有x鎖或者s鎖,所以他們倆並不互斥,當然了ix和ix也不互斥。
說到表鎖,不得不提下myisam、memory這些引擎,他們都採用表鎖,而且不支援事務,是基於會話的,這種大粒度的鎖效率是非常慢的,所以這些存貯引擎一般只適用於唯讀的場景中
record locks
記錄鎖,其實就是s鎖和x鎖
gap locks
解決幻讀就在於此。這個鎖可以鎖住某條記錄和它前邊記錄之間的間隙,使得該間隙不能插入記錄。
next-key locks
不翻譯了就,作用是鎖住指定記錄及其前邊的間隙,即前兩種鎖的合體
insert intention locks
插入意向鎖,很無聊的乙個鎖。當事務被間隙鎖阻塞不能成功插入時,會在該間隙生成乙個插入意向鎖,當可以插入時便獲得插入意向鎖
隱式鎖這個挺有意思的。試想這麼乙個場景,我們剛插入乙個記錄,此時別的事務就過來要這個記錄的s鎖進行讀取或x鎖進行修改,很明顯這會造成髒讀或者髒寫問題。隱式鎖由此而來。
對於聚簇索引記錄,有乙個隱藏列trx_id,記錄著最後改動這條記錄的事務id(mvcc才說過的),很自然的,新插入的記錄的trx_id就是他自己的事務id,如果其他事務此時想獲得該記錄的s鎖或者x鎖時,會檢查trx_id代表的事務是否是當前活躍事務,如果是的話,幫助該事務建立乙個x鎖(也就是為當前事務建立⼀個鎖結構,is_waiting屬性是false),然後自己進入等待狀態(也就是為⾃⼰也創 建⼀個鎖結構,is_waiting屬性是true)。
對於二級索引,沒有trx_id屬性,但是在⼆級索引頁面的page header部分有⼀ 個page_max_trx_id屬性,該屬性代表對該⻚⾯做改動 的最大的事務id,如果page_max_trx_id屬性值⼩於 當前最小的活躍事務id,那麼說明對該⻚⾯做修改的事 務都已經提交了,否則就需要在⻚⾯中定位到對應的二級 索引記錄,然後回表找到它對應的聚簇索引記錄,然後再重複情景聚簇索引的做法。
事務id相當於加了⼀個隱式鎖。別的事務在對這條記錄加 s鎖或者x鎖時,由於隱式鎖的存在,會先幫助當前事務生成一 個鎖結構,然後⾃⼰再⽣成⼀個鎖結構後進⼊等待狀態
is和ix以及s和x前邊說過。
資料庫中我們常用的乙個主鍵自增,其實就是表鎖的乙個體現。 執行每條插入語句時都會在表上加乙個auto-inc鎖,然後為每條待插⼊記錄的 auto_increment修飾的列分配遞增的值,在該語句執 ⾏結束後,再把auto-inc鎖釋放掉。這樣⼀個事務在持 有auto-inc鎖的過程中,其他事務的插⼊語句都要被阻 塞,可以保證⼀個語句中分配的遞增值是連續的。 該鎖尤其適用於無法確定插入記錄的條數的插入
輕量級鎖
在為插⼊語句⽣ 成auto_increment修飾的列的值時獲取⼀下這個輕量 級鎖,然後⽣成本次插⼊語句需要⽤到的 auto_increment列的值之後,就把該輕量級鎖釋放 掉,並不需要等到整個插⼊語句執⾏完才釋放鎖。 即先通過輕量級鎖對auto_increment修飾的列進⾏賦值。 該鎖適用於確定要插入的記錄條數
其實很多東西都是相通的,尤其是我們前邊說過類似共享鎖和獨佔鎖的概念,這裡就很好理解其他的,也沒什麼好說的,無非就是鎖的作用範圍和時機的一些問題,多看幾遍自然就熟了
資料庫中的鎖
11.5.1 鎖的概念 鎖 lock 是在多使用者環境下對資源訪問的一種限制。機制當對乙個 11.5.1 鎖的概念 鎖 lock 是在多使用者環境下對資源訪問的一種限制。機制當對乙個資料來源加鎖後,此資料來源就有了一定的訪問限制。我們就稱對此資料來源進行了 鎖定 在sql server中,可以對以下...
資料庫中的鎖
資料庫 sql server delete 儲存database manager 11.5.1 鎖的概念 鎖 lock 是在多使用者環境下對資源訪問的一種限制。機制當對乙個 11.5.1 鎖的概念 鎖 lock 是在多使用者環境下對資源訪問的一種限制。機制當對乙個資料來源加鎖後,此資料來源就有了一定...
資料庫中的「鎖」
資料庫當中有 鎖 這個概念,什麼叫做鎖,用咱們生活當中的事物來進行描述的話,鎖就是用來鎖門,來進行保護自己的東西的乙個物品。在資料庫當中,其實也是如此,鎖的概念就是事務訪問的乙個屏障,當乙個事務對當前系統提出加鎖的時候 加鎖的物件可以是行,表,資料庫 其他事務必須等此事務解鎖之後才能進行訪問。用生活...