1. 程式人生 > >mysql事務,select for update,及資料的一致性處理

mysql事務,select for update,及資料的一致性處理

在MySQL的InnoDB中,預設的Tansaction isolation level 為REPEATABLE READ(可重讀)

在SELECT 的讀取鎖定主要分為兩種方式:

  SELECT ... LOCK IN SHARE MODE 

  SELECT ... FOR UPDATE

  這兩種方式在事務(Transaction) 進行當中SELECT 到同一個資料表時,都必須等待其它事務資料被提交(Commit)後才會執行。

  而主要的不同在於LOCK IN SHARE MODE 在有一方事務要Update 同一個表單時很容易造成死鎖。

  簡單的說,如果SELECT 後面若要UPDATE 同一個表單,最好使用SELECT ... UPDATE。

  舉個例子:

  假設商品表單products 內有一個存放商品數量的quantity ,在訂單成立之前必須先確定quantity 商品數量是否足夠(quantity>0) ,然後才把數量更新為1。程式碼如下:

SELECT quantity FROM products WHERE id=3; UPDATE products SET quantity = 1 WHERE id=3;

為什麼不安全呢?
少量的狀況下或許不會有問題,但是大量的資料存取「鐵定」會出問題。如果我們需要在quantity>0 的情況下才能扣庫存,假設程式在第一行SELECT 讀到的quantity 是2 ,看起來數字沒有錯,但
是當MySQL 正準備要UPDATE 的時候,可能已經有人把庫存扣成0 了,但是程式卻渾然不知,將錯就錯的UPDATE 下去了。因此必須透過的事務機制來確保讀取及提交的資料都是正確的。

於是我們在MySQL 就可以這樣測試,程式碼如下:

SET AUTOCOMMIT=0; BEGIN WORK; SELECT quantity FROM products WHERE id=3 FOR UPDATE;

此時products 資料中id=3 的資料被鎖住(注3),其它事務必須等待此次事務 提交後才能執行
SELECT * FROM products WHERE id=3 FOR UPDATE 如此可以確保quantity 在別的事務讀到的數字是正確的。

UPDATE products SET quantity = '1' WHERE id=3 ; COMMIT WORK;

提交(Commit)寫入資料庫,products 解鎖。
注1: BEGIN/COMMIT 為事務的起始及結束點,可使用二個以上的MySQL Command 視窗來互動觀察鎖定的狀況。
注2: 在事務進行當中,只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一筆資料時會等待其它事務結束後才執行,一般SELECT ... 則不受此影響。
注3: 由於InnoDB 預設為Row-level Lock,資料列的鎖定可參考這篇。
注4: InnoDB 表單儘量不要使用LOCK TABLES 指令,若情非得已要使用,請先看官方對於InnoDB 使用LOCK TABLES 的說明,以免造成系統經常發生死鎖。

MySQL SELECT ... FOR UPDATE 的Row Lock 與Table Lock
上面介紹過SELECT ... FOR UPDATE 的用法,不過鎖定(Lock)的資料是判別就得要注意一下了。由於InnoDB 預設是Row-Level Lock,所以只有「明確」的指定主鍵,MySQL 才會執行Row lock (只鎖住被選取的資料) ,否則MySQL 將會執行Table Lock (將整個資料表單給鎖住)。

舉個例子:
假設有個表單products ,裡面有id 跟name 二個欄位,id 是主鍵。
例1: (明確指定主鍵,並且有此資料,row lock)

SELECT * FROM products WHERE id='3' FOR UPDATE;

例2: (明確指定主鍵,若查無此資料,無lock)

SELECT * FROM products WHERE id='-1' FOR UPDATE;

例2: (無主鍵,table lock)

SELECT * FROM products WHERE name='Mouse' FOR UPDATE;

例3: (主鍵不明確,table lock)

SELECT * FROM products WHERE id<>'3' FOR UPDATE;

例4: (主鍵不明確,table lock)

SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;


樂觀所和悲觀鎖策略
悲觀鎖:在讀取資料時鎖住那幾行,其他對這幾行的更新需要等到悲觀鎖結束時才能繼續 。
樂觀所:讀取資料時不鎖,更新時檢查是否資料已經被更新過,如果是則取消當前更新,一般在悲觀鎖的等待時間過長而不能接受時我們才會選擇樂觀鎖。

相關推薦

mysql事務select for update資料一致性處理

在MySQL的InnoDB中,預設的Tansaction isolation level 為REPEATABLE READ(可重讀) 在SELECT 的讀取鎖定主要分為兩種方式:   SELECT ... LOCK IN SHARE MODE    SELECT ... FOR UPDATE   這兩

mysql事務select for update數據的一致性處理

use tro where strong 結束 mysql事務 mode evel 簡單的 在MySQL的InnoDB中,預設的Tansaction isolation level 為REPEATABLE READ(可重讀) 在SELECT 的讀取鎖定主要分為兩種方式:

【轉載】MySQL事務以及SELECT ... FOR UPDATE的使用

商品 tail ase -a base 我們 evel erl tel MySQL中的事務,默認是自動提交的,即autocommit = 1; 但是這樣的話,在某些情形中就會出現問題:比如: 如果你想一次性插入了1000條數據,mysql會commit1000次的, 如果我

MySQL事務以及select...for update

舉個例子: 假設有個表單products ,裡面有id 跟name 二個欄位,id 是主鍵。 例1: (明確指定主鍵,並且有此資料,row lock) SELECT * FROM products WHERE id='3' FOR UPDATE; 例2: (明確指定主鍵,若查無此資料,無lock) SELEC

Oracle編輯數據時提示:這些查詢結果不可更新請使用ROWI或者SELECT……FOR UPDATE獲得可更新結果

對數 date 一個 更新 bsp ron 我們 pda from 我們在對Oracle數據庫進行操作時,有時會在查詢完結果後想要對其中的某些數據進行操作,當我們點擊編輯(一個鎖標誌)是,會提示我們上述問題中的錯誤:這些查詢結果不可更新,請使用ROWI或者SELECT……F

Mysql加鎖過程詳解(4)-select for update/lock in share mode 對事務並發性影響

per inno targe 允許 evel transacti 修改 not null warn select for update/lock in share mode 對事務並發性影響 事務並發性理解 事務並發性,粗略的理解就是單位時間內能夠執行的事務數量,常見的單

mysql事務和鎖 SELECT FOR UPDATE

事務:當然有的人用begin /begin work .推薦用START TRANSACTION 是SQL-99標準啟動一個事務。 start transaction #開始一個事務 操作 savepoint sp1 #儲存點名稱 操作 ROLLBACK ROLLBACK To sp1

ORACLE中更新資料PLSQL Developer中SELECT ... FOR UPDATESELECT T.*,ROWID的區別

背景:ORACLE中更新少量資料時,在PLSQL  Developer中,一般用的語句是SELECT   FOR   UPDATE和SELECT   T.*,ROWID,這倆語句執行之後可以手動在查詢出來的資料中修改。例項背景:表名A,資料如下:  ACOL1    COL2

數據庫:Mysql中“select ... for update”排他鎖分析

nbsp 檢索 語句 mit AI pda 兩種 訪問 upd Mysql InnoDB 排他鎖 用法: select … for update; 例如:select * from goods where id = 1 for update; 排他鎖的申

mysql lock in share mode 和 select for update

原文連結:http://blog.csdn.net/d6619309/article/details/52688250 工作需要,接觸到以下兩個MySQL sql語法: select lock in share mode select for update 1

Mysqlselect for update 的幾種情況

悲觀鎖是對資料被的修改持悲觀態度(認為資料在被修改的時候一定會存在併發問題),因此在整個資料處理過程中將資料鎖定。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在應用層中實現了加鎖機制,也無法保證外部系統不會修改資料)。 使用場景舉例

mybatis 使用for update資料進行行級鎖定

與Spring Date JPA中使用行級鎖一樣,都需要加上事務,並在查詢的時候加上for update。直接上程式碼: 資料庫表: create table t_pub_student( id int PRIMARY key auto_increment, code

MySql資料庫MySQLselect * for update鎖表的問題

       由於InnoDB預設是Row-Level Lock,所以只有「明確」的指定主鍵,MySQL才會執行Row lock (只鎖住被選取的資料例) ,否則MySQL將會執行Table Lock (將整個資料表單給鎖住)。 舉個例子: 假設有個表單p

MySQLselect * for update鎖表的範圍

MySQL中select * for update鎖表的問題 由於InnoDB預設是Row-Level Lock,所以只有「明確」的指定主鍵,MySQL才會執行Row lock (只鎖住被選取的資料例) ,否則MySQL將會執行Table Lock (將整個資料表單給鎖住)。 舉個例子: 假設有個表單p

[MySQL] 行級鎖SELECT ... LOCK IN SHARE MODE 和 SELECT ... FOR UPDATE

一、譯文 If you query data and then insert or update related data within the same transaction, the regular SELECT statement does not

【SQLServer併發問題SELECTUPDATE避免併發髒讀情況解決】

在SQL Server中,需要對資料操作進行先SELECT 之後UPDATE,對於這樣的操作,如果出現高併發,可能導致髒讀情況的發生。不能保證資料的同步。 解決方案是在事物中對錶進行加更新鎖: 事務一

資料庫:Mysql中“select ... for update”排他鎖分析

Mysql InnoDB 排他鎖 用法: select … for update; 例如:select * from goods where id = 1 for update; 排他鎖的申請前提:沒有執行緒對該結果集中的任何行資料使用排他鎖或共享鎖,否則

select for update引發死鎖分析

而在 back ons 關系 級別 分析 得到 ica 分享 本文針對MySQL中在Repeatable Read的隔離級別下使用select for update可能引發的死鎖問題進行分析。 1. 案例 業務中需要對各種類型的實體進行編號,例如對於x類實體的編號可能是x2

Java基礎-----jdk1.5新特性(靜態匯入增強for迴圈列舉)

package cn.itcast.jdk15; /*      Jdk1.5新特性之-----靜態匯入    靜態匯入的作用:簡化書寫。  靜態匯入可以作用於一個類的所有成員  靜態沒匯入的格式:

深入理解SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE

概念和區別 SELECT ... LOCK IN SHARE MODE走的是IS鎖(意向共享鎖),即在符合條件的rows上都加了共享鎖,這樣的話,其他session可以讀取這些記錄,也可以繼續新增IS鎖,但是無法修改這些記錄直到你這個加鎖的session執行完成(否則直接鎖等待超時)。 SELE