国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

并發環境下mysql插入檢查方案

2024-07-24 12:45:03
字體:
來源:轉載
供稿:網友

業務背景:
基本業務場景是這樣的,請求數據(車輛vin信息)進入到接口中,需要先判斷其在數據庫中的狀態,如果庫中不存在該vin,或者該vin狀態位為“1(已完成)”,則執行一些檢查操作后,將數據插入到數據庫中,此時新增vin狀態為0,調用人工處理接口,十分鐘后返回結果,將狀態置為1。如果其狀態位為“0(正在處理)”則駁回操作,返回提示信息。
在單線程環境下,這樣的業務沒有問題,然而當并發訪問接口時,會出現同時進入兩條vin相同的請求AB,正常情況應該插入一條A,駁回一條B。然而并發環境下,B執行檢查狀態時A還沒有插入,因此AB都進入到了數據庫中,數據就錯誤了。

解決方案一:
首先想到的是使用sql處理,對數據庫對應字段加唯一索引,保證一致性。如果插入重復的數據,則catch該異常,做出提示。

ALTER tableName ADD UNIQUE [indexName] ON (tableColumns(length))

但是由于業務限制,vin在庫中是可以重復的,多條重復數據查詢最新,所以不能再vin上添加唯一索引。

解決方案二:
使用mysql事務操作,將檢查是否存在和插入作為一個事務進行處理,當檢查失敗的時候,不進行插入。從網上搜索了一下,大致思路如下:

public static void StartTransaction(Connection con, String[] sqls) throws Exception { try { // 事務開始 con.setAutoCommit(false); // 設置連接不自動提交,即用該連接進行的操作都不更新到數據庫 sm = con.createStatement(); // 創建Statement對象 //依次執行傳入的SQL語句 for (int i = 0; i < sqls.length; i++) { sm.execute(sqls[i]);// 執行添加事物的語句 } con.commit(); // 提交給數據庫處理 // 事務結束 //捕獲執行SQL語句組中的異常 } catch (SQLException e) { try { System.out.println("事務執行失敗,進行回滾!/n"); con.rollback(); // 若前面某條語句出現異常時,進行回滾,取消前面執行的所有操作 } catch (SQLException e1) { e1.printStackTrace(); } } finally { sm.close(); } }

但是這樣實際上還是沒有解決并發的問題,這樣只是把兩個操作變成了一個原子的sql操作,可以用于同時插入兩條數據一致性的情況,但并不適合需求。

既然sql層面沒有解決問題,就考慮從java的并發編程方向解決。
解決方案三:
java解決并發問題,首先想到的是使用內置鎖或者可重入鎖,基本語法如下:
·內置鎖:
由于是在Servlet中進行的處理,因此使用synchronized(this)直接處理業務代碼,使得并發情況下,只能有一個線程訪問到該段業務代碼:

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 西和县| 杭锦后旗| 昌图县| 从江县| 鲁山县| 临漳县| 新蔡县| 玉山县| 巩留县| 冀州市| 吉安县| 沭阳县| 安泽县| 莱阳市| 定南县| 修水县| 论坛| 南投市| 拜城县| 永泰县| 长阳| 木兰县| 永胜县| 西平县| 宜君县| 休宁县| 芒康县| 浮梁县| 修水县| 梅河口市| 绥阳县| 翁源县| 凤冈县| 温州市| 永修县| 贞丰县| 桑日县| 嵊州市| 西丰县| 赤城县| 广西|