在說明問題之前我們先來看一段經常性使用的代碼
function fun(){
開啓事務
try{
var count = find();
if(count<1){
insert();
}
提交事務
}catch(e){
事務回滾
}
}
在以上代碼中我們在一個事務中,先查詢是否存在我們要插入的數據,如果不存在則插入數據,存在則不插入數據。我們很當然的認爲這很完美,我在代碼中進行了唯一性驗證,數據表中肯定不會存在相同的數據記錄。在單機應用中或不存在高併發情況確實能夠保證我們數據的唯一性。在分佈式高併發系統中,該寫法是無法保證數據表數據的唯一性。
在單應用系統中爲保證數據表中數據主鍵的唯一性一般我們使用的方法有:
1、數據表增加唯一性約束(單一數據庫最簡單方式)
增加數據表唯一性約束是最簡單的方式,只需要在我們需要的字段中增加唯一約束,當插入相同數據時,數據庫會驗證數據唯一,當存在相同主鍵時,數據庫會拋出異常信息。
2、使用insert select where not exists 方式
數據表插入語句使用insert select 方式,如在temp_table中增加名稱爲name1的數據記錄,名字列唯一
insert into temp_table(name) select 'name1' from dual where not exists(select 1 from temp_table where name ='name1');
3、使用同步(synchronous)
程序保存代碼塊中增加併發同步控制,該方法可以防止併發執行,單程序效率會降低。
更新語句寫法
for update顯示加鎖
把udpate語句寫在前邊,先把數量-1,之後select出庫存如果>-1就commit,否則rollback。
update products set quantity = quantity-1 WHERE id=3;
select quantity from products WHERE id=3 for update;
update語句在更新的同時加上一個條件
quantity = select quantity from products WHERE id=3;
update products set quantity = ($quantity-1) WHERE id=3 and queantity = $quantity;