mysql樂觀鎖是什麼?
mysql樂觀鎖是相對悲觀鎖而言,樂觀鎖假設認為資料一般情況下不會造成衝突,所以在資料進行提交更新的時候,才會正式對資料的衝突與否進行偵測,如果發現衝突了,則讓傳回使用者錯誤的訊息,讓使用者決定如何做。
mysql樂觀鎖是( Optimistic Locking )相對悲觀鎖定而言,樂觀鎖定假設認為資料一般情況下不會造成衝突,所以在資料進行提交更新的時候,才會正式對資料的衝突與否進行檢測,如果發現衝突了,則讓返回使用者錯誤的訊息,讓使用者決定如何做。
那麼我們要如何實現樂觀鎖呢,一般來說有以下2種方式:
#1、使用資料版本(Version)記錄機制實作,這是樂觀鎖最常用的一種實作方式。何謂數據版本?即為資料增加一個版本標識,一般是透過為資料庫表增加一個數字類型的 “version” 字段來實現。當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加一。
當我們提交更新的時候,判斷資料庫表對應記錄的當前版本資訊與第一次取出的version值進行比對,如果資料庫表目前版本號與第一次取出的version值相等,則予以更新,否則認為是過期資料。用下面的一張圖來說明:
如如上圖所示,如果更新操作順序執行,則資料的版本(version)依序遞增,不會產生衝突。但如果發生有不同的業務操作對同一版本的資料進行修改,那麼,先提交的操作(圖中B)會把資料version更新為2,當A在B之後提交更新時發現資料的version已經被修改了,那麼A的更新操作會失敗。
2、樂觀鎖定的第二種實作方式和第一種差不多,同樣是在需要樂觀鎖定控制的table中增加一個字段,名稱無所謂,欄位類型使用時間戳記(timestamp), 和上面的version類似,也是在更新提交的時候檢查當前資料庫中資料的時間戳記和自己更新前取到的時間戳進行對比,如果一致則OK,否則就是版本衝突。
相關學習推薦:mysql影片教學
#使用範例:
以 MySQL InnoDB
為例
還是拿之前的實例來舉:商品goods表中有一個字段status,status為1代表商品未被下單,status為2代表商品已經下單,那麼我們對某個商品下單時必須確保該商品status為1。假設商品的id為1。
下單操作包含3步驟:
1、查詢出商品資訊
select (status,status,version) from t_goods where id=#{id}
2、根據商品資訊產生訂單
3、修改商品status為2
update t_goods set status=2,version=version+1 where id=#{id} and version=#{version};
那麼為了使用樂觀鎖,我們先修改t_goods表,增加一個version字段,資料預設version值為1。
t_goods
表初始資料如下:
mysql> select * from t_goods; +----+--------+------+---------+ | id | status | name | version | +----+--------+------+---------+ | 1 | 1 | 道具 | 1 | | 2 | 2 | 装备 | 2 | +----+--------+------+---------+ 2 rows in set mysql>
對於樂觀鎖定的實現,我使用MyBatis來進行實踐,具體如下:
Goods實體類別:
/** * ClassName: Goods <br/> * Function: 商品实体. <br/> * date: 2013-5-8 上午09:16:19 <br/> * @author chenzhou1025@126.com */ public class Goods implements Serializable { /** * serialVersionUID:序列化ID. */ private static final long serialVersionUID = 6803791908148880587L; /** * id:主键id. */ private int id; /** * status:商品状态:1未下单、2已下单. */ private int status; /** * name:商品名称. */ private String name; /** * version:商品数据版本号. */ private int version; @Override public String toString(){ return "good id:"+id+",goods status:"+status+",goods name:"+name+",goods version:"+version; } //setter and getter }
GoodsDao
/** * updateGoodsUseCAS:使用CAS(Compare and set)更新商品信息. <br/> * * @author chenzhou1025@126.com * @param goods 商品对象 * @return 影响的行数 */ int updateGoodsUseCAS(Goods goods);
mapper.xml
<update id="updateGoodsUseCAS" parameterType="Goods"> <![CDATA[ update t_goods set status=#{status},name=#{name},version=version+1 where id=#{id} and version=#{version} ]]> </update>
#GoodsDaoTest測試類
@Test public void goodsDaoTest(){ int goodsId = 1; //根据相同的id查询出商品信息,赋给2个对象 Goods goods1 = this.goodsDao.getGoodsById(goodsId); Goods goods2 = this.goodsDao.getGoodsById(goodsId); //打印当前商品信息 System.out.println(goods1); System.out.println(goods2); //更新商品信息1 goods1.setStatus(2);//修改status为2 int updateResult1 = this.goodsDao.updateGoodsUseCAS(goods1); System.out.println("修改商品信息1"+(updateResult1==1?"成功":"失败")); //更新商品信息2 goods1.setStatus(2);//修改status为2 int updateResult2 = this.goodsDao.updateGoodsUseCAS(goods1); System.out.println("修改商品信息2"+(updateResult2==1?"成功":"失败")); }
輸出結果:
good id:1,goods status:1,goods name:道具,goods version:1 good id:1,goods status:1,goods name:道具,goods version:1 修改商品信息1成功 修改商品信息2失败
說明:
在GoodsDaoTest
測試方法中,我們同時查出同一個版本的數據,賦給不同的goods對象,然後先修改good1對象然後執行更新操作,執行成功。然後我們修改goods2,執行更新操作時提示操作失敗。此時t_goods
表中資料如下:
mysql> select * from t_goods; +----+--------+------+---------+ | id | status | name | version | +----+--------+------+---------+ | 1 | 2 | 道具 | 2 | | 2 | 2 | 装备 | 2 | +----+--------+------+---------+ 2 rows in set mysql>
我們可以看到 id為1的資料version已經在第一次更新時修改為2了。所以我們更新good2時update where條件已經不匹配了,所以更新不會成功,具體sql如下:
update t_goods set status=2,version=version+1 where id=#{id} and version=#{version};
這樣我們就實現了樂觀鎖。
以上是mysql樂觀鎖是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

MySQL適合初學者使用,因為它安裝簡單、功能強大且易於管理數據。 1.安裝和配置簡單,適用於多種操作系統。 2.支持基本操作如創建數據庫和表、插入、查詢、更新和刪除數據。 3.提供高級功能如JOIN操作和子查詢。 4.可以通過索引、查詢優化和分錶分區來提升性能。 5.支持備份、恢復和安全措施,確保數據的安全和一致性。

MySQL是一個開源的關係型數據庫管理系統。 1)創建數據庫和表:使用CREATEDATABASE和CREATETABLE命令。 2)基本操作:INSERT、UPDATE、DELETE和SELECT。 3)高級操作:JOIN、子查詢和事務處理。 4)調試技巧:檢查語法、數據類型和權限。 5)優化建議:使用索引、避免SELECT*和使用事務。

使用 Navicat Premium 創建數據庫:連接到數據庫服務器並輸入連接參數。右鍵單擊服務器並選擇“創建數據庫”。輸入新數據庫的名稱和指定字符集和排序規則。連接到新數據庫並在“對象瀏覽器”中創建表。右鍵單擊表並選擇“插入數據”來插入數據。

可以通過以下步驟打開 phpMyAdmin:1. 登錄網站控制面板;2. 找到並點擊 phpMyAdmin 圖標;3. 輸入 MySQL 憑據;4. 點擊 "登錄"。

MySQL和SQL是開發者必備技能。 1.MySQL是開源的關係型數據庫管理系統,SQL是用於管理和操作數據庫的標準語言。 2.MySQL通過高效的數據存儲和檢索功能支持多種存儲引擎,SQL通過簡單語句完成複雜數據操作。 3.使用示例包括基本查詢和高級查詢,如按條件過濾和排序。 4.常見錯誤包括語法錯誤和性能問題,可通過檢查SQL語句和使用EXPLAIN命令優化。 5.性能優化技巧包括使用索引、避免全表掃描、優化JOIN操作和提升代碼可讀性。

可在 Navicat 中通過以下步驟新建 MySQL 連接:打開應用程序並選擇“新建連接”(Ctrl N)。選擇“MySQL”作為連接類型。輸入主機名/IP 地址、端口、用戶名和密碼。 (可選)配置高級選項。保存連接並輸入連接名稱。

在 Navicat 中執行 SQL 的步驟:連接到數據庫。創建 SQL 編輯器窗口。編寫 SQL 查詢或腳本。單擊“運行”按鈕執行查詢或腳本。查看結果(如果執行查詢的話)。

Navicat 連接數據庫時常見的錯誤及解決方案:用戶名或密碼錯誤(Error 1045)防火牆阻止連接(Error 2003)連接超時(Error 10060)無法使用套接字連接(Error 1042)SSL 連接錯誤(Error 10055)連接嘗試過多導致主機被阻止(Error 1129)數據庫不存在(Error 1049)沒有權限連接到數據庫(Error 1000)
