记-数据库事务隔离级别

news2025/2/24 2:50:32

记-数据库事务隔离级别

      • 一、MySQL数据库默认隔离级别
      • 二、JDBC连接的事务隔离级别
        • 1. 查看JDBC连接的事务隔离级别
        • 2. JDBC连接的事务隔离级别设置过程
      • 三、修改JDBC连接的事务隔离级别
        • 1. 全局修改
        • 2. 局部修改

一、MySQL数据库默认隔离级别

MySQL数据库默认事务隔离级别为REPEATABLE-READ,大型互联网公司一般建议改成READ-COMMITTED,通过降低间隙锁概率,以提升事务性能。(顺便提一句,Oracle数据库默认事务隔离级别是READ-COMMITTED

  • 查看数据库事务隔离级别
show variables like '%tx_isolation%';

: 使用DBeaver数据库连接工具查询事务隔离级别时,要确认是否修改过工具的默认事务隔离级别,若修改过DBeaver数据库连接工具的默认事务隔离级别,查询结果可能和预期的不一致。因此建议使用原生的mysql cmd工具查看事务隔离级别。

二、JDBC连接的事务隔离级别

JDBC连接的事务隔离级别默认取数据库服务端设置的默认隔离级别,也就是show variables like '%tx_isolation%'查询结果

1. 查看JDBC连接的事务隔离级别

MyBatis框架为例,Debug跟踪当前SqlSession,查看org.apache.ibatis.session.SqlSession#getConnection对象使用的原生Connection对象(com.mysql.cj.jdbc.ConnectionImpl)查看isolationLevel属性值即可!

  /**
     * A constant indicating that transactions are not supported.
     */
    int TRANSACTION_NONE             = 0;

    /**
     * A constant indicating that
     * dirty reads, non-repeatable reads and phantom reads can occur.
     * This level allows a row changed by one transaction to be read
     * by another transaction before any changes in that row have been
     * committed (a "dirty read").  If any of the changes are rolled back,
     * the second transaction will have retrieved an invalid row.
     */
    int TRANSACTION_READ_UNCOMMITTED = 1;

    /**
     * A constant indicating that
     * dirty reads are prevented; non-repeatable reads and phantom
     * reads can occur.  This level only prohibits a transaction
     * from reading a row with uncommitted changes in it.
     */
    int TRANSACTION_READ_COMMITTED   = 2;

    /**
     * A constant indicating that
     * dirty reads and non-repeatable reads are prevented; phantom
     * reads can occur.  This level prohibits a transaction from
     * reading a row with uncommitted changes in it, and it also
     * prohibits the situation where one transaction reads a row,
     * a second transaction alters the row, and the first transaction
     * rereads the row, getting different values the second time
     * (a "non-repeatable read").
     */
    int TRANSACTION_REPEATABLE_READ  = 4;

    /**
     * A constant indicating that
     * dirty reads, non-repeatable reads and phantom reads are prevented.
     * This level includes the prohibitions in
     * <code>TRANSACTION_REPEATABLE_READ</code> and further prohibits the
     * situation where one transaction reads all rows that satisfy
     * a <code>WHERE</code> condition, a second transaction inserts a row that
     * satisfies that <code>WHERE</code> condition, and the first transaction
     * rereads for the same condition, retrieving the additional
     * "phantom" row in the second read.
     */
    int TRANSACTION_SERIALIZABLE     = 8;

    /**
     * Attempts to change the transaction isolation level for this
     * <code>Connection</code> object to the one given.
     * The constants defined in the interface <code>Connection</code>
     * are the possible transaction isolation levels.
     * <P>
     * <B>Note:</B> If this method is called during a transaction, the result
     * is implementation-defined.
     *
     * @param level one of the following <code>Connection</code> constants:
     *        <code>Connection.TRANSACTION_READ_UNCOMMITTED</code>,
     *        <code>Connection.TRANSACTION_READ_COMMITTED</code>,
     *        <code>Connection.TRANSACTION_REPEATABLE_READ</code>, or
     *        <code>Connection.TRANSACTION_SERIALIZABLE</code>.
     *        (Note that <code>Connection.TRANSACTION_NONE</code> cannot be used
     *        because it specifies that transactions are not supported.)
     * @exception SQLException if a database access error occurs, this
     * method is called on a closed connection
     *            or the given parameter is not one of the <code>Connection</code>
     *            constants
     * @see DatabaseMetaData#supportsTransactionIsolationLevel
     * @see #getTransactionIsolation
     */
    void setTransactionIsolation(int level) throws SQLException;
2. JDBC连接的事务隔离级别设置过程

JDBC SPI加载机制

com.mysql.cj.jdbc.ConnectionImpl#ConnectionImpl(com.mysql.cj.conf.HostInfo)

==>

com.mysql.cj.jdbc.ConnectionImpl#createNewIO

==>

com.mysql.cj.jdbc.ConnectionImpl#connectOneTryOnly

==>

com.mysql.cj.jdbc.ConnectionImpl#initializePropsFromServer

==> 查询服务端变量transaction_isolation(别名)和tx_isolation

com.mysql.cj.jdbc.ConnectionImpl#checkTransactionIsolationLevel

/**
     * Set transaction isolation level to the value received from server if any.
     * Is called by connectionInit(...)
     */
    private void checkTransactionIsolationLevel() {
        String s = this.session.getServerSession().getServerVariable("transaction_isolation");
        if (s == null) {
            s = this.session.getServerSession().getServerVariable("tx_isolation");
        }

        if (s != null) {
            Integer intTI = mapTransIsolationNameToValue.get(s);

            if (intTI != null) {
                this.isolationLevel = intTI.intValue();
            }
        }
    }
  • 从服务端加载变量

在这里插入图片描述

com.mysql.cj.NativeSession#loadServerVariables

/**
     * Loads the result of 'SHOW VARIABLES' into the serverVariables field so
     * that the driver can configure itself.
     * 
     * @param syncMutex
     *            synchronization mutex
     * @param version
     *            driver version string
     */
    public void loadServerVariables(Object syncMutex, String version) {

        if (this.cacheServerConfiguration.getValue()) {
            createConfigCacheIfNeeded(syncMutex);

            Map<String, String> cachedVariableMap = this.serverConfigCache.get(this.hostInfo.getDatabaseUrl());

            if (cachedVariableMap != null) {
                String cachedServerVersion = cachedVariableMap.get(SERVER_VERSION_STRING_VAR_NAME);

                if (cachedServerVersion != null && getServerSession().getServerVersion() != null
                        && cachedServerVersion.equals(getServerSession().getServerVersion().toString())) {
                    this.protocol.getServerSession().setServerVariables(cachedVariableMap);

                    return;
                }

                this.serverConfigCache.invalidate(this.hostInfo.getDatabaseUrl());
            }
        }

        try {
            if (version != null && version.indexOf('*') != -1) {
                StringBuilder buf = new StringBuilder(version.length() + 10);
                for (int i = 0; i < version.length(); i++) {
                    char c = version.charAt(i);
                    buf.append(c == '*' ? "[star]" : c);
                }
                version = buf.toString();
            }

            String versionComment = (this.propertySet.getBooleanProperty(PropertyDefinitions.PNAME_paranoid).getValue() || version == null) ? ""
                    : "/* " + version + " */";

            this.protocol.getServerSession().setServerVariables(new HashMap<String, String>());

            if (versionMeetsMinimum(5, 1, 0)) {
                StringBuilder queryBuf = new StringBuilder(versionComment).append("SELECT");
                queryBuf.append("  @@session.auto_increment_increment AS auto_increment_increment");
                queryBuf.append(", @@character_set_client AS character_set_client");
                queryBuf.append(", @@character_set_connection AS character_set_connection");
                queryBuf.append(", @@character_set_results AS character_set_results");
                queryBuf.append(", @@character_set_server AS character_set_server");
                queryBuf.append(", @@collation_server AS collation_server");
                queryBuf.append(", @@init_connect AS init_connect");
                queryBuf.append(", @@interactive_timeout AS interactive_timeout");
                if (!versionMeetsMinimum(5, 5, 0)) {
                    queryBuf.append(", @@language AS language");
                }
                queryBuf.append(", @@license AS license");
                queryBuf.append(", @@lower_case_table_names AS lower_case_table_names");
                queryBuf.append(", @@max_allowed_packet AS max_allowed_packet");
                queryBuf.append(", @@net_write_timeout AS net_write_timeout");
                if (!versionMeetsMinimum(8, 0, 3)) {
                    queryBuf.append(", @@query_cache_size AS query_cache_size");
                    queryBuf.append(", @@query_cache_type AS query_cache_type");
                }
                queryBuf.append(", @@sql_mode AS sql_mode");
                queryBuf.append(", @@system_time_zone AS system_time_zone");
                queryBuf.append(", @@time_zone AS time_zone");
                if (versionMeetsMinimum(8, 0, 3) || (versionMeetsMinimum(5, 7, 20) && !versionMeetsMinimum(8, 0, 0))) {
                    queryBuf.append(", @@transaction_isolation AS transaction_isolation");
                } else {
                    queryBuf.append(", @@tx_isolation AS transaction_isolation");
                }
                queryBuf.append(", @@wait_timeout AS wait_timeout");

                NativePacketPayload resultPacket = sendCommand(this.commandBuilder.buildComQuery(null, queryBuf.toString()), false, 0);
                Resultset rs = ((NativeProtocol) this.protocol).readAllResults(-1, false, resultPacket, false, null,
                        new ResultsetFactory(Type.FORWARD_ONLY, null));
                Field[] f = rs.getColumnDefinition().getFields();
                if (f.length > 0) {
                    ValueFactory<String> vf = new StringValueFactory(f[0].getEncoding());
                    Row r;
                    if ((r = rs.getRows().next()) != null) {
                        for (int i = 0; i < f.length; i++) {
                            this.protocol.getServerSession().getServerVariables().put(f[i].getColumnLabel(), r.getValue(i, vf));
                        }
                    }
                }

            } else {
                NativePacketPayload resultPacket = sendCommand(this.commandBuilder.buildComQuery(null, versionComment + "SHOW VARIABLES"), false, 0);
                Resultset rs = ((NativeProtocol) this.protocol).readAllResults(-1, false, resultPacket, false, null,
                        new ResultsetFactory(Type.FORWARD_ONLY, null));
                ValueFactory<String> vf = new StringValueFactory(rs.getColumnDefinition().getFields()[0].getEncoding());
                Row r;
                while ((r = rs.getRows().next()) != null) {
                    this.protocol.getServerSession().getServerVariables().put(r.getValue(0, vf), r.getValue(1, vf));
                }
            }
        } catch (PasswordExpiredException ex) {
            if (this.disconnectOnExpiredPasswords.getValue()) {
                throw ex;
            }
        } catch (IOException e) {
            throw ExceptionFactory.createException(e.getMessage(), e);
        }

        if (this.cacheServerConfiguration.getValue()) {
 // 缓存服务端变量
            this.protocol.getServerSession().getServerVariables().put(SERVER_VERSION_STRING_VAR_NAME, getServerSession().getServerVersion().toString());
            this.serverConfigCache.put(this.hostInfo.getDatabaseUrl(), this.protocol.getServerSession().getServerVariables());
        }
    }

上面代码本质是执行select语句查询MySQL服务端变量

select  @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_write_timeout AS net_write_timeout, @@query_cache_size AS query_cache_size, @@query_cache_type AS query_cache_type, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@tx_isolation AS transaction_isolation, @@wait_timeout AS wait_timeout

三、修改JDBC连接的事务隔离级别

1. 全局修改

java.sql.Connection#TRANSACTION_REPEATABLE_READ

  • Druid数据源

com.alibaba.druid.pool.DruidAbstractDataSource#defaultTransactionIsolation

          druid:
            defaultTransactionIsolation: 2
  • Hikari数据源

com.zaxxer.hikari.HikariConfig#transactionIsolationName

    hikari:
      transactionIsolationName: TRANSACTION_READ_COMMITTED
2. 局部修改
@Transactional(isolation = Isolation.READ_COMMITTED) 

参考:

查-MySQL 常用语句速查

源码分析-JDBC SPI加载机制

springboot @ConfigurationProperties注解源码解析(含松散绑定)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1027929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务生态系统:使用Spring Cloud构建分布式系统

文章目录 什么是微服务&#xff1f;为什么选择Spring Cloud&#xff1f;Spring Cloud的关键组件示例&#xff1a;构建一个简单的微服务步骤1&#xff1a;创建Spring Boot项目步骤2&#xff1a;配置Eureka服务发现步骤3&#xff1a;创建REST控制器步骤4&#xff1a;运行项目步骤…

【R语言】完美解决devtools安装GitHub包失败的问题(以gwasglue为例)

Rstudio&#xff0c;R4.3.1&#xff0c;命令在Rstudio的命令行即console中运行。 文章目录 一、问题复述二、分析三、解决四、安装示例&#xff1a;gwasglue 一、问题复述 使用devtools安装一个github的包。 devtools&#xff1a; devtools 是 R 语言中一个非常有用的包&…

netty之数据读写源码阅读

数据读写 write 从client端的写开始看 client与服务端建立完connect后可以从future里拿到连接的channel对象。这里的channel是io.netty.channel.Channel对象。 调用其channel.writeAndFlush(msg);方法可以进行数据发送。 writeAndFlush会调用pipeline的writeAndFlush方法 …

目标检测算法改进系列之Neck添加渐近特征金字塔网络(AFPN模块)

渐近特征金字塔网络&#xff08;AFPN模块&#xff09; 在目标检测任务中&#xff0c;多尺度特征对具有尺度差异的目标进行编码具有重要意义。多尺度特征提取的常用策略是采用经典的自顶向下和自底向上的特征金字塔网络。 然而&#xff0c;这些方法存在特征信息丢失或退化的问…

【音视频】ffplay源码解析-FrameQueue队列

帧队列架构位置 结构体源码 FrameQueue结构体 /* 这是一个循环队列&#xff0c;windex是指其中的首元素&#xff0c;rindex是指其中的尾部元素. */ typedef struct FrameQueue {Frame queue[FRAME_QUEUE_SIZE]; // FRAME_QUEUE_SIZE 最大size, 数字太大时会占用大量的…

第二证券:什么是a股b股?

在我国的股市中&#xff0c;我们经常会听到“A股”和“B股”这两个名词。那么&#xff0c;终究什么是A股和B股呢&#xff1f; 首先&#xff0c;A股全称为“A股票”&#xff0c;是指在我国境内上市的以人民币计价的股票。A股首要面向国内出资者&#xff0c;只要具有必定条件的内…

如何快速检测代理IP质量?方法与工具全干货

一直以来&#xff0c;IP代理都是出海跨境业务的刚需。质量好的IP代理&#xff0c;除了在跨境业务产生巨大作用&#xff0c;在SEO监控、爬虫抓取、市场研究等领域也发挥着很大的作用。但是&#xff0c;对于IP代理的质量检测是我们选择高标准IP代理的一句&#xff0c;我们一般都会…

美国零售电商平台Target,值得入驻吗?如何入驻?

Target 是美国最大的零售商之一&#xff0c;在品牌出海为大势所趋的背景下&#xff0c;它在北美电商中的地位节节攀升。Target 商店在众多垂直领域提供各种价格实惠的自有品牌&#xff0c;吸引越来越多的跨境商家入驻&#xff0c;如美妆、家居、鞋服、日用百货等&#xff0c;随…

Mybatis学习笔记12 分页插件

Mybatis学习笔记11 缓存相关_biubiubiu0706的博客-CSDN博客 (5) select distinct top(<取数说明>) <选择 列表> (1) from <表1> <连接类型> join <表2> ON <连接条件> (2) where <筛选条件> (3) group by <分组条件> (4) havi…

linux下链接

linux下链接用法 ln链接格式与介绍 linux下链接用法一、链接的使用格式二、链接的介绍 一、链接的使用格式 链接&#xff1a; 格式&#xff1a; ln 源文件 链接文件 硬链接 ln -s 源文件 链接文件 软连接 硬链接文件占磁盘空间 但是删除源文件不会影响硬链接文件 软链接文件不…

秒杀场景设计

1.活动页面静态化处理 没有到活动时间页面静态化处理避免访问服务端 2.使用cdn让用户可以获取就近的所需静态页面内容 3.限制用户同一时间点击次数 4.把商品库存提前放入redis&#xff0c;秒杀请求直接操作redis防止操作直接落库打崩数据库 5.使用lua脚本操作redis保证操作…

transformer系列2---transformer架构详细解析

transformer详细解析 Encoder1 输入1.1 Embedding 词嵌入1.1.1 Embedding 定义1.1.2 几种编码方式对比1.1.3 实现代码 1.2 位置编码1.2.1 使用位置编码原因1.2.2 位置编码方式1.2.3 位置编码代码 2 注意力 Attention2.1 自注意力self-attention2.1.1 QKV含义2.1.2 自注意力公式…

微信图文如何替换成自己的二维码?

二维码样式中的二维码目前都是小蚂蚁的二维码&#xff0c;如何替换成自己的二维码&#xff0c;其实也很简单&#xff0c;就像替换样式中的图片一样&#xff0c;首先点击二维码&#xff0c;选择工具条中的“换图”&#xff0c;然后在弹出来的框中填入二维码图片的链接地址或者直…

招股书更新9版终上市,飞沃科技能否躲过风电红利后的黯淡?

文丨熔财经 作者丨文泽 碳达峰、碳中和成为主旋律目标下&#xff0c;作为可再生能源主力的风电产业迎来了发展的“黄金时代”。与新能源相关的上下游企业也赚的“盆满钵满”。 在此背景下&#xff0c;飞沃科技(301232.SZ)历经4轮问询&#xff0c;更新9版招股书终于登陆资本市…

Command not found 解决方法

前言&#xff1a;要更新code上服务器用GUI失败&#xff0c;$ patch_delivery_gui&#xff0c;报错&#xff1a;patch_delivery_gui: command not found&#xff0c;上次编TA也是这个问题 写了个脚本&#xff1a;这个脚本会先检查ifconfig、firewall-cmd和vim命令是否可用&#…

ExcelServer EXCEL服务器使用- 用户、角色权限配置

Excel文件服务器搭建 搭建Excel服务器 1、登录 默认 用户名 Admin 密码 3 2、角色管理 添加修改角色 角色配置在 系统管理->角色.fexm文件夹下 可以像修改excel文件一样 修改角色 3、用户管理 添加修改用户 用户的修改在 系统管理->用户.fexm 可以像excel一样编辑用户…

27、Flink 的SQL之SELECT (窗口聚合)介绍及详细示例(4)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

机器人中的数值优化(十七)—— 锥与对称锥

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

http的网站进行访问时候自动跳转至https

通常情况下我们是用的都是http的路径&#xff0c;对于https的使用也很少&#xff0c;但是随着https的普及越来越多的域名访问需要用到https的&#xff0c;这个我们就演示怎么设置在我们对一个http的网站进行访问时候自动跳转至https下。 用到的工具及软件: 系统&#xff1a;wi…

规划基础知识

1 规划简介 在规划中&#xff0c;我们通过结合高精地图&#xff0c;定位和预测来构建车辆轨迹。 规划的第一步就是路线导航&#xff0c;侧重于如何从地图上的A前往B&#xff0c;在进行路径规划时&#xff0c;将地图数据作为输入&#xff0c;并输出可行驶路径。 在Apollo中&…