一、for update定義
for update是一種行級鎖,又叫排它鎖,一旦使用者對某個行施加了行級加鎖,則該使用者可以查詢也可以更新被加鎖的資料行,其它使用者只能查詢但不能更新被加鎖的資料行.如果其它使用者想更新該表中的資料行,則也必須對該錶施加行級鎖.即使多個使用者對乙個表均使用了共享更新,但也不允許兩個事務同時對乙個表進行更新,真正對錶進行更新時,是以獨佔方式鎖表,一直到提交或復原該事務為止。行鎖永遠是獨佔方式鎖。
只有當出現如下之一的條件,才會釋放共享更新鎖:
1、執行提交(commit)語句
2、退出資料庫(log off)
3、程式停止執行
二、概念和用法
通常情況下,select語句是不會對資料加鎖,妨礙影響其他的dml和ddl操作。同時,在多版本一致讀機制的支援下,select語句也不會被其他型別語句所阻礙。
而select … for update 語句是我們經常使用手工加鎖語句。在資料庫中執行select … for update ,大家會發現會對資料庫中的表或某些行資料進行鎖表,在mysql中,如果查詢條件帶有主鍵,會鎖行資料,如果沒有,會鎖表。
由於innodb預設是row-level lock,所以只有「明確」的指定主鍵,mysql才會執行row lock (只鎖住被選取的資料例) ,否則mysql將會執行table lock (將整個資料表單給鎖住)。
舉個例子: 假設有張表user ,裡面有 id 和 name 兩列,id是主鍵。
例1: (明確指定主鍵,並且資料真實存在,row lock)
select * from user where id=3 for update;select * from user where id=3 and name='tom' for update;
例2: (明確指定主鍵,但資料不存在,無lock)
select * from user where id=0 for update;
例3: (主鍵不明確,table lock)
select * from user where id<>3 for update;select * from user where id like '%3%' for update;
例4: (無主鍵,table lock)
select * from user where name='tom' for update;
注意:1、for update僅適用於innodb,且必須在事務處理模組(begin/commit)中才能生效。
2、要測試鎖定的狀況,可以利用mysql的command mode(命令模式) ,開兩個視窗來做測試。
3、myisam 只支援表級鎖,innerdb支援行級鎖 新增了(行級鎖/表級鎖)鎖的資料不能被其它事務再鎖定,也不被其它事務修改。是表級鎖時,不管是否查詢到記錄,都會鎖定表。
三、什麼時候需要使用for update?
借助for update語句,我們可以在應用程式的層面手工實現資料加鎖保護操作。就是那些需要業務層面資料獨佔時,可以考慮使用for update。
場景上,比如火車票訂票,在螢幕上顯示有票,而真正進行出票時,需要重新確定一下這個資料沒有被其他客戶端修改。所以,在這個確認過程中,可以使用for update。
四、for update悲觀鎖
悲觀鎖:總是假設最壞的情況,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會阻塞直到它解鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。就像for update,再比如j**a裡面的同步原語synchronized關鍵字的實現也是悲觀鎖。
樂觀鎖:顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號等機制。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,像資料庫提供的類似於write_condition機制,其實都是提供的樂觀鎖。
問 題select ** for update
必須只有主鍵才管用嗎?給定索引也不行?
像select user_id from orders where order_no = :no for update
是拿不到鎖的嗎?order_no
是唯一索引。
select user_id from orders where id = (select id from orders where order_id = :no) for update
只能這樣了嗎?
另外乙個問題:
for update是寫鎖(其他session可讀)。那還有什麼意義
a,b都同時select,獲取的資料(money)都是1,a 把money-1 update 成了 0,b把1-1也update成0。兩個都成功?
解決方案
select for update 語句只需要有索引就能工作
它會阻塞其他的語句對涉及到的記錄的修改。
money =0
如果a執行select for update, b執行select for update, b阻塞
a 修改money = 1
a commit
然後這時, b 的select for update 返回,查詢該行 money = 1
select語句for update作用
select for update語句的語法與select語句相同,只是在select語句的後面加for update nowait 子句。該語句用來鎖定特定的行 如果有where子句,就是滿足where條件的那些行 當這些行被鎖定後,其他會話可以選擇這些行,但不能更改或刪除這些行,直到該語句的事務...
空間的作用和用法
對於乙個使用者系統預設的會建立。temp undotabs user system這幾個表空間。那請問這幾個表空間各有什麼 作用呢?當學了oracle的人都會說。temp表空間是放處理的臨時資料的,比如排序操作。undotabs表空間是資料恢復時用到。user表空間是存班實資料的。但是大家有誰能真正...
Const 的作用和用法
const型別定義 指明變數或物件的值是不能被更新,引入目的是為了取代預編譯指令 常量必須被初始化 cons的作用 1 可以定義const常量 例如 const int max 100 int array max 2 便於進行型別檢查 例如 void f const int i 編譯器就會知道i是乙...