由一段代碼想到的問題數據庫
public int updateRoleStatus(Long roleId, String userName) { SystemRoleBean role = queryOneByObject(QueryId.GET_ROLE_BY_ID, roleId); if(role.getStatus().equals(MemberEnum.YES.value())) { int count = queryCountByObject(QueryId.GET_SYSTEM_USER_COUNT_BY_ROLE_ID, roleId); if(count > 0) { //不能禁用該角色,請先禁用或刪除該角色的用戶 throw new BaseAPIException("508"); } } role.setUpdateBy(userName); role.setUpdateDate(new Date()); return update(UpdateId.UPDATE_ROLE_STATUS, role); }
<update id="updateRoleStatus" parameterType="com.cignacmb.member.mis.bean.SystemRoleBean"> update MEMBER_SHOP_SYSTEM_ROLE SET STATUS = ( case when STATUS = '01' then '00' else '01' end), update_date = #{updateDate, jdbcType=TIMESTAMP}, update_by = #{updateBy, jdbcType=CHAR} where ROLE_ID = #{roleId,jdbcType=DECIMAL} </update>
這樣的狀況,在查詢和更新之間,數據庫status的值變了。好比,查詢是角色下的用戶是可用的(status='01'),更新以前,角色下的用戶禁用了(status='00'),繞過了校驗,最後角色仍是禁用了。oracle
雖然時間超級短,機率超級小。spa
髒讀是指在一個事務處理過程裏讀取了另外一個未提交的事務中的數據。code
不可重複讀是指在對於數據庫中的某個數據,一個事務範圍內屢次查詢卻返回了不一樣的數據值,這是因爲在查詢間隔,被另外一個事務修改並提交了。事務
幻讀是事務非獨立執行時發生的一種現象。例如事務T1對一個表中全部的行的某個數據項作了從「1」修改成「2」的操做,這時事務T2又對這個表中插入了一行數據項,而這個數據項的數值仍是爲「1」而且提交給數據庫。而操做事務T1的用戶若是再查看剛剛修改的數據,會發現還有一行沒有修改,其實這行是從事務T2中添加的,就好像產生幻覺同樣,這就是發生了幻讀。ci
幻讀和不可重複讀都是讀取了另外一條已經提交的事務(這點就髒讀不一樣),所不一樣的是不可重複讀查詢的都是同一個數據項,而幻讀針對的是一批數據總體(好比數據的個數)。get
隔離級別:it
① Serializable (串行化):可避免髒讀、不可重複讀、幻讀的發生。io
② Repeatable read (可重複讀):可避免髒讀、不可重複讀的發生。(MySQL默認)table
③ Read committed (讀已提交):可避免髒讀的發生。(oracle等默認)
④ Read uncommitted (讀未提交):最低級別,任何狀況都沒法保證。
這段代碼和隔離級別沒有關係,由於是2個表,也沒有加@Transactional註解。