MyBatis3源码深度解析(七)JDBC单连接事务

news2025/2/26 7:08:57

文章目录

    • 前言
    • 2.7 JDBC单连接事务
      • 2.7.1 事务的开启与提交
      • 2.7.2 事务隔离级别
        • 2.7.2.1 并发访问问题
          • (1)脏读
          • (2)不可重复读
          • (3)幻读
        • 2.7.2.2 事务隔离级别
          • (1)TRANSACTION_NONE:不支持事务
          • (2)TRANSACTION_READ_UNCOMMITTED:读未提交
          • (3)TRANSACTION_READ_COMMITTED:读提交
          • (4)TRANSACTION_REPEATABLE_READ:可重复读
          • (5)TRANSACTION_SERIALIZABLE:串行化
      • 2.7.3 事务中的保存点
    • 2.8 小结

前言

DatabaseMetaData接口中有一个supportsTransactions()方法,用于判断当前数据源是否支持事务。

事务用于提供数据完整性、正确的应用程序语义和并发访问的数据一致性。所有遵循JDBC规范的驱动程序都需要提供事务支持。

本节研究JDBC中的单连接事务。

2.7 JDBC单连接事务

2.7.1 事务的开启与提交

在JDBC API中,没有对应的方法显式地开启事务,因此何时开启一个新的事务是由JDBC驱动程序或数据库隐式决定的

通常情况下,当SQL语句需要开启事务但目前还没有事务时,会自动地开启一个新的事务。

对于什么时候提交或回滚事务,Connection接口提供了setAutoCommit(boolean autoCommit)commit()rollback()等方法来进行控制。

  1. setAutoCommit(boolean autoCommit)方法用于设置事务是否自动提交,默认情况下事务自动提交是开启的,每个SQL语句执行完毕后会自动地提交事务。
  2. 如果使用setAutoCommit(boolean autoCommit)方法禁用了事务的自动提交,则需要显式地调用commit()方法提交事务,或者调用rollback()方法回滚事务。

禁用事务自动提交一般适用于需要将多个SQL语句作为一个事务提交或者事务由应用服务器管理的情况。

2.7.2 事务隔离级别

事务隔离级别用于表示事务中对数据的操作对其他事务的“可见性”,主要用于解决数据并发访问中的可能会出现的问题,且会直接影响到并发访问的效率。

Connection接口中提供了一个setTransactionIsolation(int level)方法,用于设置当前驱动程序的事务隔离级别。

2.7.2.1 并发访问问题
(1)脏读

脏读是指在一个事务中读取到另一个事务中未提交的数据。例如,A事务修改了一条数据,但是未提交修改,此时A事务对数据的修改对其他事务是可见的,因此B事务中能够读取A事务未提交的修改。一旦A事务回滚,B事务中读取的就是不正确的数据。

下面用一个简单例子来解释。

在数据库中插入一条数据:

在数据库中插入一条数据
编写A事务和B事务的测试代码:

@Test
public void testA() {
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        connection = DbUtils.getConnection();
        // 关闭事务自动提交
        connection.setAutoCommit(false);
        // 设置事务隔离级别为:读未提交(下文解释)
        connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        // 读取一条记录
        String sql = "select * from user where id = 1";
        statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        resultSet = statement.executeQuery(sql);
        resultSet.next();
        System.out.println("A事务读取的用户信息:" + new User(resultSet).toString());
        // 修改这条记录
        resultSet.updateString("name", "孙悟空");
        resultSet.updateRow();
        System.out.println("A事务修改后的用户信息:" + new User(resultSet).toString());
        
        // 此处打一个断点 ...
        
        // 回滚事务
        connection.rollback();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        DbUtils.close(resultSet, statement, connection);
    }
}

@Test
public void testB() {
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        connection = DbUtils.getConnection();
        // 关闭事务自动提交
        connection.setAutoCommit(false);
        // 设置事务隔离级别为:读未提交
        connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        // 读取一条记录
        String sql = "select * from user where id = 1";
        statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        resultSet = statement.executeQuery(sql);
        resultSet.next();
        System.out.println("B事务读取的用户信息:" + new User(resultSet).toString());
        
        // 此处打一个断点 ...
        
        // 提交事务
        connection.commit();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        DbUtils.close(resultSet, statement, connection);
    }
}

下面开始模拟脏读产生的过程:

  1. 以Debug方式执行A事务中的查询记录、修改记录操作,停到断点处,控制台打印修改前和修改后的用户数据;

  1. 以Debug方式执行B事务中的查询记录操作,停到断点处,控制台打印查询出来的用户数据,确实是A事务修改后但未提交的用户数据;

  1. 继续执行A事务,回滚修改操作,但B事务已经拿到了A事务修改后的用户数据,如果B事务对修改后的数据进一步处理,就是不符合要求的,这就产生脏读。
(2)不可重复读

不可重复读是指在同一个事务中,对于同一份数据的多次读取可能返回不同的结果。例如,A事务读取了一行数据,但此时B事务中修改了该行数据,A事务中再次读取该行数据将得到不同的结果。

下面用一个简单例子来解释。

在数据库中只有一条数据:

编写A事务和B事务的测试代码:

@Test
public void testA() {
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        connection = DbUtils.getConnection();
        // 关闭事务自动提交
        connection.setAutoCommit(false);
        // 设置事务隔离级别为:读未提交
        connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        // 读取一条记录
        String sql = "select * from user where id = 1";
        statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        resultSet = statement.executeQuery(sql);
        resultSet.next();
        System.out.println("A事务首次读取的用户信息:" + new User(resultSet).toString());
        
        // 此处打一个断点 ...
        
        // 再次读取记录
        resultSet = statement.executeQuery(sql);
        resultSet.next();
        System.out.println("A事务再次读取的用户信息:" + new User(resultSet).toString());
        // 提交事务
        connection.commit();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        DbUtils.close(resultSet, statement, connection);
    }
}

@Test
public void testB() {
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        connection = DbUtils.getConnection();
        // 关闭事务自动提交
        connection.setAutoCommit(false);
        // 设置事务隔离级别为:读未提交
        connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        // 读取一条记录
        String sql = "select * from user where id = 1";
        statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        resultSet = statement.executeQuery(sql);
        resultSet.next();
        System.out.println("B事务读取的用户信息:" + new User(resultSet).toString());
        // 修改这条记录
        resultSet.updateString("name", "孙悟空");
        resultSet.updateRow();
        System.out.println("B事务修改后的用户信息:" + new User(resultSet).toString());
        // 提交事务
        connection.commit();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        DbUtils.close(resultSet, statement, connection);
    }
}

下面开始模拟不可重复读产生的过程:

  1. 以Debug方式执行A事务中的首次查询记录操作,停到断点处,控制台打印首次查询的用户数据;

  1. 直接执行B事务中的查询记录、修改记录操作,控制台打印处理结果,此时数据库记录也已被修改;


  1. 继续执行A事务,再次以相同的SQL查询用户数据,发现查询的数据是修改后的,这就产生了不可重复读的问题。

(3)幻读

幻读发生在多个事务同时读取和修改数据时。例如,当A事务正在读取一系列数据时,B事务可能会插入一些新的数据,然后提交事务。当A事务再次查询相同的记录集时,它可能会发现一些原本不存在的记录,这会导致数据的不一致性,给用户造成幻觉。

幻读和不可重复读的区别在于,不可重复读侧重于已存在数据的更改,而幻读侧重于新增数据的插入。

下面用一个简单例子来解释。

在数据库中只有一条数据:

编写A事务和B事务的测试代码:

@Test
public void testA() {
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        connection = DbUtils.getConnection();
        // 关闭事务自动提交
        connection.setAutoCommit(false);
        // 设置事务隔离级别为:读未提交
        connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        // 查询记录集
        String sql = "select * from user";
        statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        resultSet = statement.executeQuery(sql);
        System.out.println("A事务首次读取的用户信息有:");
        while (resultSet.next()) {
            System.out.println(new User(resultSet).toString());
        }
        System.out.println("-----------------------");
        
        // 此处打一个断点 ...
        
        // 再次查询记录集
        resultSet = statement.executeQuery(sql);
        System.out.println("A事务再次读取的用户信息有:");
        while (resultSet.next()) {
            System.out.println(new User(resultSet).toString());
        }
        // 提交事务
        connection.commit();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 关闭资源
        DbUtils.close(resultSet, statement, connection);
    }
}

@Test
public void testB() {
    Connection connection = null;
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        connection = DbUtils.getConnection();
        // 关闭事务自动提交
        connection.setAutoCommit(false);
        // 设置事务隔离级别为:读未提交
        connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
        // 插入一条记录
        String sql = "INSERT INTO USER (NAME, age, phone, birthday) VALUES('user1', 18, '18705464523', '2000-02-21 10:24:30');";
        statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        statement.executeUpdate(sql);
        // 提交事务
        connection.commit();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        // 关闭资源
        DbUtils.close(resultSet, statement, connection);
    }
}

下面开始模拟幻读产生的过程:

  1. 以Debug方式执行A事务中的首次查询记录集操作,停到断点处,控制台打印首次查询的用户数据;

  1. 直接执行B事务中的插入记录操作,控制台打印处理结果,此时数据库记录也增加了一条;

  1. 继续执行A事务,再次以相同的SQL查询用户数据集,发现查询的数据还包括B事务新增的,这就产生了幻读的问题。

2.7.2.2 事务隔离级别

JDBC遵循SQL:2003规范,定义了5种事务隔离级别:

(1)TRANSACTION_NONE:不支持事务
(2)TRANSACTION_READ_UNCOMMITTED:读未提交

这种事务隔离级别允许某一事务读取另一事务未提交更改的数据,这意味着可能会出现脏读、不可重复读、幻读现象。

【2.7.2.1 并发访问问题】的三个案例均将事务隔离级别设置为“读未提交”,经过实际测试,确实会发生脏读、不可重复读、幻读现象。

(3)TRANSACTION_READ_COMMITTED:读提交

这种事务隔离级别表示在某一事务中进行任何数据的更改,在提交之前对其他事务都是不可见的,这样可以防止脏读,但不能解决不可重复读、幻读问题。

这是MySQL驱动程序默认的事务隔离级别。

下面继续使用【2.7.2.1 并发访问问题】中的三个案例进行测试。

首先手动将事务隔离级别设置为TRANSACTION_READ_COMMITTED读提交,其余代码保持不变。

// 设置事务隔离级别为:读提交
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
  • 测试脏读问题:已解决
  1. 以Debug方式执行A事务中的查询记录、修改记录操作,停到断点处,控制台打印修改前和修改后的用户数据;

  1. 以Debug方式执行B事务中的查询记录操作,停到断点处,控制台打印查询出来的用户数据,确实是原来的数据,而不是A事务修改后但未提交的用户数据

  1. 继续执行A事务,回滚修改操作,但B事务拿到的是A事务修改前的用户数据,符合要求,脏读问题已被解决。
  • 测试不可重复读问题:未解决

  • 测试幻读问题:未解决

(4)TRANSACTION_REPEATABLE_READ:可重复读

这种事务隔离级别表示在某一事务中对同一数据进行多次读取时,可以得到相同的结果,并且其他事务插入数据的操作对该事务不可见,这样可以防止脏读、不可重复读,但不能解决幻读问题;

下面继续使用【2.7.2.1 并发访问问题】中的三个案例进行测试。

首先手动将事务隔离级别设置为TRANSACTION_REPEATABLE_READ可重复读,其余代码保持不变。

// 设置事务隔离级别为:可重复读
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
  • 测试脏读问题:已解决

  • 测试不可重复读问题:已解决

  1. 以Debug方式执行A事务中的首次查询记录操作,停到断点处,控制台打印首次查询的用户数据;

  1. 直接执行B事务中的查询记录、修改记录操作,控制台打印处理结果,此时记录已被修改;

  1. 继续执行A事务,再次以相同的SQL查询用户数据,发现查询的数据是修改前的,这就解决了不可重复读的问题。

  • 测试幻读问题:未解决
(5)TRANSACTION_SERIALIZABLE:串行化

这种事务隔离级别是最高的事务隔离级别,保证数据的一致性和完整性,可以防止脏读、不可重复读,、幻读问题,但是并发性较差。

下面继续使用【2.7.2.1 并发访问问题】中的三个案例进行测试。

首先手动将事务隔离级别设置为TRANSACTION_SERIALIZABLE串行化,其余代码保持不变。

// 设置事务隔离级别为:串行化
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
  • 测试脏读问题:已解决

  • 测试不可重复读问题:已解决

  • 测试幻读问题:已解决

  1. 以Debug方式执行A事务中的首次查询记录集操作,停到断点处,控制台打印首次查询的用户数据;

  1. 直接执行B事务中的插入记录操作,发现报错,无法打开新的事务。

  1. 继续执行A事务,再次以相同的SQL查询用户数据集,发现查询的数据是一样的,这就解决了幻读的问题。

  1. A事务提交后,再次执行B事务,发现可以成功执行,说明串行化等级下一次只能打开一个事务。

2.7.3 事务中的保存点

保存点是指通过事务中标记的一个中间点来对事务进行更细粒度的控制,一旦设置保存点,事务就可以归滚到保存点,而不影响保存点之前的操作。

DatabaseMetaData接口提供了supportsSavepoints()方法用于判断JDBC驱动程序是否支持保存点。

Connection接口提供了``setSavepoint()```方法用于在当前事务中设置保存点。如果该方法在事务外中调用,则会在该方法调用处开启一个新的事务。

该方法的返回值是一个Savepoint对象,该对象可作为COnnection接口的rollback()方法的参数,用于回滚到对应的保存点。

示例代码如下:

// ......
// 关闭事务自动提交
connection.setAutoCommit(false);
// 读取一条记录
String sql = "select * from user where id = 1";
statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
resultSet = statement.executeQuery(sql);
resultSet.next();
System.out.println("第一次读取的用户信息:" + new User(resultSet).toString());
// 第一次修改这条记录
resultSet.updateString("name", "孙悟空-修改1");
resultSet.updateRow();
System.out.println("第一次修改后的用户信息:" + new User(resultSet).toString());
// 设置保存点
Savepoint savepoint = connection.setSavepoint();
// 第二次修改这条记录
resultSet.updateString("name", "孙悟空-修改2");
resultSet.updateRow();
System.out.println("第二次修改后的用户信息:" + new User(resultSet).toString());
// 回滚到保存点
connection.rollback(savepoint);
// 再次读取这条记录
// 读取一条记录
resultSet = statement.executeQuery(sql);
resultSet.next();
System.out.println("第二次读取的用户信息:" + new User(resultSet).toString());
// 提交事务
connection.commit();
// ......

控制台打印执行结果:

第一次读取的用户信息:User{id=1, name='黑风怪', age=18, phone='18705464523', birthday=2000-02-21}
第一次修改后的用户信息:User{id=1, name='孙悟空-修改1', age=18, phone='18705464523', birthday=2000-02-21}
第二次修改后的用户信息:User{id=1, name='孙悟空-修改2', age=18, phone='18705464523', birthday=2000-02-21}
第二次读取的用户信息:User{id=1, name='孙悟空-修改1', age=18, phone='18705464523', birthday=2000-02-21}

在示例代码中,依次进行读取记录→第一次修改→设置保存点→第二次修改→回滚到保存点→再次读取记录→提交事务,第二次读取的结果恰好就是第一次修改后的结果,说明确实回滚到了保存点的位置。

保存点创建后,可以被手动释放。Connection接口提供了releaseSavepoint()方法,接收一个Savepoint对象为参数,用于释放保存点。保存点被释放后,如果试图通过rollback()方法回滚到保存点,则会抛出SQLException异常。

事务中创建的保存点在事务提交或回滚之后会自动释放,事务回滚到某一保存点之后,该保存点之后的保存点将会自动释放。

2.8 小结

第2章到此就梳理完毕了,本章的主题是:JDBC规范。回顾一下本章的梳理的内容:

(二)JDBC API简介
(三)Connection
(四)Statement
(五)ResultSet
(六)DatabaseMetaData
(七)JDBC单连接事务

更多内容请查阅分类专栏:MyBatis3源码深度解析

第3章主要梳理:MyBatis常用工具类。主要内容包括:

  • 使用SQL类生成语句;
  • 使用ScriptRunner执行脚本;
  • 使用SqlRunner操作数据库;
  • MetaObject详解;
  • MetaClass详解;
  • ObjectFactory详解;
  • ProxyFactory详解。

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

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

相关文章

JVM内存问题排错最佳实践

写在文章开头 上一篇的文章中分享了一个入门级别的调优实践,收到很多读者的好评,所以笔者今天再次分享一个进阶一点的案例,希望对近期在面试的读者对于JVM这一块的实践经验有所帮助。 Hi,我是 sharkChili ,是个不断在硬核技术上作死的 java coder ,是 CSDN的博客专家 ,…

光伏数字化管理平台:驱动绿色能源革命的智能化引擎

随着全球对可再生能源需求的不断增长,光伏产业已经成为推动绿色能源革命的重要力量。在这个背景下,光伏数字化管理平台应运而生,以其强大的数据处理、实时监控和智能优化功能,为光伏电站的运营管理和维护带来了革命性的变革。 光伏…

有源电桥电路

有源电桥电路 有源电桥由A3运放的正向输入端与负向输入端电压相等且为零可知:G点(待测阻抗Zx与被测阻抗Rs的连接点)电平一直为零,也就是平衡点虚地点,Ux与Us也就变成参照虚地点的绝对相量电压。并且根据运放的虚断原理…

7-16 计算符号函数的值

对于任一整数n,符号函数sign(n)的定义如下: 请编写程序计算该函数对任一输入整数的值。 输入格式: 输入在一行中给出整数n。 输出格式: 在一行中按照格式“sign(n) 函数值”输出该整数n对应的函数值。 输入样例1: 10输出样例1: sign(10) 1输入样…

unity学习(54)——选择角色界面--解析赋值服务器返回的信息1

1.decode这种照猫画虎的工作 把逆向出来UserHandler.cs中的内容,融到自建客户端的MessageManager.cs中: 2.此时登录账号,马上显示当前账号下已有三名角色: 此时返回数据包中的command的值是1: 3.当注册玩家数超过三名…

springboot255基于spring boot的疫情信息管理系统

疫情信息管理系统的设计与实现 摘要 近年来,信息化管理行业的不断兴起,使得人们的日常生活越来越离不开计算机和互联网技术。首先,根据收集到的用户需求分析,对设计系统有一个初步的认识与了解,确定疫情信息管理系统…

人工智能|机器学习——DBSCAN聚类算法(密度聚类)

1.算法简介 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,簇集的划定完全由样本的聚集程度决定。聚集程度不足以构成簇落的那些样本视为噪声点,因此DBSCAN聚类的方式也可以用于异常点的检测。 2.算法原…

Xss-labs-master 1-16关

第一关 <?php ini_set("display_errors", 0); $str $_GET["name"]; echo "<h2 aligncenter>欢迎用户".$str."</h2>"; ?> <center><img srclevel1.png></center> <?php echo "&l…

【NR技术】 3GPP支持无人机服务的关键性能指标

1 性能指标概述 5G系统传输的数据包括安装在无人机上的硬件设备(如摄像头)收集的数据&#xff0c;例如图片、视频和文件。也可以传输一些软件计算或统计数据&#xff0c;例如无人机管理数据。5G系统传输的业务控制数据可基于应用触发&#xff0c;如无人机上设备的开关、旋转、升…

实时智能应答3D数字人搭建

语音驱动口型的算法 先看效果&#xff1a; 你很快就可以帮得上我了 FACEGOOD 决定将语音驱动口型的算法技术正式开源&#xff0c;这是 AI 虚拟数字人的核心算法&#xff0c;技术开源后将大程度降低 AI 数字人的开发门槛。FACEGOOD是一家国际领先的3D基础软件开发商&#xff0c;…

【sgExcelGrid】自定义组件:简单模拟Excel表格拖拽、选中单元格、横行、纵列、拖拽圈选等操作

特性&#xff1a; 可以自定义拖拽过表格可以点击某个表格&#xff0c;拖拽右下角小正方形进行任意方向选取单元格支持选中某一行、列支持监听selectedGrids、selectedDatas事件获取选中项的DOM对象和数据数组支持props自定义显示label字段别名 sgExcelGrid源码 <template&g…

MySQL主从读写分离之Proxysql(openEuler版)

实验目的&#xff1a; 基于proxysql实现MySQL的主从读写分离。 实验过程&#xff1a; 前期准备&#xff1a; 一共有四台虚拟机&#xff0c;其中三台为配置好的一主两从虚拟机&#xff0c;还有一台干净的虚拟机用来配置proxysql。 主机名地址master192.168.27.137node1192.…

如何在Windows系统使用固定tcp公网地址ssh远程Kali系统

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过[cpolar 内网穿透](cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站)软件实现ssh 远程连接kali! …

【机器学习300问】30、准确率的局限性在哪里?

一、什么是准确率&#xff1f; 在解答这个问题之前&#xff0c;我们首先得先回顾一下准确率的定义&#xff0c;准确率是机器学习分类问题中一个很直观的指标&#xff0c;它告诉我们模型正确预测的比例&#xff0c;即 还是用我最喜欢的方式&#xff0c;举例子来解释一下&#xf…

业务随行简介

定义 业务随行是一种不管用户身处何地、使用哪个IP地址&#xff0c;都可以保证该用户获得相同的网络访问策略的解决方案。 背景 在企业网络中&#xff0c;为实现用户不同的网络访问需求&#xff0c;可以在接入设备上为用户部署不同的网络访问策略。在传统园区网络中&#xf…

文本生成视频:从 Write-a-video到 Sora

2024年2月15日&#xff0c;OpenAI 推出了其最新的文本生成视频模型——Sora。Sora 能够根据用户的指令生成一分钟长度的高质量视频内容。这一创新的发布迅速在社会各界引发了广泛关注与深入讨论。本文将围绕本实验室发表于SIGGRAPH AISA 的 Write-a-video和 Sora 展开&#xff…

修改简化docker命令

修改|简化docker命令 使用命令打开 .bashrc 文件&#xff1a; vim ~/.bashrc在文件中添加类似以下行来创建别名&#xff1a; # 查看所有容器 alias disdocker images # 查看运行容器 alias dpsdocker ps # 查看所有容器 alias dpsadocker ps -a # 停止容器 alias dsdocker s…

python 蓝桥杯之动态规划入门

文章目录 DFS滑行&#xff08;DFS 记忆搜索&#xff09; 思路&#xff1a; 要思考回溯怎么写&#xff08;入参与返回值、递归到哪里&#xff0c;递归的边界和入口&#xff09; DFS 滑行&#xff08;DFS 记忆搜索&#xff09; 代码分析&#xff1a; 学会将输入的数据用二维列表…

云原生架构设计:分布式消息队列技术解析

消息队列是在消息传输过程中保存消息的容器&#xff0c;消息队列管理器在将消息从源到目标时充当中间人的角色&#xff0c;消息队列的主要目的是提供路由并保证消息的可靠传递。如果发送消息时接收者不可用&#xff0c;那消息队列就会保留消息&#xff0c;直到下次成功消费为止…

超网、IP 聚合、IP 汇总分别是什么?三者有啥区别和联系?

一、超网 超网&#xff08;Supernet&#xff09;是一种网络地址聚合技术&#xff0c;它可以将多个连续的网络地址合并成一个更大的网络地址&#xff0c;从而减少路由表的数量和大小。超网技术可以将多个相邻的网络地址归并成一个更大的网络地址&#xff0c;这个更大的网络地址…