ResultSet.TYPE_SCROLL_SENSITIVE到底发生了什么?

转自:https://blog.csdn.net/axman/article/details/3984103java

这个问题我在几年前说过,但今天再次从CSDN上看到有人问这个问题,能够看出,真正懂这个问题的人1%都不到。
我再次把这个问题写在这里,但愿光临个人BLOG的人能真正了解它。mysql

咱们先来作一个例子,在例子中我用的是mysql-essential-5.1.30-win32版。sql

来跟我作如下几个命令:数据库

mysql> create database axman;
mysql> use axman;
mysql> create table axmantest(
    -> id int(4) not null auto_increment primary key
    -> name varchar(20));缓存

mysql> insert into axmantest (name) values ('axman')
mysql> insert into axmantest (name) values ('sager')
mysql> insert into axmantest (name) values ('p4');测试

OK,写一个测试程序:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;.net


public class MainTest {
 public static void main(String[] args) throws Exception{
  
  Class.forName("org.gjt.mm.mysql.Driver");
  Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/axman?useUnicode=true&characterEncoding=UTF-8","root","password");
  Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
  ResultSet rs = stmt.executeQuery("select * from axmantest");
  System.out.println("请删除!");
  Thread.sleep(1000*20);
  while(rs.next()){
   System.out.println(rs.getString(1)+","+rs.getString(2));
  }
  rs.close();
  stmt.close();
  conn.close();
 }
}code

先在刚才的MYSQL命令环境下输入命令:
select * from axmantest;
+----+-------+
| id | name  |
+----+-------+
|  1 | axman |
|  2 | sager |
|  3 | p4    |
+----+-------+
3 rows in set (0.00 sec)blog

delete from axmantest where id = 3;不要提交,敲好放在这儿,运行那个测试程序。看到“请删除”三个字当即切换到
Mysql命令环境下回车。
跟着:
select * from axmantest;
+----+-------+
| id | name  |
+----+-------+
|  1 | axman |
|  2 | sager |
+----+-------+
2 rows in set (0.00 sec)索引

回到测试程序,看看:
1,axman
2,sager
3,p4

个人个神啦,这哪叫结果集敏感啊?彻底是INSENSITIVE嘛!


可是,这正是TYPE_SCROLL_SENSITIVE形成的。

对于TYPE_SCROLL_INSENSITIVE,一次查询的结果可能存在数据库端的内存缓冲中,也能够直接发送到JVM的内存中,
若是结果集很小,会直接发送到JVM层,而后被next定位,转换数据类型,显示,或者缓存在数据库内存中。总之
查询结果已经和数据库脱离,这时若是数据库记录被其它进程更新,则结果集没法得知,仍是使用缓存的记录。

而对于TYPE_SCROLL_SENSITIVE,一次查询的结果并非直接的记录被缓存下来,只是符合条件的记录的“原始ROWID”
被缓存了,这个原始ROWID并不是特指ORACLE的ROWID,而是数据库底层定位记录的索引值。简单说
select * from axmantest操做的结果并非
1,axman
2,sager
3,p4
这些内容被缓存了。而是相似rd_file_offset_0x111010101001这样的值被缓存了,而后next定位到这条记录时,
数据库会再次根据这个ROWID作底层操做:
select * from axmantest where rowid = rd_file_offset_0x111010101001;
简单说每next一次都会发生一次查询,这样能够保证next后操做到的是当前最新的数据。
对于更新操做,若是你先查询,而后数据被其它进程更新掉了,而后next到这条记录时确定没有问题,会取出最新的
内容,但对于删除操做。由于数据库删除记录只是记录上作一个标记,再也不被检索,但原来被缓存的ROWID还在,根据
它还能够经过数据库本身的底层操做正确地把数据提取出来,因此你看到的已经被手工删除的数据又被显示出来了。

一样插入操做由于查询的时候结果集中尚未要插入的操做,因此不可能缓存了它的ROWID,咱们再次作这个例子,把
“请删除”修改为“请插入”(有些很差听),如今数据库中是两条记录,当运行程序看到“请插入”时当即插入,注意
我说的是往表中插入记录,不是插入别的。而后看一下运行结果仍是两条记录。

若是有兴趣再试一下更新操做,你会看更新的结果会立刻反映出来。

因此TYPE_SCROLL_SENSITIVE只能更新操做敏感,其它的插入操做和删除操做不会及时地反映到结果集中。

相关文章
相关标签/搜索