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

为何TYPE_SCROLL_INSENSITIVE的ResultSet仍反映外部数据变更?

问题原因分析

  1. 代码中的ResultSet类型与描述不符:你提到使用了TYPE_SCROLL_INSENSITIVE,但实际代码里写的是ResultSet.TYPE_SCROLL_SENSITIVE——这个类型本身就是设计用来感知外部数据变更的。
  2. refreshRow()的强制刷新作用:不管你用哪种ResultSet类型,调用refreshRow()都会直接从数据库重新拉取当前行的最新数据,完全绕过INSENSITIVE类型的客户端缓存机制。
  3. 事务自动提交的影响:Connection默认开启自动提交,第一次executeQuery()执行后事务就会提交。sleep后的操作会在新事务中执行,此时外部提交的变更已经对新事务可见,再加上refreshRow()的调用,自然会拿到更新后的值。

如何用TYPE_SCROLL_SENSITIVE显示更新后的数据

你当前的代码已经实现了这个效果,只需注意两个细节:

  • 确保Statement创建时明确指定ResultSet.TYPE_SCROLL_SENSITIVE和ResultSet.CONCUR_READ_ONLY(你已经做到了)。
  • MySQL的Connector/J驱动不会自动更新ResultSet内容,必须主动调用refreshRow()触发单条数据刷新,或者重新执行executeQuery()获取全新的ResultSet来批量更新数据。

如何实现预期行为(外部变更不反映到ResultSet)

要让ResultSet始终保留初始查询的数据,不受外部变更影响,需要做以下调整:

  1. 修正ResultSet类型为TYPE_SCROLL_INSENSITIVE:
    Statement statement = connection.createStatement(
        ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY
    );
    
  2. 移除refreshRow()调用:这个方法会强制从数据库拉取最新数据,直接删除这行代码即可。
  3. 控制事务范围:关闭自动提交,让整个查询、等待、再次读取的操作处于同一个事务中,利用MySQL默认的REPEATABLE READ隔离级别保证事务内的数据一致性:
    connection.setAutoCommit(false); // 关闭自动提交
    Statement statement = connection.createStatement(
        ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY
    );
    ResultSet resultSet = statement.executeQuery("SELECT * FROM table1");
    
    // 第一次读取数据
    if (resultSet.next()) {
        System.out.print(resultSet.getInt("id") + " ");
        System.out.print(resultSet.getString("name") + " ");
        System.out.print(resultSet.getString("value"));
        System.out.println();
    }
    
    // 模拟外部修改延迟
    Thread.sleep(10 * 1000);  
    
    // 直接回到结果集开头重新读取,无需刷新
    resultSet.beforeFirst();
    
    // 第二次读取数据
    if (resultSet.next()) {
        System.out.print(resultSet.getInt("id") + " ");
        System.out.print(resultSet.getString("name") + " ");
        System.out.print(resultSet.getString("value"));
        System.out.println();
    }
    
    connection.commit(); // 最后提交事务
    
  4. 驱动特性验证:MySQL的Connector/J对TYPE_SCROLL_INSENSITIVE的实现是将结果集缓存到客户端内存中,只要不主动触发刷新,就会一直保留初始查询的数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:40:55