悲觀鎖和樂觀鎖使用場景
樂觀鎖是在應用層加鎖,而悲觀鎖是在數據庫層加鎖(for update)
樂觀鎖顧名思義就是在操做時很樂觀,這數據只有我在用,我先儘管用,最後發現不行時就回滾。
悲觀鎖在操做時很悲觀,生怕數據被其餘人更新掉,我就先將其先鎖住,讓別人用不了,我操做完成後再釋放掉。
悲觀鎖須要數據庫級別上的的實現,程序中是作不到的,若是在長事務環境中,數據會一直被鎖住,致使併發性能大大地下降。
通常來講若是併發量很高的話,建議使用悲觀鎖,不然的話就使用樂觀鎖。
若是併發量很高時使用樂觀鎖的話,會致使不少的併發事務回滾、操做失敗。
總之,衝突概率大用悲觀,小就用樂觀。
悲觀鎖通常是用於併發不是很高,而且不容許髒讀等狀況。可是對數據庫資源消耗較大
悲觀鎖
當一個事務鎖定了一些數據以後,只有噹噹前鎖提交了事務,釋放了鎖,其餘事務才能得到鎖並執行操做
使用方式以下:
首先要關閉MySQL的自動提交:set autocommit = 0;
這裏使用select for update的方式利用數據庫開啓了悲觀鎖,鎖定了id=1的這條數據(注意:這裏除非是使用了索引會啓用行級鎖,否則是會使用表鎖,將整張表都鎖住。)。
以後使用commit提交事務並釋放鎖,這樣下一個線程過來拿到的就是正確的數據。
悲觀鎖通常是用於併發不是很高,而且不容許髒讀等狀況。可是對數據庫資源消耗較大。
咱們可使用命令設置MySQL爲非autocommit模式
set autocommit=0;
//0.開始事務
begin;/begin work;/start transaction; (三者選一就能夠)
//1.查詢出商品信
select status from t_goods where id = #{id} for update;
//2.根據商品信息生成訂單
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status爲2
update t_goods set status=2;
//4.提交事務
commit;/commit work;
樂觀鎖
一般的實現方式增長一個version字段,爲每一條數據加上版本。每次更新的時候version+1,而且更新時候帶上版本號。實現方式以下:
版本號(version)
UPDATE price_version
SET front = #{front,jdbcType=DECIMAL},
version= version + 1
WHERE id = #{id,jdbcType=INTEGER}
AND version = #{version,jdbcType=INTEGER}數據庫