將存儲引擎作爲innodb使用mysql 5.7。我有一張儲存產品信息的表格。該表看起來像這樣具有獨特的鍵上的productId導致死鎖的行上的Mysql併發更新
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+-------------------+-----------------------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| productId | varchar(50) | NO | UNI | NULL | |
| seller | varchar(100) | NO | MUL | NULL | |
| updatedAt | timestamp | NO | MUL | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| status | varchar(100) | NO | MUL | NULL | |
| data | longtext | NO | | NULL | |
+-----------+--------------+------+-----+-------------------+-----------------------------+
我通過連接到該MySQL的Java應用程序有兩種操作:
1.新進入的事件(包含關於產品的變更信息)產品ID需要如果它們的版本大於現有事件,則插入它們。該版本作爲json blob存儲在我的數據列中
2.更新productId的行以更改狀態。
我的隔離級別是讀取提交的。 我嘗試了兩種方式,但兩者都導致死鎖:
Approach1:
Transaction1 starts
Insert ignore into products where productId='X' values(); // Takes a S lock on the row
select * from products where productId='X' for update ; // Take a X lock on the row to prevent new writes and compare the incoming event with the current event
Insert into products values on duplicate key update values // insert into row and on duplicate key update values
commit
一個併發更新將打開另一個交易:
Transaction2 starts
select * from products where productId='X' for update ; // Take a X lock on the row to prevent new writes and compare the incoming event with the current event
Insert into products values on duplicate key update values // insert into row and on duplicate key update values
commit;
這是導致死鎖的情況當出現以下情況時:
1.事務1 - 插入忽略語句已對該行進行了S鎖定。
2.事務2 - 選擇更新語句正在等待對行進行X鎖定。
3.事務1 - 選擇更新語句嘗試對行進行X鎖定。
因爲S鎖被保持由事務1和事務2等待採取X鎖,並且當事務1試圖採取X鎖,它會導致死鎖這導致死鎖。
方法2:
Transaction 1 starts:
select * from products where productId='X' for update ; // If a row exists then it will be locked else I know it does not exist
Insert ignore into products where productId='X' values();
commit
Transaction 2 starts:
select * from products where productId='X' for update ; // If a row exists then it will be locked else I know it does not exist
commit
這導致了局勢的僵局時,以下幾點:
1.事務1 - 選擇更新語句採用該行的X鎖。
2.事務2 - 選擇更新語句正在等待對該行進行X鎖定。
3.事務1 - 插入忽略語句試圖採取對行的S鎖,但成交1的X鎖已經等待這導致死鎖
因此,一個鎖,我想知道如何處理併發更新並插入新的事件(而不是行更新)到我的表中,而不會導致死鎖。
1.什麼是鎖定順序?
2.如何確保併發更新和新行插入的工作沒有死鎖。
任何幫助,將不勝感激:)
或者,重新應用已被殺死的交易。您需要做好準備來做到這一點,因爲某些事情可能導致死鎖或其他對交易致命的錯誤。 –
感謝@RickJames的建議。是的,重新啓動交易是一種選擇。但是,這是一種反覆出現的模式,上述解決方案解決了這個問題。總的來說,你對僵局有何看法,難道不應該避免嗎? –
可以避免一些死鎖。我同意_trying_來避免它們。然而,我發現這個論壇上有很多人似乎認爲所有僵局都可以避免,並花費太多時間來嘗試這樣做。我很高興你解決了你自己的問題。 –