死鎖場景
select for update 為悲觀鎖,隻有目前會話才能過去到鎖,其他事務通路加鎖資料會被阻塞。
以下代碼無實際邏輯,隻做示範…
代碼如下:
@Transactional
public void test() {
userService.selectByIdForUpdate(1L);
userService.increaseAmountById(1L, 10);
}
使用Sharding JDBC讀寫分離時,導緻死鎖。
死鎖原因
使用Sharding JDBC後,目前事務第一個寫之前的所有讀操作都會優先讀取從庫,而事務内第一個寫以後的讀寫操作都隻會操作主庫。
根本原因:查詢和更新不是同一個會話,導緻死鎖。即便是select for update,也會操作從庫,導緻讀取和修改不在同一個會話。但是由于是開發環境,主從為同一個資料庫,讀方法加鎖後,寫方法擷取鎖失敗,事務不送出,讀不釋放鎖,寫擷取不到鎖,導緻死鎖。
解決方法
-
在需要指定主庫查詢前,加一行代碼,指定隻能從主庫讀取資料:
HintManager.getInstance().setMasterRouteOnly();
- 在查詢之前執行一次主庫更新,無業務需求不建議使用。
代碼如下
@Transactional
public void test() {
HintManager.getInstance().setMasterRouteOnly();
userService.selectByIdForUpdate(1L);
userService.increaseAmountById(1L, 10);
}