You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

两个Java应用从Oracle数据库查询结果不一致的原因排查

问题分析:直接查表与查询视图返回数据条数不一致

问题场景

  • 两个运行在同一服务器的Java应用,从同一Oracle数据库获取实时更新数据
  • 应用1直接关联Indices和tipowner.idxm表查询,应用2通过视图vw_l_mkt_index查询数据
  • 两者均通过250毫秒周期的线程拉取数据,预期返回记录条数一致,但实际应用1返回10条,应用2仅返回4条

应用1查询语句

select  T.Id,   
    T.Index_Name,
    T.xIndex,
    T.NetChange,
    T.PrcntChange,
    to_char(T.IDXM_RCV_DT+NUMTODSINTERVAL(3,'HOUR') ,'YYYY/MM/DD HH24:MI:SS.FF3') local_time ,
    T.TradeVolume,
    T.TradeValue,
    T.TodayInitIndex,
    T.IndexHigh,
    T.IndexLow,
    T.YestCloseIndex,
    T.YestCloseAdjusted, 
    T.ChangeDir,
    I.IDXM_LI_TOT_TRAD_SYM totalSym,
    I.IDXM_LI_TOT_TRAD_NB||'' totalTrades,
    I.IDXM_LI_TOT_TRAD_QTY||'' totalQty,
    I.IDXM_LI_TOT_TRAD_VAL||'' totalValue
from 
  Indices T, 
  tipowner.idxm I
where 
  I.IDXM_IDX_ID=T.id 
  AND T.IDXM_RCV_DT > (to_timestamp('2023/08/03 16:47:23.496','YYYY/MM/DD HH24:MI:SS.FF3')-(3/24))

视图vw_l_mkt_index定义

CREATE OR REPLACE VIEW vw_l_mkt_index (
  market,
  name_en,
  name_ar,
  msg_timestamp,
  status,
  index_value,
  change,
  change_percent,
  trades_count,
  traded_symbols,
  traded_value,
  traded_volume,
  rising_symbols,
  dropping_symbols,
  flat_symbols,
  open_time,
  close_time
) AS
SELECT /*+ INDEX(IDXM IX_IDXM_IDX_ID_RECV_DT) INDEX(T IX_TADAWUL_INDICES_TS) */
    I.IDXM_IDX_ID AS MARKET,
    I.IDXM_DESC AS NAME_EN,
    I.IDXM_ADESC AS NAME_AR,
    to_timestamp(to_char(I.IDXM_RCV_DT+NUMTODSINTERVAL(3,'HOUR'),'dd.mm.yy HH24:MI:SS.FF3'), 'dd.mm.yy HH24:MI:SS.FF3') AS MSG_TIMESTAMP,
    P.MKT_STATUS AS STATUS,
    T.XINDEX AS INDEX_VALUE,
    DECODE(T.CHANGEDIR, '-', (T.NETCHANGE * -1), T.NETCHANGE)AS CHANGE,
    DECODE(T.CHANGEDIR, '-', (T.PRCNTCHANGE * -1), T.PRCNTCHANGE) AS CHANGE_PERCENT,
    I.IDXM_LI_TOT_TRAD_NB || '' AS TRADES_COUNT,
    I.IDXM_LI_TOT_TRAD_SYM AS TRADED_SYMBOLS,
    I.IDXM_LI_TOT_TRAD_QTY || '' AS TRADED_VOLUME,
    I.IDXM_LI_TOT_TRAD_VAL || '' AS TRADED_VALUE,
    I.IDXM_LI_ADV_TRAD_SYM AS RISING_SYMBOLS,
    I.IDXM_LI_DEC_TRAD_SYM AS DROPPING_SYMBOLS,
    I.IDXM_LI_UNC_TRAD_SYM AS FLAT_SYMBOLS,
    TO_CHAR(M.MK_FROM, 'HH24:MI:SS') AS OPEN_TIME,
    TO_CHAR(M.MK_TO, 'HH24:MI:SS') AS CLOSE_TIME
FROM IDXM I, INDICES T, PARAM P, MARKET M
WHERE IDXM.IDXM_IDX_ID = T.ID
  AND M.MK_CODE (+)= IDXM.IDXM_IDX_ID
  AND IDXM.IDXM_IDX_ID <> 'NOMU'

核心原因分析

1. 视图包含额外的过滤条件与关联表

  • 排除特定ID数据:视图中有IDXM.IDXM_IDX_ID <> 'NOMU'条件,直接过滤掉ID为NOMU的记录,而应用1的查询没有该条件,会保留这部分数据。
  • 内连接PARAM表导致数据丢失:视图的FROM子句中直接关联了PARAM P表,但未使用外连接(没有(+)),意味着只有在PARAM表中存在匹配IDXM_IDX_ID记录的数据,才会被视图返回。而应用1仅关联Indices和tipowner.idxm,不会受PARAM表的影响,因此会保留那些PARAM中无匹配的记录。

2. 时间过滤的字段差异

应用1的查询基于T.IDXM_RCV_DT做时间过滤,而如果应用2查询视图时是基于视图的MSG_TIMESTAMP(来源于I.IDXM_RCV_DT)做过滤,若T.IDXM_RCV_DT与I.IDXM_RCV_DT的值不一致,会导致两者的时间过滤范围不同,最终返回的记录条数出现差异。

3. 索引提示的潜在影响(概率较低)

视图中包含索引提示/*+ INDEX(IDXM IX_IDXM_IDX_ID_RECV_DT) INDEX(T IX_TADAWUL_INDICES_TS) */,如果索引未及时同步最新数据(比如索引失效、未实时更新),可能导致视图查询时无法获取到最新的部分记录,但这种情况需要结合数据库索引状态验证。

验证方法

  • 在应用1的查询中添加视图的过滤条件:AND I.IDXM_IDX_ID <> 'NOMU',并内连接PARAM P表,观察返回条数是否变为4条。
  • 修改视图定义,移除PARAM P的内连接和IDXM_IDX_ID <> 'NOMU'条件,查询视图看返回条数是否与应用1一致。
  • 对比T.IDXM_RCV_DT和I.IDXM_RCV_DT的取值,确认两者是否同步,以及应用2的时间过滤逻辑是否与应用1匹配。

内容的提问来源于stack exchange,提问作者ManKeer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 03:34:58