天天看點

Transaction中SQL的順序引起的死鎖

因為項目的資料更新頻率很高,導緻經常出現死鎖的問題。感覺以下遇到的一種情況比較典型,也比較tricky,計之。

問題描述:

如以下兩條非常簡單的sql語句,它們共同組成了一個transaction,那麼在多線程高頻率執行時就會引起死鎖問題(當然這裡要考慮鎖的級别問題,一般多類似這種系統都會選擇行鎖,那麼以下引起死鎖的條件是兩條語句都對同一行操作):

select <column1> from <table> where <column2> = ? 

update <table> set <column1> = %d where <column2> = '%s'

問題分析:

select語句需要“shared lock”,因而多個線程可以同時進入,而update需要“exclusive lock”,當兩個線程同時執行了select語句,而獲得了“shared lock”,而他們在接下來執行update語句時,都需要獲得“exclusive lock”而産生競争,導緻死鎖。

解決方案1:

互換他們的順序,這樣,在第一次執行update語句時,他們會競争"exclusive lock"而引起沒有得到“exclusive lock”的線程等待:

1, update <table> set <column2> = <column2> + <some value> where <column1> = '%s' 

2. select <column1> from <table> where <column2> = ? 

3. <column1> - <some value> to get the old <column1> value.

解決方案2:

采用“hold lock”方式,即在所有操作之前做一個dummy的update操作,這樣可以保證在進transaction之前需要先獲得一個“exclusive lock”