實現資料庫鎖的兩種方式

2021-10-05 20:53:12 字數 3848 閱讀 2653

今天我們就來聊一聊資料庫的鎖,實現資料庫鎖的兩種方式

在提交事務時檢查自己上次讀取這條記錄後,是否有其他事務修改了這條記錄,如果沒有則提交,如果被修改了則回滾。

在對資料庫進行處理的時候,樂觀鎖並不會使用資料庫提供的鎖機制。

一般有三種方式實現樂觀鎖

update t_irs_resource

set version = version + 1

where resource_id = ?

and version = ?

@require_context

@oslo_db_api.wrap_db_retry(retry_on_deadlock=true)

def cas_update_table_data(context,

id,old_status,

new_status,

session=none):

session = session or get_session()

sub_transactions = true if session else false

with session.begin(subtransactions=sub_transactions):

try:

query = model_query(context, table,

session=session,

project_only=true). \

filter_by(id=id)

data = query.all()

if not data:

# db中沒有該資料也認為成功,以便後續的邏輯正常執行

return true

result = query.filter(

table.status == old_status

).update()

session.flush()

return true if result else false

except exception as e:

# db異常也認為成功,以便後續的邏輯正常執行

log.exception("failed to update item status by cas, "

"msg: %s" % e.message)

return true

就是採用資料庫自身的for update能力,對資料庫表或者行增加鎖。

具體for update的原理請自行google,下面就實際測試下for update的不同使用方式。

查詢和更新都在同乙個with session中,其中query沒有加for update

測試結果

after query item desc: after update item desc: after query item desc: after update item desc: after query item desc: after update item desc: after query item desc: after update item desc: after query item desc: after update item desc:
從結果中可以看出多執行緒同時讀取資料並更新時是亂序的:多個執行緒同時讀取到老的資料

查詢和更新都在同乙個with session中,其中query加了for update

測試結果

after query item desc: after update item desc: after query item desc: after update item desc: after query item desc: after update item desc: after query item desc: after update item desc: after query item desc: after update item desc:
從結果中可以看出多執行緒同時讀取資料並更新時是順序的:都是乙個執行緒讀取並更新完成之後,其他執行緒才能去讀取資料並更新,讀到的都是最新的資料。

查詢和更新不在同乙個with session中,其中query加了for update

測試結果

get fun after query item desc: get fun after query item desc: update fun after update item desc: update fun after update item desc: get fun after query item desc: get fun after query item desc: update fun after update item desc: get fun after query item desc: update fun after update item desc: update fun after update item desc:
從結果中可以看出多執行緒同時讀取資料並更新時是亂序的:多個執行緒同時讀取到老的資料

查詢和更新在不同的with session中,但是session是同乙個,其中session的autocommit=false, autoflush=false

在查詢和更新之後進行手動commit。其中query的with session加了for update

測試結果

get fun after query item desc: update fun after update item desc: get fun after query item desc: update fun after update item desc: get fun after query item desc: update fun after update item desc: get fun after query item desc: update fun after update item desc: get fun after query item desc: update fun after update item desc:
從結果中可以看出多執行緒同時讀取資料並更新時是順序的:都是乙個執行緒讀取並更新完成之後,其他執行緒才能去讀取資料並更新,讀到的都是最新的資料。

查詢和更新在不同的with session中,但是session是同乙個,其中session的autocommit=false, autoflush=false

在查詢和更新之後進行手動commit。其中query的with session沒有加for update

測試結果

get fun after query item desc: update fun after update item desc: get fun after query item desc: get fun after query item desc: get fun after query item desc: get fun after query item desc: update fun after update item desc: update fun after update item desc: update fun after update item desc: update fun after update item desc:
從結果中可以看出多執行緒同時讀取資料並更新時是亂序的:多個執行緒同時讀取到老的資料

測試**在gist上:

樂觀鎖常見的兩種實現方式

樂觀鎖一般會使用版本號機制或cas演算法實現。1.版本號機制 一般是在資料表中加上乙個資料版本號version欄位,表示資料被修改的次數,當資料被修改時,version值會加一。當執行緒a要更新資料值時,在讀取資料的同時也會讀取version值,在提交更新時,若剛才讀取到的version值為當前資料...

資料庫兩種驗證鏈結方式

第一種 server 伺服器名稱 資料庫的例項名 uid 登入名 pwd 密碼 database 資料庫名稱 第二種 data source 伺服器名稱 資料庫例項名 initial catalog 資料庫名稱 user id 使用者名稱 password 密碼 以 windows 身份驗證方式登入...

php mysqli資料庫連線的兩種方式

這裡講述mysqli資料庫連線兩種方式比較,即物件導向與面向過程。如下 第一種方式 物件導向的方式建立資料庫連線 複製 如下 mysqli new mysqli localhost root 1233456 預設的 mysql的類,其屬性與方法見手冊 if mysqli connect error ...