mysql触发器行锁_MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁
需求: 有一個賬戶,兩個人在同一時間要對此賬戶操作,A要對賬戶充值100塊,B要從賬戶中取出100塊.操作前都要先看一下賬戶的 余額然后再操作.
--窗口1 用戶進行充值
--充值前 先查看余額
set @m=0;SELECT money into @m from account where id = 1;select @m;--看到余額后 充值100 塊
update account set money = @m + 100 where id = 1;SELECT * fromaccount;----------------------------------------------------------------窗口2 用戶進行取款
--取款前 先查看余額
set @m=0;SELECT money into @m from account where id = 1;select @m;--看到余額后 取款100 塊
update account set money = @m - 100 where id = 1;SELECT * from account;
示例
1.鎖的基本概念
當并發(fā)事務(wù)同時訪問一個資源時,有可能導致數(shù)據(jù)不一致,因此需要一種機制來將數(shù)據(jù)訪問順序化,以保證數(shù)據(jù)庫數(shù)據(jù)的一致性。
2.鎖的基本類型
多個事務(wù)同時讀取一個對象的時候,是不會有沖突的。同時讀和寫,或者同時寫才會產(chǎn)生沖突。因此為了提高數(shù)據(jù)庫的并發(fā)性能,通常會定義兩種鎖:共享鎖和排它鎖。
2.1共享鎖(Shared Lock,也叫S鎖)
共享鎖(S)表示對數(shù)據(jù)進行讀操作。因此多個事務(wù)可以同時為一個對象加共享鎖。(如果試衣間的門還沒被鎖上,顧客都能夠同時進去參觀)
2.2排他鎖(Exclusive Lock,也叫X鎖)
排他鎖(X)表示對數(shù)據(jù)進行寫操作。如果一個事務(wù)對 對象加了排他鎖,其他事務(wù)就不能再給它加任何鎖了。(某個顧客把試衣間從里面反鎖了,其他顧客想要使用這個試衣間,就只有等待鎖從里面給打開了).
3. 實際開發(fā)中常見的兩種鎖:
3.1悲觀鎖?顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時候都認為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)就會block(阻塞)直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫里邊就用到了很多這種鎖機制.
注意:要使用悲觀鎖,我們必須關(guān)閉mysql數(shù)據(jù)庫的自動提交屬性.因為MySQL默認使用autocommit模式,也就是說,當你執(zhí)行一個更新操作后,MySQL會立刻將結(jié)果進行提交。關(guān)閉自動提交命令為:set autocommit=0;
設(shè)置完autocommit后,我們就可以執(zhí)行我們的正常業(yè)務(wù)了。具體如下:
-- 0.開始事務(wù)
start transaction;
-- 1.查詢賬戶余額
set @m = 0; -- 賬戶余額
select money into @m from account where id = 1 for update;
select @m;
-- 2.修改賬戶余額
update account set money = @m -100 where id = 1;
select * FROM account where id = 1;
-- 3. 提交事務(wù)
commit;
在另外的查詢頁面執(zhí)行:
-- 0.開始事務(wù)
start transaction;
-- 1.查詢賬戶余額
set @m = 0; -- 賬戶余額
select money into @m from account where id = 1 for update;
select @m;
-- 2.修改賬戶余額
update account set money = @m +100 where id = 1;
select * FROM account where id = 1;
-- 3. 提交事務(wù)
commit;
會發(fā)現(xiàn)當前查詢會進入到等待狀態(tài),不會顯示出數(shù)據(jù),當上面的sql執(zhí)行完畢提交事物后,當前sql才會顯示結(jié)果.
注意1:在使用悲觀鎖時,如果表中沒有指定主鍵,則會進行鎖表操作.
注意2:?悲觀鎖的確保了數(shù)據(jù)的安全性,在數(shù)據(jù)被操作的時候鎖定數(shù)據(jù)不被訪問,但是這樣會帶來很大的性能問題。因此悲觀鎖在實際開發(fā)中使用是相對比較少的。
3.2?樂觀鎖, 顧名思義,就是很樂觀,每次去拿數(shù)據(jù)的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數(shù)據(jù),可以使用版本號等機制。
使用樂觀鎖的兩種方式:
1.使用數(shù)據(jù)版本(Version)記錄機制實現(xiàn),這是樂觀鎖最常用的一種實現(xiàn) 方式。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個版本標識,一般是通過為數(shù)據(jù)庫表增加一個數(shù)字類型的 “version” 字段來實現(xiàn)。當讀取數(shù)據(jù)時,將version字段的值一同讀出,數(shù)據(jù)每更新一次,對此version值加一。當我們提交更新的時候,判斷數(shù)據(jù)庫表對應(yīng)記錄 的當前版本信息與第一次取出來的version值進行比對,如果數(shù)據(jù)庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期數(shù) 據(jù)。
代碼示例:
-- 1.查詢賬戶余額
set @m = 0; -- 賬戶余額
select money into @m from account where id = 1 ;
select @m;
-- 2.查詢版本號
set @version = 0; -- 版本號
select version into @version from account where id = 1 ;
select @version;
-- 3.修改賬戶余額
update account set money = @m -100,version=version+1 where id = 1 and version = @version;
select * FROM account where id = 1;
2.樂觀鎖定的第二種實現(xiàn)方式和第一種差不多,同樣是在需要樂觀鎖控制的table中增加一個字段,名稱無所謂,字段類型使用時間戳 (datatime), 和上面的version類似,也是在更新提交的時候檢查當前數(shù)據(jù)庫中數(shù)據(jù)的時間戳和自己更新前取到的時間戳進行對比,如果一致則OK,否則就是版本沖突。
悲觀鎖與樂觀鎖的優(yōu)缺點:
兩種鎖各有其有點缺點,不能單純的講哪個更好.
樂觀鎖適用于寫入比較少的情況下,即沖突真的很少發(fā)生的時候,這樣可以省去了鎖的開銷,加大了系統(tǒng)的整個吞吐量。
但如果經(jīng)常產(chǎn)生沖突,上層應(yīng)用會不斷的進行重試操作,這樣反倒是降低了性能,所以這種情況下用悲觀鎖就比較合適.
總結(jié)
以上是生活随笔為你收集整理的mysql触发器行锁_MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 字符列做日期分区_mysql
- 下一篇: mysql 代码怎么优化_MySQL 性