【MySQL】事务(重点)

目录

一、什么是事务:

二、事务的前置知识了解

引擎是否支持事务

事务的提交方式

事务操作的前置准备:

三、事务回滚:

四、事务崩溃:

原子性:

持久性:

五、自动提交和手动提交:

六、事务的隔离性:

怎么理解:

隔离级别示例:

读未提交:

读提交:

可重复读:

串行化:

七、拓展知识:

数据库的并发场景:

三个隐藏字段:

undo日志:

MVCC多版本控制:

周边问题:

read view:

 RC VS RR:


一、什么是事务:

事务是由多条DML的SQL语句构成的,这些语句在逻辑上是相关联的,比如进行转账操作,就需要有多条SQL语句:查询账户,在此账户上减去指定金额,在别的账户上加上指定金额等等,这些操作是由多条语句构成的,但是这多条操作必须是原子的,也就是说要么转账失败,要么转账成功,不能只进行一般(在我这账户里面扣了,但是在别人的账户那里却没有加上)

这样一个在用户角度看起来是原子性的操作在MySQL中就是一个事务,要把事务看做一个整体

在MySQL中,会有多个事务同时执行,而每个事务都有许多SQL语句,那么在MySQL中就会有很多SQL被同时执行,所以事务不仅仅只是由SQL语句的集合,其还要满足一下属性:

事务的四大属性:

  • 原子性:这个在之前的学习中了解过了,就是只有执行前和执行后,没有正在执行,也就是一个事务只有其中的SQL语句全部完成和其中的SQL语句还未开始执行这两个情况,不会在中间的某个环节结束
  • 一致性:这个指的是,事务在执行前和执行后,用户数据的正确性没有被破坏,也就是说在执行前后数据的变化是可预期的,比如说在转账这个事务前后,我肯定能预期我的账户会减少,别人的账户会增多我减少的部分,在技术层面上,保证好原子性,隔离性,持久性就能够保证一致性
  • 隔离性:MySQL中允许多个事务同时执行数据,隔离性就是保证事务之间互不影响,隔离性又分许多等级包括读未提交( Read uncommitted )读提交( read committed )可重复读( repeatable read)和串行化( Serializable ),两个事务同时执行,两个事务又是具有原子性的,这时当两个事务并发执行的时候要体现出事务之间的隔离性
  • 持久性:当事务执行结束后,对数据的修改是永久的,即便后面系统崩溃也不会丢失数据

以上四大属性也被叫做ACID

二、事务的前置知识了解

引擎是否支持事务

在MySQL中,MyISAM引擎是不支持事务的,InnoDB引擎是支持的,我们默认也是InnoDB引擎

事务的提交方式

查看事务的提交方式:

关于事务有两种提交方式,分别是手动提交和自动提交,可以在命令行中用如下SQL进行查看自动提交是否打开:

show variables like 'autocommit';

如下,就证明自动提交是打开的,如果value那一列是OFF的话就证明自动提交是关闭的,此时也就是手动提交

修改事务的提交方式:

用set设置autocommit来进行事务的自动提交的打开或者关闭

0就是OFF,1就是ON

事务操作的前置准备:

在接下来进行事务操作的时候,我们首先将隔离级别修改为读未提交( Read uncommitted )这是最低的隔离级别,这样在后面的操作中能够方便查看,在了解完其他性质后,我们再来了解事务的隔离级别:

首先查看当前的隔离级别:

select @@transaction_isolation;

如上是可重复读的隔离级别,我将其修改为读未提交( Read uncommitted )

set global transaction isolation level read uncommitted;

但是在修改后进行查看发现没有改变,这是因为当前查看的是局部的隔离级别

如上修改是修改的全局的,如果想查看全局的需要如下SQL:

隔离这部分接下来会详细讲解的,可以在后面详细了解

我们重新登录一下MySQL就会把局部的也修改了

接下来准备一张测试表

这是一张员工表,其中包含了员工ID,员工姓名,员工工资

mysql> create table if not exists account(-> id int primary key,-> name varchar(50) not null default '',-> blance decimal(10, 2) not null default 0.0-> );

三、事务回滚:

首先就是启动一个事务,这里有两种方法,begin和start transaction

等到后面commit为止这就是MySQL中的一个事务,在这期间的SQL语句是要看做一个整体的

接着准备两个终端,一个进行插入操作,并设置保存点,另一个进行查看操作

设置保存点的方法:

savepoint 名称;

如上,这是首先对emp员工表进行插入,每插入一条数据就设置一个保存点,当三条语句全部插入后再右边可以进行查看

这个时候,如果我后悔插入关羽这条消息了,就可以使用事务回滚,如下SQL语句进行回滚到s2

rollback to 名称;

此时在进行查看就会发现关羽这条消息不见了

也可以回滚到s1让张飞也不见

接着我们在进行插入

如果想一次性回滚到最开始可以使用rollback,这样就在右侧看不到任何记录了

接着我们在进行插入数据,这个时候直接commit提交数据,这个时候尽管在进行回滚在右边仍然能看到数据,此时左边的事务就是完成了,其修改就是永久了的,这就是事务的持久性,就不能进行事务回滚了

综上所述:

  • 使用begin/start transaction启动一个事务
  • 使用commi提交一个事务
  • 使用savepoint设置一个保存点
  • 使用rollback to 回到指定一个保存点
  • 使用rollback回滚到最开始

四、事务崩溃:

原子性:

首先在员工表中是存在如下信息的,接着启动一个事务进行测试:

如上,首先在左侧事务进行插入一个数据,在右侧是能够看到的,此时是处于读未提交的隔离性中,但是在左侧的MySQL崩溃后,没有及时的进行commit提交,这个时候会回滚到当前事务的最开始,此时在右侧进行查询就会查询不到新插入的语句,这也保证了事务的原子性

持久性:

那么如果在事务崩溃前进行commit提交了呢?

如上,在MySQL崩溃前进行commit提交后,尽管MySQL崩溃了,但是依然能够看到上一个事务进行插入的数据,这正是因为事务的持久性,如果事务提交后,其修改的数据是永久的

五、自动提交和手动提交:

这里的自动提交和begin的启动事务是无关的,事务必须使用commit命令进行手动提交,数据才会被持久化

那么自动提交和手动提交有什么区别呢?

首先查看当前事务的提交方式:

show variables like'autocommit';

这是自动提交的,并且此时有着如下的一张表:

接着在左侧进行删除表中的数据,然后将左侧的客户端崩溃,发现该员工表中的对应数据被删除了

接着仅仅将提交方式改为手动提交,其余动作不变

set autocommit=0;

接着在左侧进行删除表中的数据,然后将左侧的客户端崩溃,发现该员工表中的对应数据并没有被删除

综上所述:

全局变量autocommit影响的是单SQL语句,在InnoDB中,一条SQL语句会被封装成一个事务,这个事务就需要根据autocommit的大小来进行自动提交或者手动提交

六、事务的隔离性:

怎么理解:

MySQL在启动后,可能会被多个客户(进程或者线程)进行访问,都是以事务为单位进行访问的,一个事务又是由多条SQL语句组成的,那么这些SQL语句在执行的时候可能会访问同一张表,那么MySQL为了保证在执行的过程中一个事务不被其他事务所干扰,于是就有了事务的隔离性,与隔离级别

隔离级别有以下四种:

READ UNCOMMITTED(读未提交):读到了别人未提交的数据,在这个级别下,事务中的修改,即使没有提交,对其他事务也是可见的,这个级别会导致脏读,即一个事务可以读取到另一个事务未提交的数据

READ COMMITTED(提交读):读别人提交了的数据,在这个级别下,一个事务只能看见已经提交事务所做的修改,这可以防止脏读,但是仍然可能发生不可重复读,不可重复读是指在同一个事务中,多次读取同一数据集合时,由于其他事务的介入,导致前后两次读取结果不一致

REPEATABLE READ(可重复读):无论别的事务是否提交修改后的数据,只有当前事务也提交后才能够看到之前别的事务所修改的数据,这是MySQL的默认事务隔离级别。在这个级别下,保证在同一个事务中多次读取同样记录的结果是一致的,因此解决了不可重复读的问题。但是,仍可以发生幻读,即当某个事务在处理某个范围内的记录时,另一个事务插入了新的记录,导致原本的查询结果集发生了变化

SERIALIZABLE(可串行化):这是最高的隔离级别,所有CURD必须按照到来的顺序一个一个执行,在SERIALIZABLE级别下,事务的执行会通过锁定参与事务的所有数据来实现,从而完全避免脏读,不可重复读以及幻读的问题,这意味着事务的执行会像顺序执行一样,一个接一个地串行化执行,从而保证了数据的一致性,但是,这种级别的性能开销最大,因为它需要对所有相关的数据行加锁

隔离级别示例:

隔离级别在MySQL中的表现有两种,分别是全局隔离级别会话隔离级别

查看全局隔离级别:

查询全局事务隔离级别,即MySQL服务启动后所有新会话的默认隔离级别

select @@global.transaction_isolation;

查看会话隔离级别:

select @@transaction_isolation;
// 或者
select @@session.transaction_isolation;

查询当前会话的事务隔离级别,若会话未主动修改过隔离级别,则继承全局值

设置隔离级别:

set [session | global] transaction isolation level {read uncommitted | read committed | repeatable read | serializable}

如上,其中session表示设置会话隔离级别,global表示设置全局隔离级别

后面的{ }中,在四个中选一个作为设置后的隔离级别

注意:

  • 设置会话的隔离级别只会影响当前会话,新起的会话依旧采用全局隔离级
  • 设置全局隔离级别会影响后续的新会话,但当前会话的隔离级别没有发生变化,如果要让当前会话的隔离级别也改变,则需要重启MySQL

读未提交:

如下两个终端中,均是读未提交,并且有如下数据的员工表

那么在左右两边开启事务,并且先进行插入一条数据,并没有进行提交,在右边是能够看到的,这就是读到了别的事务未提交的数据,这种情况叫做脏读,是不合理的

并且此时rollback回滚后发现所读到的数据也回滚了

读提交:

先将隔离级别修改为读提交

接着做和上一个步骤一样的,观察结果:

如上,当进行插入后,发现在右边并未查到,但是像下面那样,将左边的事务提交后,发现此时就能够看到了

这就是读别人提交后的数据,这就解决了脏读的问题,但是又出现了不可重复读的问题,也就是右边在一直查询,这样会在某个查询前后出现查询不一致问题,这就导致了右边的事务不可重复读

在实际应用中,这个不可重复读会存在问题的,比如在一个公司中发年终奖前后,如果一个员工在统计工资区间中,另一个员工突然又经过老板同意给公司的某个员工加上薪资,此时就可能会存在同一个员工在奖品区间中出现两次,这是不合理的

所以这个不可重复读,在实际应用中会存在问题的

可重复读:

首先将隔离级别修改为可重复度

接着启动事务,然后在左边进行表的修改,当执行完后在右边再次进行查看,发现右边没有被修改

接着将左边的事务进行提交,此时在进行查看发现右边的表依然没有被修改

最后将右边的事务也提交了,此时在进行查询就能够看得见了

像上边这种,在一个事务中,一直进行查询读,尽管别的事务对同一张表后进行修改,此时依然是看不到这个修改的,直到当前事务也被提交后才能进行看到,也就是说,在可重复读的条件下,在一个事务中进行查询的结果总是一致的

这种隔离级别是MySQL默认的,也是最常使用的

一般的数据库在可重复读隔离级别下,update数据是满足可重复读的,但insert数据会存在幻读问题,因为隔离性是通过对数据加锁完成的,而新插入的数据原本是不存在的,因此一般的加锁无法屏蔽这类问题,但是在MySQL中是解决了这类问题的

幻读:一个事务在执行过程中,相同的select查询得到了新的数据,这种现象叫做幻读

串行化:

首先依然是将隔离级别修改为串行化:

然后启动事务,然后在两边都进行查操作,发现都能够进行查看

但是此时如果有一方进行修改表的操作,会被阻塞

如果长时间没有响应就会报错,如果在阻塞中,另一个事务提交了,此时就不会阻塞了

但是两边查询的结果不一样,直到左边的事务也提交

对于串行化,其效率非常低,在开发中几乎不会使用

对于隔离级别:隔离级别越严格,安全性越高,但数据库的并发性能也就越低,在选择隔离级别时往往需要在两者之间找一个平衡点

七、拓展知识:

数据库的并发场景:

  • 读-读并发:不存在任何问题,不需要并发控制
  • 读-写并发:有线程安全问题,可能会存在事务隔离性问题,可能遇到脏读 幻读 不可重复读
  • 写-写并发:有线程安全问题,可能存在更新丢失问题,第一类更新丢失,第二类更新丢失

这里最值得讨论的是读-写并发,读-写并发是数据库当中最高频的场景,在解决读-写并发时不仅需要考虑线程安全问题,还需要考虑并发的性能问题

接下来要了解事务的隔离是怎么做到的,RC和RR的底层区别在哪?事务回滚又是怎么做到的,接下来需要知道些前置知识:

当一个事务启动的时候,MySQL会为其设置事务ID,每个事务都要有自己的事务ID,可以根据事务的大小,来决定事务到来的先后顺序

mysqld可能会面临处理多个事务的情况,事务也有自己的生命周期,mysqld要对事务进行管理,先描述,再组织,所以事务在mysqld中一定是对应的一个或者一套结构体对象

三个隐藏字段:

MySQL在给我们建表的时候,除了我们在SQL语句中自主创建的字段,还会有三个默认隐藏的字段的

DB_TRX_ID :6 byte,表示最后一次对这个表进行操作的事务ID
DB_ROLL_PTR : 7 byte,在MySQL中,进行修改数据并不是简简单单的修改就行了,还需要将这个数据进行保存,这样在进行事务回滚的时候能够找到历史数据,这就是指向上一个版本的指针
DB_ROW_ID : 6 byte,隐含的自增ID(隐藏主键),如果数据表没有主键, InnoDB 会自动以DB_ROW_ID 产生一个聚簇索引

undo日志:

这是回滚日志,用于对已经执行的操作进行回滚,MySQL会为undo日志开辟对应的缓冲区,用于存储日志相关的信息,必要时会将缓冲区中的数据刷新到磁盘

关于上图,操作系统之上是应用层,然后在应用层上的MySQL中有一个buffer pool空间,在这个空间里面就有我们的undo日志

事实上,undo log就是MySQL中的一段缓冲区,用来记录MySQL中事务回滚的操作的

MVCC多版本控制:

首先我们有如下一串数据

这串数据我们创建之后,就是在B+树中的叶子结点中的,我们又知道这个叶子节点是被加载到buffer pool中的,此时后来的一个事务到来,将该数据的age修改为18

这个时候不是简单的修改,

1、要先对访问这条记录进行加锁,
2、将这个原本的记录复制一份到undo log中,
3、将表中的数据进行修改,将age改为18,
4、此时尽管是只修改了一个字段,但是后面隐藏的字段中修改该记录的事务ID也要被修改为新到来的事务ID,这里假设为11,并且回滚指针也不在指向空,要指向undo log中被复制的原本数据
5、最后提交事务,释放锁即可

同样的道理,又来了一个事务,将name改为李四

这样,这些历史数据就像链表一样串起来,就有了一个版本链,当进行事务回滚的时候,需要回滚到哪个版本,就能够通过这个版本链找到对应的版本了,直接找到版本后覆盖当前数据即可,所谓的创建保存点就可以理解为给某些版本做标记,方便查找回滚

这种多版本控制就叫做MVCC多版本控制,并且在undo log中的一个个的历史版本就称为一个个的快照

周边问题:

那么上述都是修改才有的版本链,那么Delete和INSERT呢?

Delete的数据也会形成版本链的,在MySQL中Delete删除不是真的删了,本质是通过修改数据中的某个比特位将其置为删除,此时就相当于将这行数据进行删除了,如果回滚就是将表示存在还是不存在的比特位修改即可,这样是能够形成版本链的

INSERT操作本身不会形成版本链,但它为后续的UPDATE或DELETE操作提供了初始版本,版本链的形成必须依赖对同一行的多次修改,因此,INSERT是版本链的起点,但非版本链本身

当前读与快照读

当前读:读取最新的记录,就是当前读,增删改,都叫做当前读,select也可能当前读

快照读:读取历史版本,就叫做快照读

对数据进行CURD的时候的加锁问题

当对表进行CURD的时候,此时有两种情况,一个是对当前数据进行修改,一个是对历史数据进行修改,当对当前数据进行修改的时候,可能是CURD中的任意一种情况,此时就需要进行加锁保护,但是对历史数据修改的时候只可能是select,为快照读,就不需要加锁,毕竟历史版本不会被修改,也就是可能并发执行,提高效率

undo log中的版本链何时才会被清除?

unod log存在的意义是进行回滚操作和进行快照读,所以当事务提交后,且所有依赖该版本的事务已完成此时才会将undo log中的版本链清除

read view:

当我们某个事务执行快照读的时候,会对该记录创建一个Read View读视图,记录并维护系统当前活跃事务的ID,read view是一个类,与事务的关系就类似于进程地址空间和PCB,根据这个Read View来判断,当前事务能够看到该记录的哪个版本的数据

Read View是一个数据结构,记录当前事务执行一致性读时的可见性上下文,它决定了哪些数据版本对当前事务是可见的,从而避免脏读,不可重复读等问题

Read View主要由下述字段组成

字段名含义说明
creator_trx_id创建该Read View的事务ID(即当前事务ID)
up_limit_id最小活跃事务ID(即当前系统中最小的未提交事务ID)
low_limit_id当前系统最大事务ID + 1(即系统中尚未分配的事务ID)
m_ids当前系统中所有活跃事务(未提交事务)的ID列表
m_low_limit_no最小的Undo Log编号(用于InnoDB的Purge机制)

注意:

Read View是事务可见性的一个类,不是事务创建出来,就会有Read View,而是当这个已经存在的事务首次进行快照读的时候,MySQL形成的Read View

事务ID是依次增大的

当进行一次快照读的时候,此时可以将事务ID分为三种情况

事务ID小于up_limit_id,up_limit_id已经是当前系统中最小的未提交事务ID,如果事务ID比它还要小就证明此刻生成Read View时,该事务一定是提交了的

事务ID大于low_limit_id,low_limit_id是系统中尚未分配的事务ID,所以当事务ID大于low_limit_id时,该事务是生成Read View时还未启动的事务ID

事务ID在这两者之间,这些事务就需要通过判断m_ids来进行判断是否提交,注意:这里的快照事务ID不一定是连续的,毕竟事务的时间长短是不一样的,有可能提前启动的事务,结束得晚,后启动的事务结束得早或晚都有可能

一个事务在进行读操作时,只应该看到自己或已经提交的事务所作的修改,因此我们可以根据Read View来判断当前事务能否看到另一个事务所作的修改

 RC VS RR:

关于RC和RR,他们本质区别就是:

RC在每一次查询的时候都会生成一次Read View,每次select都是快照读,因此每次快照读时都能读取到被提交了的最新的数据

RR只有在第一次select的时候才会生成一次Read View,之后的select都用这个Read View,因此当前事务看不到第一次快照读之后其他事务所作的修改

RR级别下快照读只会创建一次Read View,所以RR级别是可重复读的,而RC级别下每次快照读都会创建新的Read View,所以RC级别是不可重复读的

接下来通过两个实验理解理解:

首先将事务隔离级别设置成可重复度

在第一个实验中,我们先让二者都进行快照读,然后在左边进行修改提交,再在右边进行查看

如上,无论怎么进行查看都是看不见修改的,这也符合可重复读的特性

在第二个实验中,我们先在左边进行修改提交,再在右边进行查看

这时发现右边能够查看到左边的修改了

为什么呢?

实验一中,在最开始就进行了快照读,此时左右都属于活跃事务,都是在中间的,那么无论左边怎么修改,右边的都看不到

实验二中,左边先进行修改后提交,右边在进行快照读,此时左边的事务ID就小于最小活跃事务ID,右边事务中快照读生成的Read View中的m_ids就一定没有左边的事务ID,此时左边的事务ID就比右边事务的up_limit_id还要小,或者是在up_limit_id和low_limit_id之间但是没在m_ids里面,无论那种情况都能够被右边的事务所看到

那么RC呢?

RC和RR的本质区别就在于RC在每次进行快照读的时候,都是生成新的快照了,那么low_limit_id就是当前系统下最大的事务ID,所以就能保证只要其他事务commit了, 其他事务就不是活跃事务了, 那么就只剩下了在up_limit_id和low_limit_id之间但是没在m_ids里面这种情况,也就一定能看到了别的事务的修改了

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

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

相关文章

C++STL——stack,queue

stack与queue 前言容器适配器deque 前言 本篇主要讲解stack与queue的底层,但并不会进行实现,stack的接口 queue的接口 ,关于stack与queue的接口在这里不做讲解,因为通过前面的对STL的学习,这些接口都是大同小异的。 …

STM32智能手表:基于FreeRTOS

引言 随着物联网和可穿戴设备的快速发展,智能手表作为典型代表,集成了传感器数据采集、实时显示、无线通信等多项功能。本文将深入剖析一个基于STM32和FreeRTOS的智能手表项目,从硬件架构到软件设计,逐步讲解如何构建一个完整的嵌…

leetcode504.七进制数

标签:进制转换 机试真题 给定一个整数 num,将其转化为 7 进制,并以字符串形式输出。 示例 1: 输入: num 100 输出: "202" 示例 2: 输入: num -7 输出: "-10" 思路:求n进制就是循环取余数,…

中国古代史2

夏朝(公元前2070-公元前1600年) 1.禹建立了我国历史上第一个奴隶制国家–夏朝,定都阳城。禹传启,世袭制代替禅让制。 2.夏代都城:二里头遗址位于今河南洛阳偃师二里头村。发现了大型绿松石龙形器,被命名为…

死锁的形成

死锁的形成 背景学习资源死锁的本质 背景 面试可能会被问到. 学习资源 一个案例: https://www.bilibili.com/video/BV1pz421Y7kM 死锁的本质 互相持有对方的资源. 存在资源竞争都没有释放. 可能出现死锁. insert into demo_user (no, name) values (6, ‘test1’) on dupl…

MapReduce架构-打包运行

(一)maven打包 MapReduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序(例如:jar…

C++发起Https连接请求

需要下载安装openssl //stdafx.h #pragma once #include<iostream> #include <openssl/ssl.h> #include <openssl/err.h> #include <iostream> #include <string>#pragma comment(lib, "libssl.lib") #pragma comment(lib, "lib…

ADI ADRV902x的射频模拟信号输入输出端口的巴伦匹配

根据规格书可知ADRV902x系列的&#xff1a; 【1】输入阻抗是100Ω差分&#xff0c;包括RX端口和ORX端口。 【2】输出阻抗是50Ω差分&#xff0c;包括TX端口。 而射频系统通常采用50Ω的单端走线&#xff0c;所以需要通过正确规格的巴伦完成差分转单端/单端转差分的处理。 巴…

【计算机视觉】OpenCV实战项目:Athlete-Pose-Detection 运动员姿态检测系统:基于OpenCV的实时运动分析技术

运动员姿态检测系统&#xff1a;基于OpenCV的实时运动分析技术 1. 项目概述1.1 技术背景1.2 项目特点 2. 技术架构与算法原理2.1 系统架构2.2 核心算法2.3 模型选择 3. 项目部署与运行指南3.1 环境准备硬件要求软件依赖 3.2 项目配置3.3 运行项目基本运行模式高级参数 4. 常见问…

linux perf top分析系统性能

1,看到内核宏是否支持perf功能 perf top -g 查看linux 内核宏定义 CONFIG_PERF_EVENTS=y CONFIG_HAVE_PERF_EVENTS=y CONFIG_FRAME_POINTER=y # 确保帧指针支持以捕获完整堆栈 2,使用perf top -g 报错 Access to performance monitoring and observability operations is l…

gin + es 实践 08

自动扩缩容 本文档详细介绍如何在Kubernetes环境中实现Go-ES应用的自动扩缩容&#xff0c;包括水平Pod自动扩缩容(HPA)、垂直Pod自动扩缩容(VPA)和集群自动扩缩容。 1. 自动扩缩容概述 自动扩缩容是指根据负载变化自动调整计算资源的过程&#xff0c;主要目标是&#xff1a;…

【比赛真题解析】混合可乐

这次给大家分享一道比赛题:混合可乐。 洛谷链接:U561549 混合可乐 【题目描述】 Jimmy 最近沉迷于可乐中无法自拔。 为了调配出他心目中最完美的可乐,Jimmy买来了三瓶不同品牌的可乐,然后立马喝掉了一些(他实在是忍不住了),所以 第一瓶可口可乐最大容量为 a 升,剩余 …

AI Coding的发展之路:从概念到改变世界的旅程

AI Coding的发展之路:从概念到改变世界的旅程 引言:当代码开始自己写代码 还记得第一次接触编程时的手足无措吗?那些复杂的语法规则、难以捉摸的逻辑错误,让多少人在深夜对着屏幕抓狂。而今天,一个全新的时代正在来临——AI开始帮我们写代码了。这不是科幻电影,而是正在…

基于DQN的自动驾驶小车绕圈任务

1.任务介绍 任务来源: DQN: Deep Q Learning &#xff5c;自动驾驶入门&#xff08;&#xff1f;&#xff09; &#xff5c;算法与实现 任务原始代码: self-driving car 最终效果&#xff1a; 以下所有内容&#xff0c;都是对上面DQN代码的改进&#…

Spring 必会之微服务篇(2)

经过上一篇文章的介绍,应该对微服务有了基本的认识,以及为什么要用微服务和微服务要面临的挑战和对应的解决问题,这一期继续聊聊关于微服务的相关知识。 服务拆分 为什么拆 对于大多数的小型项目来说,一般是先采用单体架构,但是随着后面的用户规模变大,业务越来越复杂…

word换行符和段落标记

换行符&#xff1a;只换行不分段 作用&#xff1a;我们需要对它进行分段&#xff0c;但它是一个信息群组&#xff0c;我希望它们有同样的段落格式&#xff01; 快捷键&#xff1a;shiftenter 段落标记&#xff1a;分段 快捷键&#xff1a;enter 修改字体格式或段落格式 …

JSON|cJSON 介绍以及具体项目编写

一、JSON介绍 JSON&#xff08;JavaScript Object Notation 即JavaScript对象表示法&#xff09;是一种轻量级的数据交换格式。采用完全独立于编程语言的文本格式来存储和表示数据。 JSON是一种数据交换格式.JSON独立于编程语言(你不必学习JavaScript).JSON表达数据的方式对通…

【LLaMA-Factory】使用LoRa微调训练DeepSeek-R1-Distill-Qwen-7B

【LLaMA-Factory】使用LoRa微调训练DeepSeek-R1-Distill-Qwen-7B 本地环境说明禁用开源驱动nouveau安装nvidia-smi安装Git环境安装Anaconda(conda)环境下载DeepSeek-R1-Distill-Qwen-7B模型安装LLaMA-Factory下载LLaMA-Factory安装LLaMA-Factory依赖修改环境变量安装deepspeedA…

初始图形学(7)

上一章完成了相机类的实现&#xff0c;对之前所学的内容进行了封装与整理&#xff0c;现在要学习新的内容。 抗锯齿 我们放大之前渲染的图片&#xff0c;往往会发现我们渲染的图像边缘有尖锐的"阶梯"性质。这种阶梯状被称为"锯齿"。当真实的相机拍照时&a…

vllm笔记

目录 vllm简介vllm解决了哪些问题&#xff1f;1. **瓶颈&#xff1a;KV 缓存内存管理低效**2. **瓶颈&#xff1a;并行采样和束搜索中的内存冗余**3. **瓶颈&#xff1a;批处理请求中的内存碎片化** 快速开始安装vllm开始使用离线推理启动 vLLM 服务器 支持的模型文本语言模型生…