今天我們就來聊一聊資料庫的鎖,實現資料庫鎖的兩種方式
在提交事務時檢查自己上次讀取這條記錄後,是否有其他事務修改了這條記錄,如果沒有則提交,如果被修改了則回滾。
在對資料庫進行處理的時候,樂觀鎖並不會使用資料庫提供的鎖機制。
一般有三種方式實現樂觀鎖
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 ...