重複插入資料的另類解決思路

2021-07-08 17:22:03 字數 2026 閱讀 9464

在進行插入資料時,我們會先從資料庫查詢是否已經擁有該記錄,但是最後會發現這個判斷沒有任何效果,導致這個判斷失效的原因有很多,比如事務沒有提交,或者多台伺服器都執行了相同的**,或者你的控制器(strut2的action,springmvc的controller等)是多例項的!

該部落格旨在解決最後一種問題。

知識補充:

1、springmvc的controller是預設是單例的,struts2的action是多例的,spring注入預設是單例的。

2、synchronized(this)

a、與放在方法上修飾一樣,都是鎖住的物件,也就是說任何執行緒執行到這裡時都需要獲得該方法的物件鎖,然後才能執行括號裡面的**,稱為同步(任何時間都只有乙個執行緒在執行同步**塊)。

b、如果該**執行時間特別長,其他執行緒都在等著**執行完,就是同步阻塞狀態。

c、this也可以替換為其他的物件,與之類似,其他執行緒到此時,需要獲得該物件的鎖,才能執行同步**塊。

d、特別的,如果方法上有static和synchronized關鍵字,這時就變成了類鎖,要執行同步**,各個執行緒之間就需要對類鎖競爭,誰有類鎖才能夠執行。

3、執行緒安全指的是多個執行緒之間的切換不會導致程式執行完後出現多種結果。

如果你使用struts2、spring,你會發現這類似於多執行緒,一條請求進來新建乙個action,然後注入業務實現類。同一時間多個相同請求併發,就會有可能繞過你的重複判斷,即同一時間,每個執行緒都有可能查詢不到重複結果。

解決方法:

1、通常情況下,我們可以給判斷重複的字段上加上聯合主鍵來判斷唯一即可,但是很多時候我們不願意這樣做,因為會減少插入的效率。資料庫在每次插入時都會遍歷資料來判斷是否唯一,不唯一就丟擲異常,在大資料量大批量插入時,效率急劇下降。

2、當然你可以直接給你的方法加上synchronized來鎖住插入方法的物件,任何人要執行插入的操作方法,就必須得到該方法的物件鎖,但是如果方法特別慢,就會同步阻塞。

此時給出一種思路,用乙個執行緒安全的標識位來實現同步。

流程:1、各個執行緒將自己需要修改的資源作為標識位,這裡我們將可以用來判斷重複的字段值作為標誌位。

2、提供乙個全域性變數存放這些標識位,對這個全域性變數的操作必須保證執行緒安全,即任意時刻都只能有乙個執行緒修改、查詢這個全域性變數。

3、每次進行插入操作時,先判斷是否全域性變數含有自己的標識位。沒有,放入自己的標識位;有,說明在此之前已經有其他執行緒在執行這個方法。

4、從資料庫裡查詢判斷重複。

5、執行操作方法。

6、執行完後,釋放掉標識位,告訴其他相同標識位的執行緒「你可以執行了!」,但是具體能不能夠執行,也得經過資料庫的重複判斷。

請看**:

public class cache 

public static mapgetinstance()

}

上面是乙個簡單的單例物件來作為全域性變數,不同的是這個單例是乙個map型別的,我們可以存放多個標識位,這樣不同標識位的執行緒是可以執行的。

private boolean isincache(string key)else

}return false;

}

以上**是對全域性變數操作的,讀者可以看到,synchronized可以保證執行緒安全,而且是對map進行put和containskey操作,效率極快,幾乎不會造成同步阻塞。引數key是由你自己定義的,合理使用就可以讓有插入相同資源想法的執行緒們變成同步的。(我這裡因為業務需求,orgid和classid兩個都相同說明是重複資料, 所以我將兩個值拼接起來作為標誌位)

if (!isincache(orgid + classid))

}

以上**就是對重複插入的判斷,外層判斷使執行緒不重複,內層判斷使資料不重複。

synchronized (cache.getinstance())
最後,**執行完後,請釋放資源,告訴其他相同想法的執行緒可以進來看一下,但是由於你已經執行了,資料庫已經有值了,內層判斷不會讓它執行的。當然你也可以不釋放,最後的結果是map裡面的值越積越多~~

Python中的另類解體思路

no.1給定乙個非空陣列,除了其中的某個元素只出現了一次之外,其餘每個元素均出現兩次,找出那個只出現了一次的元素。說明 你的演算法應該具有時間線性複雜度。示例 輸入 2,2,1 輸出 1 輸入 4,1,2,1,2 輸出 4 題目說完了,大部分人可以想到的正常解題思路 class solution d...

防止頁面重複提交,插入重複資料的解決辦法

新做的物業收費系統,當使用者點選收費按鈕的時候,如果點選多次會生成兩張收款單,發現問題後通過 在按鈕click的js事件裡面加了 lnkcharge.attributes onclick this getpostbackeventreference this lnkcharge this.disab...

刪除重複資料思路

1.在運算元據庫的時候往往會出現一條資料重複出現多次,而且沒有唯一標識的情況下該如何刪除重複資料呢?解決方案 先用distinct 查出所有不重複的資料,然後存入到乙個臨時表中,刪除現有表的所以資料,把臨時表資料匯入。select distinct into tmp from emp delete ...