一次javaweb項目Oracle數據被刪除的事件追查

         波波給我說,我們driver_record表數據不在了一部分,就是一個帳套的數據,其他帳套的數據都還在,時間大約是2019年5月22日下午3點多。

        我首先想,我們是同一張表用了一個字段叫帳套ID來區分數據的,這一個帳套的全部數據掉了,人爲誤操作數據庫的可能性較小,程序bug的可能性較大。

        既然是程序bug,那麼今天有沒有刪除這個表數據的sql執行過呢?我用下面的語句查詢了一下:

SELECT
	sql_text,sql_fullText,last_load_time,first_load_time,module
FROM
	v$sqlarea b
WHERE
	last_load_time >= to_date('2019-05-22' ,'yyyy-mm-dd')
 and 
	last_load_time <=  to_date('2019-05-22 18' ,'yyyy-mm-dd hh24')
AND (sql_text LIKE '%DELETE%'
or 
sql_text LIKE '%delete%'
)
AND (sql_text LIKE '%driver_record%'
or 
sql_text LIKE '%DRIVER_RECORD%'
)
AND ROWNUM < 10

發現查詢結果爲:

發現了這一條sql:

DELETE FROM driver_record  WHERE  id = :1 

看時間端不在今天,但是連接端是JDBC Thin Client,說明是程序連接的這個sql,不是數據庫工具連接的。

到這裏,我蒙圈了,沒有刪除全部數據的sql啊。我繼續想,既然可能是程序bug,那麼就可能循環刪除掉所有的記錄。

看sql 的樣式,應該是調用了平臺根據主鍵刪除的方法。

我在eclipse中查詢driverRecordMapper.deleteByPrimaryKey,找到了我們的CustomerReservationMateralServiceImpl類下面的這段代碼

        DriverRecord dr = new DriverRecord();
        dr.setDriverName(req.getDriverName());
        dr.setDriverIdcard(req.getIdCard());
        dr.setPhoneNum(req.getPhone());
        List<DriverRecord> drs = driverRecordMapper.selectDriverBySoming(dr);
        //如果 司機  身份證(駕駛證) 車牌沒有匹配過,直接新增
        if (Utils.isEmpty(drs)) {
            DriverRecord driver = new DriverRecord();
            driver.setAccountId(UserContext.getAccountId());
            driver.setDriverCarno(req.getCarNo());
            driver.setDriverName(req.getDriverName());
            driver.setDriverIdcard(req.getIdCard());
            driver.setPhoneNum(req.getPhone());
            driverRecordMapper.insertSelective(driver);
        }
        else {
        	for (int i = 0;i<drs.size();i++) {
        		drs.get(0).setDriverName(req.getDriverName());
        		driverRecordMapper.updateByPrimaryKeySelective(drs.get(0));
        		if (i != 0) {
        			driverRecordMapper.deleteByPrimaryKey(drs.get(i).getId());
        		}
        	}
        }

果然有我害怕的循環和刪除

逆向繼續推導,如果是循環刪除掉了,那麼循環的對象應該是查詢出了該表該帳套的所有記錄。

我繼續查看mapper中對應的查詢方法:

  <select id="selectDriverBySoming" parameterType="com.jwell.mms.cc.entity.DriverRecord" resultMap="BaseResultMap">
     SELECT 
			* 
			FROM DRIVER_RECORD dr
			<where>
			  dr.ACCOUNT_ID = #{accountId}
			  <if test="driverCarno != null and driverCarno !='' ">
			    and dr.DRIVER_CARNO = #{driverCarno}
		        </if>
		         <if test="driverName != null and driverName !='' ">
			        and dr.DRIVER_NAME = #{driverName}
		           </if>
		             <if test="driverIdcard != null and driverIdcard !='' ">
			            and dr.DRIVER_IDCARD = #{driverIdcard}
		              </if>
		              <if test="phoneNum != null and phoneNum !='' ">
			            and dr.PHONE_NUM = #{phoneNum}
		              </if>
			 </where>	
			    order by dr.CREATE_TIME DESC
  </select>

其實不看我都知道,按照我們的代碼習慣,經常查詢條件不傳遞就是查詢整個帳套的數據的,看着這段sql腳本模版,我猜測可能有一次全部查詢。於是我又繼續到數據庫找痕跡:

select first_load_time,last_load_time,sql_text,sql_fulltext  from v$sqlarea where  sql_FULLtext LIKE '%FROM DRIVER_RECORD dr%' AND	first_load_time >= '2019-05-22'

查詢結果是疑似事件時間真的有一次全表查詢。。。。跟我推測一致。

再返回來看代碼,可能是前臺傳遞的參數沒有,也沒有檢查,導致了本次全表查詢並循環刪除。找到bug了,就好辦了,洗洗睡。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章