innoDB可重复读级别是否可以隔离幻行读

import java.io.*;
import java.sql.*;
import java.util.Properties;

/***
 * 验证innoDB可重复读级别是否可以隔离幻行读
 *
 *
 * 查看隔离级别
 * select @@tx_isolation
 * 或
 * select @@transaction_isolation
 *
 * 建表句子如下
 * CREATE TABLE `test` (
 *   `id` int(11) NOT NULL,
 *   PRIMARY KEY (`id`)
 * ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 *
 * 开两个线,第一个读一次 停10S再读取一次
 * 第一个线程开始后5S开始第二个线程去写入一条
 *
 */
public class Jdbc {
    static Properties properties;

    public static void main(String[] args) throws  Exception {
        new MyThread1().start();
        Thread.sleep(5000);
        new MyThread2().start();
    }

    public static class MyThread1 extends Thread  {
        @Override
        public void run() {
            try {
                Connection connection=getConnection();
                connection.setAutoCommit(false);
                String sql="SELECT COUNT(*) FROM EXERCISE.TEST";
                Statement statement=connection.createStatement();
                System.out.println("读取");
                ResultSet resultSet1=statement.executeQuery(sql);
                while (resultSet1.next()){
                    System.out.println(resultSet1.getString("COUNT(*)"));
                }
                Thread.sleep(10000);
                System.out.println("读取");
                ResultSet resultSet2=statement.executeQuery(sql);
                while (resultSet2.next()){
                    System.out.println(resultSet2.getString("COUNT(*)"));
                }
                connection.commit();
                statement.close();
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static class MyThread2 extends Thread {
        @Override
        public void run() {
            try {
                Connection connection=getConnection();
                connection.setAutoCommit(false);
                String sql="INSERT INTO EXERCISE.TEST VALUES(2);";
                Statement statement=connection.createStatement();
                System.out.println("插入");
                System.out.println(statement.executeUpdate(sql));
                connection.commit();
                statement.close();
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static Connection getConnection() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection(
                properties.getProperty("localhostURL"),
                properties.getProperty("localhostUser"),
                properties.getProperty("localhostPwd")
        );
    }

    static {
        InputStream in = null;
        try {
            in = new FileInputStream(new File("D:\\javaProject\\exercise\\src\\main\\Resources\\db.properties"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        properties = new Properties();
        try {
            properties.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,InnoDB默认隔离级别下(REPEATABLE READ)存在幻的问题。 幻是指在同一个事务内,多次执行相同的查询,但结果集却不一致的情况。这是由于其他事务在查询期间插入或删除了满足查询条件的行导致的。 为了解决幻问题,InnoDB引入了多版本并发控制(Multi-Version Concurrency Control,简称MVCC)机制,并提供了两种解决幻问题的方式: 1. 快照(Snapshot Read):在REPEATABLE READ隔离级别下,默认使用快照。快照会在事务开始时创建一个一致性视图,并使用该视图来取数据。其他事务对数据的修改不会影响当前事务的取操作,从而避免了幻问题。 2. 当前(Current Read):在REPEATABLE READ隔离级别下,可以使用当前来解决幻问题。当前会对查询的数据加锁,确保其他事务不能插入或删除符合查询条件的行。可以使用SELECT ... FOR UPDATE语句或SELECT ... LOCK IN SHARE MODE语句来进行当前操作。 需要注意的是,REPEATABLE READ隔离级别下,使用快照可以避免大部分幻问题,但在某些情况下仍然可能出现幻。如果需要完全避免幻,可以将隔离级别提升至SERIALIZABLE,但这可能会影响并发性能。 总结起来,InnoDB通过MVCC机制和快照、当前的方式来解决幻问题。开发者可以根据具体的业务需求和性能要求选择适当的隔离级别取方式来处理幻问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值