MySQL乐观锁、共享锁、排他锁、行锁、表锁区别和使用方法
數據庫鎖分類
| 范圍鎖 | 行鎖、表鎖 |
| 算法鎖 | 臨間鎖、間隙鎖、記錄鎖 |
| 屬性鎖 | 共享鎖(讀鎖)、排他鎖(寫鎖) |
| 狀態鎖 | 意向共享鎖、意向排他鎖 |
?
一、樂觀鎖和悲觀鎖
1.樂觀鎖介紹
樂觀鎖( Optimistic Locking ) 相對悲觀鎖而言,樂觀鎖假設認為數據一般情況下不會造成沖突,所以在數據進行提交更新的時候,才會正式對數據的沖突與否進行檢測,如果發現沖突了,則讓返回用戶錯誤的信息,讓用戶決定如何去做。那么我們如何實現樂觀鎖呢,一般來說有以下2種方式:
2.使用方法
版本號控制
版本號的實現方式有兩種,一個是數據版本機制,一個是時間戳機制。具體如下。
a.使用數據版本(Version)記錄機制實現,這是樂觀鎖最常用的一種實現方式。何謂數據版本?即為數據增加一個版本標識,一般是通過為數據庫表增加一個數字類型的 “version” 字段來實現。當讀取數據時,將version字段的值一同讀出,數據每更新一次,對此version值加一。當我們提交更新的時候,判斷數據庫表對應記錄的當前版本信息與第一次取出來的version值進行比對,如果數據庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期數據。
3.代碼實現
數據庫表新增字段version,更新修改操作時,需要比較當前版本值是否相等,相等的話,每次修改值時,將版本號version+1,同一版本的數據只能有一次提交成功,其他提交時會因為version不一致導致修改失敗
<update id="updateGoodsUseCAS" parameterType="Goods"> ?<![CDATA[?update t_goods?set status=#{status},name=#{name},version=version+1?where id=#{id} and version=#{version}?]]> ? </update> ?二、屬性鎖
MySQL常用引擎有MyISAM和InnoDB,而InnoDB是mysql默認的引擎。MyISAM不支持事務,InnoDB支持事務。MyISAM不支持行鎖,而InnoDB支持行鎖和表鎖。MyISAM在執行查詢語句(SELECT)前,會自動給涉及的所有表加讀鎖,在執行更新操作(UPDATE、DELETE、INSERT等)前,會自動給涉及的表加寫鎖,這個過程并不需要用戶干預,因此用戶一般不需要直接用LOCK TABLE命令給MyISAM表顯式加鎖
1.共享鎖(讀鎖)
共享 (S) 用于不更改或不更新數據的操作(只讀操作),多個事務對同一數據共享一把鎖。 如 SELECT 語句。如果事務T對數據A加上共享鎖后,則其他事務只能對A再加共享鎖,不能加排他鎖。獲準共享鎖的事務只能讀數據,不能修改數據。
顯示加鎖:
select * from t_activity where id=1 lock in share mode;2.排他鎖(寫鎖)
用于數據修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進行多重更新。如果事務T對數據A加上排他鎖后,則其他事務不能再對A加任何類型的鎖,包括共享鎖和排它鎖。獲準排他鎖的事務既能讀數據,又能修改數據。類似于資源鎖,只允許一個請求進來。
select * from t_activity where id=1 for update;如下所示:innodb引擎對select開啟事務,id為1的數據使用排它鎖,事務沒有結束時,其他事務不能獲取到排它鎖,提交之后就可以了
(1)可視化界面事務中使用排它鎖,命令行事物對同一行數據也獲取排它鎖
(2)事務中使用排它鎖,其他事物對同一行數據獲取共享鎖
(3)事務中使用排它鎖,提交之后,其他事物對同一行數據也獲取排它鎖
mysql InnoDB引擎默認的修改數據語句,update,delete,insert都會自動給涉及到的數據加上排他鎖,select語句默認不會加任何鎖類型
三、范圍鎖
行鎖和表鎖其實是排它鎖的兩種實現,主要用于update,delete,insert這些語句,區別在于是對是否命中索引
1.行鎖
行鎖就是鎖一行或者多行記錄,mysql的行鎖是基于索引加載的,所以行鎖是要加在索引響應的行上,即命中索引
這里的表t_activity中id是主鍵索引,在事務中沒有結束的情況下,命中索引,進行修改操作,其他事務對同一張表中的相同數據不能進行修改,必須等待事務提交完畢,釋放了行鎖,才能執行。
t_activity表數據如下所示,id為主鍵索引,credit未添加索引
可視化界面中開啟事務,修改表t_activity 的id為6的credit為10,命令行中一事物修改id為6的credit為8,因為是同一行數據,事務未提交,行鎖沒有釋放,無法進行修改 。
可視化界面中開啟事務,修改表t_activity中id=1的credit字段,不關閉事務,命令行一事物修改id=2的credit為8,成功,兩者互不影響,因為行鎖只鎖定了id=1的這一行,id為2的這一行沒有鎖住,可以正常執行
2.表鎖
表鎖就是一鎖鎖一整張表,在表被鎖定期間,其他事務不能對該表進行操作,必須等當前表的鎖被釋放后才能進行操作。表鎖響應的是非索引字段,即全表掃描,全表掃描時鎖定整張表,sql語句可以通過執行計劃看出掃描了多少條記錄。
這里在可視化界面事務中對t_activity表中非索引字段進行修改,命令行事務中任意修改表數據,會導致修改失敗,因為鎖定了整張表
事務提交完畢后,釋放了表鎖,其他事物就可以修改表中任意數據了
總結
以上是生活随笔為你收集整理的MySQL乐观锁、共享锁、排他锁、行锁、表锁区别和使用方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring 通过Java Config
- 下一篇: SpringBoot+Junt+Mock