使用資料庫實現冪等性的方法有三種:
通過悲觀鎖來實現冪等性
通過唯一索引來實現冪等性
通過樂觀鎖來實現冪等性
接下來我們分別來看這些實現方式的具體執行過程。
① 悲觀鎖
使用悲觀鎖實現冪等性,一般是配合事務一起來實現,在沒有使用悲觀鎖時,我們通常的執行過程是這樣的,首先來判斷資料的狀態,執行 sql 如下:
select
status
from table_name where id=
'***'
;
然後再進行新增操作:
insert
into table_name (id)
values
('***'
);
最後再進行狀態的修改:
update table_name set
status
='***'
;
但這種情況因為是非原子操作,所以在高併發環境下可能會造成乙個業務被執行兩次的問題,當乙個程式在執行中時,而另乙個程式也開始狀態判斷的操作。因為第乙個程式還未來得及更改狀態,所以第二個程式也能執行成功,這就導致乙個業務被執行了兩次。
在這種情況下我們就可以使用悲觀鎖來避免問題的產生,實現 sql 如下所示:
begin
;# 1.開始事務
select
*from table_name where id=
'***'
forupdate
;# 2.查詢狀態
insert
into table_name (id)
values
('***');
# 3.新增操作
update table_name set
status
='***'
;# 4.更改操作
commit
;# 5.提交事務
在實現的過程中需要注意以下兩個問題:
如果使用的是 mysql 資料庫,必須選用 innodb 儲存引擎,因為 innodb 支援事務;
id 字段一定要是主鍵或者是唯一索引,不然會鎖表,影響其他業務執行。
② 唯一索引
我們可以建立乙個唯一索引的表來實現冪等性,在每次執行業務之前,先執行插入操作,因為唯一字段就是業務的 id,因此如果重複插入的話會觸發唯一約束而導致插入失敗。在這種情況下(插入失敗)我們就可以判定它為重複提交的請求。
唯一索引表的建立示例如下:
create
table
`table_name`
(`id`
intnot
null
auto_increment
,`orderid`
varchar(32
)not
null
default
''comment
'唯一id'
,primary
key(
`id`),
unique
key`uq_orderid`
(`orderid`
)comment
'唯一約束'
)engine
=innodb
;
③ 樂觀鎖
樂觀鎖是指在執行資料操作時(更改或新增)進行加鎖操作,其他時間不加鎖,因此相比於整個執行過程都加鎖的悲觀鎖來說,它的執行效率要高很多。
樂觀鎖可以通過版本號來實現,例如以下 sql:
update table_name set version=version+
1 where version=
0;
Mysql實現冪等 基於資料庫實現冪等介面
tl dr 通過唯一編號確定同一請求,沒有唯一編號的自行生成。資料庫記錄操作狀態,資料庫事務保證資料一致性。概述通過http api進行通訊的系統,在支付或者只允許操作一次的相關場景中,對介面的冪等性有嚴格要求。介面的冪等性體現在 請求執行成功所得到的結果與次數無關 如果介面沒有實現冪等性,對於轉賬...
冪等性和實現方法
冪等性和實現方法 tommwq.tech blog 如果乙個操作重複執行多次,其效果 不考慮操作時間 和只執行一次是一樣的,那麼這個操作就叫做是冪等 idempotent 的。乍看起來,冪等操作似乎沒什麼用處,畢竟只有第一次執行有效。但如果在系統設計中考慮到 失敗 場景的話,冪等操作是非常重要的。因...
資料庫新增冪等操作 基於資料庫實現冪等介面
tl dr 通過唯一編號確定同一請求,沒有唯一編號的自行生成。資料庫記錄操作狀態,資料庫事務保證資料一致性。概述通過http api進行通訊的系統,在支付或者只允許操作一次的相關場景中,對介面的冪等性有嚴格要求。介面的冪等性體現在 請求執行成功所得到的結果與次數無關 如果介面沒有實現冪等性,對於轉賬...