1. 程式人生 > >Mysql 鎖表 for update (引擎/事務)

Mysql 鎖表 for update (引擎/事務)

不支持 所有 很好 war from pan data 獨立 模式

因為之前用過oracle,知道利用select * for update 可以鎖表。所以很自然就想到在mysql中能不能適應for update來鎖表呢。

學習參考如下

由於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<>&apos;3&apos; FOR UPDATE;
例4: (主鍵不明確,table lock)
SELECT * FROM products WHERE id LIKE &apos;3&apos; FOR UPDATE;
註1: FOR UPDATE僅適用於InnoDB,且必須在交易區塊(BEGIN/COMMIT)中才能生效。
註2: 要測試鎖定的狀況,可以利用MySQL的Command Mode ,開二個視窗來做測試。

由上面的InnoDB 已經交易區塊引出兩個問題。

1. what is InnoDB?

MySQL是我們比較常用的一種數據庫軟件。它有著諸多的優點,如開源的,免費的等等。其實它還有一個很好的特點,那就是有多種引擎可以供你選擇。如果賽車手能根據不同的路況,地形隨手更換與之最適宜的引擎,那麽他們將創造奇跡。然而目前他們還做不到那樣便捷的更換引擎,但是我們卻可以!
所謂知己知彼方可百戰不殆,要想將它們發揮到極致,首先我們應該來認識一下MySQL提供給我們的這幾種引擎。
一般來說,MySQL有以下幾種引擎:ISAM、MyISAM、HEAP、InnoDB和Berkley(BDB)。註意:不同的版本支持的引擎是有差異的。

進一步:

如何查看MySQL的當前存儲引擎?

一般情況下,mysql會默認提供多種存儲引擎,你可以通過下面的查看:

看你的mysql現在已提供什麽存儲引擎:
mysql> show engines;

以上說明我的mysql默認使用的InnoDB引擎,並且支持MyISAM,memory,archive,Mrg_myisam。

後面還跟著解釋, InnoDB 的解釋是:支持事務,行級別鎖定,外鍵。

看你的mysql當前默認的存儲引擎:
mysql> show variables like &apos;%storage_engine%&apos;;

你要看某個表用了什麽引擎(在顯示結果裏參數engine後面的就表示該表當前用的存儲引擎):
mysql> show create table 表名;

實這是一定的,因為我的mysql引擎就是InnoDB,默認情況下創建的表當前也是以InnoDB為引擎的嘍

2. what is 交易區塊?

參考:http://hi.baidu.com/cuihu0706/blog/item/1dd6ccb1621c355709230278.html

事務處理在各種管理系統中都有著廣泛的應用,比如人員管理系統,很多同步數據庫操作大都需要用到事務處理。比如說,在人員管理系統中,你刪除一個人員,你即需要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等等,這樣,這些數據庫操作語句就構成一個事務!
刪除的SQL語句
delete from userinfo where ~~~
delete from mail where ~~
delete from article where~~
~~
如果沒有事務處理,在你刪除的過程中,假設出錯了,只執行了第一句,那麽其後果是難以想象的!
但用事務處理。如果刪除出錯,你只要rollback就可以取消刪除操作(其實是只要你沒有commit你就沒有確實的執行該刪除操作) 一般來說,在商務級的應用中,都必須考慮事務處理的!

MYSQL數據庫從4.1就開始支持事務功能,據說5.0將引入存儲過程^_^
先簡單介紹一下事務吧!事務是DBMS得執行單位。它由有限得數據庫操作序列組成得。但不是任意得數據庫操作序列都能成為事務。一般來說,事務是必須滿足4個條件(ACID)
原子性(Autmic):事務在執行性,要做到“要麽不做,要麽全做!”,就是說不允許事務部分得執行。即使因為故障而使事務不能完成,在rollback時也要消除對數據庫得影響!
一致性(Consistency):事務得操作應該使使數據庫從一個一致狀態轉變倒另一個一致得狀態!就拿網上購物來說吧,你只有即讓商品出庫,又讓商品進入顧客得購物籃才能構成事務!
隔離性(Isolation):如果多個事務並發執行,應象各個事務獨立執行一樣!
持久性(Durability):一個成功執行得事務對數據庫得作用是持久得,即使數據庫應故障出錯,也應該能夠恢復!

MYSQL的事務處理主要有兩種方法。
1、用begin,rollback,commit來實現
begin 開始一個事務
rollback 事務回滾
commit 事務確認
2、直接用set來改變mysql的自動提交模式
MYSQL默認是自動提交的,也就是你提交一個QUERY,它就直接執行!我們可以通過
set autocommit=0 禁止自動提交
set autocommit=1 開啟自動提交
但註意當你用 set autocommit=0 的時候,你以後所有的SQL都將做為事務處理,直到你用commit確認或rollback結束,註意當你結束這個事務的同時也開啟了個新的事務!按第一種方法只將當前的作為一個事務!個人推薦使用第一種方法!
MYSQL中只有INNODB和BDB類型的數據表才能支持事務處理!其他的類型是不支持的!(切記!)

MYSQL5.0 WINXP下測試通過~ ^_^

mysql> use test;
Database changed
mysql> CREATE TABLE `dbtest`(
-> id int(4)
-> )
TYPE=INNODB;
Query OK, 0 rows affected, 1 warning (0.05 sec)

mysql> select * from dbtest
-> ;
Empty set (0.01 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into dbtest value(5);
Query OK, 1 row affected (0.00 sec)

mysql> insert into dbtest value(6);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from dbtest;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into dbtest values(7);
Query OK, 1 row affected (0.00 sec)

mysql> rollback; //這裏回滾了
Query OK, 0 rows affected (0.00 sec)

mysql> select * from dbtest;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.00 sec)

mysql>

既然已經知道了相關的知識,那麽下面就用for update來鎖定行,進行試驗

以上例中student表為例,

1. 使用begin開始一個事務

2. 利用select * for update 鎖定行,

3. 在新窗口中驗證非選中行是否被鎖定 ----未被鎖定

4. 在新窗口中驗證選中行是否被鎖定 -----鎖定,update語句在等待了一段時間後失敗。

Mysql 鎖表 for update (引擎/事務)