REPEATABLE-READ隔离级别 事务中无法读到其它事务提交了的最新数据
前言:
業務要求一個簡單的并發控制,使得一條數據只被確認一次,我的方案是 悲觀鎖,就是在事務中先對數據行加鎖(MySQL InnoDB 行鎖基于索引),判斷是否已經確認過,未確認的情況下確認,已確認則事務提交釋放鎖。代碼寫完,結果發現未生效,就開始了滿腦子問號的排查過程。
業務代碼結構如下:
//不要這么做 //一沒對異常進行處理 //二事務的范圍太大包含很多不需要在事務中的代碼@Transactionalpublic void dangerConfirm(ConfirmDangerRequest request) throws CommonException {String zhiXinBianHao = request.getZhiXinBianHao();//此處方法中包含一次查詢操作 查詢表 A數據CodeWxid codeWxid = hisDaoService.getCode(request.getConfirmUserId());if (codeWxid == null || codeWxid.getWxId() == null){throw new CommonException("工號或企業微信id有問題", ResultStatusCode.INVALID_CAPTCHA);}//在此行打斷點先阻塞//悲觀鎖 鎖表B中的一行數據 mybatisString lock = someMapper.lock("AED5ADC3C67E4A89AB7161DA84DC1FC1");System.out.println(lock);//用JPA查同一條數據 偷懶 表BBaseInfo baseInfo = baseInfoRepository.findByZhiXinBianHao("AED5ADC3C67E4A89AB7161DA84DC1FC1");//用mybatis查詢同一行的某個字段 表BString te = someMapper.te("AED5ADC3C67E4A89AB7161DA84DC1FC1");情況描述:
在MySQL命令行直接開事務,鎖同一行,此時上文代碼斷點往下執行會等待鎖的釋放,正常。在命令行事務中更新數據中的某個字段,后提交。此時,調試代碼獲取到鎖,向下執行時 發現問題:最后兩行,均未查出命令行已經提交的字段的值,即 無法讀到其它事務已經提交的數據。這和我所掌握的知識不符。
分析:
數據庫MySQL的隔離級別時 RR,不會出現臟讀和不可重復讀。問題是現在其它事務提交的都讀不到,但是數據庫軟件是可以查到的。沒辦法了,排除法,把所有與事務無關的注釋掉,一執行,好了。。。。。??梢哉2榈狡渌聞找烟峤坏臄祿?/strong>
那么,自然地就定位到 下面這行的問題
//此處方法中包含一次查詢操作 查詢表 A數據 CodeWxid codeWxid = hisDaoService.getCode(request.getConfirmUserId());加上上面這行,又不行了。。。。。除了悲觀鎖那行外,后面又讀不到其它事務提交的數據了。。
發現了這個現象,下面就開始做實驗(隔離級別為 REPEATABLE-READ):
起兩個MySQL命令行客戶端A、B,兩邊都?set autocommit = 0;?start transaction;
實驗一:A更新一條數據行 id = 1,值更新為 99,此時A不提交,B是查不到新值99的。A提交,B直接查詢此條數據,可以查到值99。注意,在此之前B從未執行過查詢操作。
實驗一:A更新一條數據行 id = 1,值更新為 99,此時A不提交,B是查不到新值99的。A提交,B先任意執行一條查詢,再查詢此條id=1的數據,就不可以查到值99,查到的是之前的舊值。
這好像很符合 REPEATABLE-READ隔離級別的定義
使用?set @@session.tx_isolation='read-committed'; 將AB會話的隔離級別調整為?read-committed。發現:B事務任何情況下都可以讀到A事務剛提交的最新數據。
總結:
MySQL默認的隔離級別為?REPEATABLE-READ,這個隔離級別使得 前后讀取同一條的值是相同的,不會受其它事務的影響,除非它自己改變的。
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的REPEATABLE-READ隔离级别 事务中无法读到其它事务提交了的最新数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第2章 关系模型
- 下一篇: Typora 镜像下载/主题下载