MySQL---事务管理

1.关于事务

  理解和学习事务,不能只站在程序猿的角度来理解事务,而是要站在使用者(用户)的角度来理解事务。

比如支付宝转账,A转了B100块前,在程序猿的角度来看,是两条update操作,A -100块,B +100块。但是站在使用者的角度,这就是一条转账逻辑。

事务就是一组 DML 语句组成,这些语句在逻辑上存在相关性,这一组 DML 语句要么全部成功,要么全部失败,是一个整体。MySQL 提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。
事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。

事务具有四个属性:

原子性: 一个事务( transaction )中的所有操作,要么全部完成,要么全部不完成,不会结束在中
间某个环节。事务在执行过程中发生错误,会被回滚( Rollback )到事务开始前的状态,就像这个
事务从来没有执行过一样。

一致性: 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
(也就是说,一个事务在开始之前和和事务结束之后,它的结果是可预期的。比如A转给B100块,如果成功了,那么A -100块,B +100块;如果失败了,那么A,B都不变。不会出现,A -100,但是B没变的这种情况。)
虽然说一致性是事务的一大属性,但是MYSQL并没有从技术层面上来实现它,一致性是通过原子性,隔离性,持久性来保证的。

隔离性: 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务
并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read
uncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化
Serializable

持久性: 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

 上面四个属性,可以简称为 ACID

原子性( A tomicity ,或称不可分割性)

一致性( C onsistency

隔离性( I solation ,又称独立性)

持久性( D urability )。

 MYSQL中存在的大量的事务,它们也是需要先被描述,然后再组织的,这样管理起来的。其实就是将一批SQL语句打包成一个事务对象,将这个对象放在事务执行的事务列表里。

2.为什么要存在事务?

事务被 MySQL 编写者设计出来 , 本质是为了当应用程序访问数据库的时候 , 事务能够简化我们的编程模型 ,不需要我们去考虑各种各样的潜在错误和并发问题. 可以想一下当我们使用事务时 , 要么提交 , 要么回滚 , 我们不会去考虑网络异常了, 服务器宕机了 , 同时更改一个数据怎么办对吧 ? 因此事务本质上是为了应用层服 务的 . 而不是伴随着数据库系统天生就有的 .

后面我们将MYSQL的一行信息称为一条记录。

3.了解事务的提交方式 

在MYSQL的两大存储引擎Innodb和MYISAM,只有Innodb支持事务。

事务的提交方式有两种:

1.自动提交。

2.手动提交。

我们可以查看我们的MYSQL的提交方式

mysql> show variables like 'autocommit';

ON表示了它是自动提交的。

我们也可以设置它的提交方式

set autocommit=0;

show variables like 'autocommit';

0是关闭,1是打开。 

4.准备工作
 

我们知道,mysqld是一个网络服务,那么我们可以查看

netstat -nltp

 

可以看到,端口号为3306就是我们的mysql网络服务。 

另外可以查看我们mysql和mysqld文件所在的位置

首先我们先将隔离级别设置成为读未提交

set global transaction isolation level read uncommitted;

 但是设置好后,需要登录mysql会话才能生效

此时我们输入

select @@tx_isolation;

此时的隔离级别就是读未提交

然后创建一张测试表

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
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

 5.事务的基本操作

这里我们看到事务是自动提交的。

 有两种方式可以开启事务

start transaction;

begin;

推荐 使用begin 

设置保存点(比如p1)

savepoint p1;

这是可以方便我们定向回滚的。比如

在插入一条数据后

insert into account values(1,'张三',123.2);

我们看到另一个开启事务的会话可以直接看到更新的结果

然后我们回到插入数据前的保存点p1。

rollback to p1;

 

数据就消失了

也可以直接

rollback;

 直接回到最开始的地方。

如果想结束事务

commit;

事务回滚只能在事务运行期间,如果事务已经提交了,就不能回滚了。

6.事务异常验证与产出的结论 

当mysql遇到异常情况(比如强制关闭会话),事务会自动回滚。

但是如果事务已经commit了,那么mysql的数据就不会受到影响,已经持久化了。

另外关于事务的自动提交,如果我们手动开启事务,比如使用begin,那么即便mysql的设置是自动提交,手动开启的事务=必须要手动提交。那么此外,所有的SQL语句都是自动开启的事务,因为又是手动提交,所以每一条SQL都是一个事务,并且执行完就提交了。 

7.事务隔离性理论

数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性

数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

隔离级别:(由低到高)

读未提交【 Read Uncommitted : 在该隔离级别,所有的事务都可以看到其他事务没有提交的
执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多
并发问题,如脏读,幻读,不可重复读等,我们上面为了做实验方便,用的就是这个隔离性。
就比如说,两个事务同时运行,一方对表插入了数据,还没有提交,另一个事务直接就能查看到更新的结果。

读提交【 Read Committed :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL
认的)。它满足了隔离的简单定义 : 一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select , 可能得到不同的结果。

比如两个事务同时运行,其中一个事务对表插入了数据,只有提交了,另一个事务才能查看到更新的结果。 

可重复读【 Repeatable Read : 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行
中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。

还是这两个事务,其中一个事务对表插入了数据,但是就算它提交了,另一个事务也看不到更新的结果,只有当它也结束了才能看得到。 

串行化【 Serializable : 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,
从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争
(这种隔离级别太极端,实际生产基本不使用)

 8.事务隔离级别的设置和查看。

1.查看隔离级别:

有三种方式:

-- 查看
mysql> SELECT @@global.tx_isolation; --查看全局隔级别
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SELECT @@session.tx_isolation; --查看会话(当前)全局隔级别
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ |
+------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SELECT @@tx_isolation; --是上一种的简写方式,也是查看当前会话的
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

 2.设置隔离级别

中括号表示可以省略,但是这里不建议

-- 设置当前会话 or 全局隔离级别语法
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ
COMMITTED | REPEATABLE READ | SERIALIZABLE}

比如将当前会话的隔离级别改为 读-提交

set session transaction isolation level read committed;

 9.事务隔离级别--读未提交

这种隔离级别几乎没有加锁,虽然效率高,但是问题也很多,严重不推荐使用。

读-未提交会产生脏读现象:

即一个事务在执行时,可以看到另一个事务的更新,但是没有提交的数据,就是脏读。

10.事务隔离级别--读提交 

在这个隔离级别下,一个事务在执行时,可以看到其他事务更新并且提交后的数据。

这样会带来一个后果:

就是在同一个事务内部,每次查询数据时,根据时间段的不同,可能会查询到不一样的结果,我们把这个现象称为不可重复读。 

事务的运行要保证其原子性,不可重复读会破坏原子性。

11.事务隔离级别--可重复读

可重复读解决了两个并发运行的事务,一方提交,不会影响另一个未提交的事务。 

多次查看,发现终端A在对应事务中insert的数据,在终端B的事务周期中,也没有什么影响,也符合可重复的特点。但是,一般的数据库在可重复读情况的时候,无法屏蔽其他事务insert的数据(为什么?因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存在,那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读
(phantom read)。很明显,MySQL在RR级别的时候,是解决了幻读问题的(解决的方式是用Next-Key锁(GAP+行锁)解决的。

 

也就是说,幻读问题是insert数据操作时伴随出来的问题,属于不可重复度的情况的一种。

12.事务隔离级别--串行化 

对所有的操作进行加锁,也就是将所有的事务进行串行化,这样就不会存在安全问题,但是效率很低。

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

MYSQL默认的隔离级别是可重复读,并且解决了幻读的问题。 

13.关于一致性的理解 

一致性其实不是技术层面的概念,而是使用层面的概念。 

比如有一个事务在运行时,操作到一半时出现了异常,导致事务没有完成,那么那些完成了一半的操作使数据库处于一种不正确的状态,也就是不一致的状态。

所以:

事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务
成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中
断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一
致)的状态。因此一致性是通过原子性来保证的。

其实一致性和用户的业务逻辑强相关,一般 MySQL 提供技术支持,但是一致性还是要用户业务逻辑做支撑(比如要保证SQL是对的),也就是,一致性,是由用户决定的。

而技术上,通过AID保证C 。 

14.MVCC机制 

数据库的并发有三种场景:

- :不存在任何问题,也不需要并发控制

- 写 :有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读

- :有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失

这里重点介绍读写。

多版本并发控制( MVCC )是一种用来解决 -写冲突 无锁并发控制 。

MYSQL为事务分配单向增长的事务 ID ,为每个修改保存一个版本,版本与事务 ID 关联,读操作只读该事务开始前的数据库的快照。 所以 MVCC 可以为数据库解决以下问题。
事务ID越小,说明这个事务来得越早。可以根据事务ID的大小来判断事务到来的顺序。
mysqld可能会同时面临处理多个事务的情况,事务也有自己的生命周期,mysqld要将这些事务管理起来,就需要先描述,再组织,所以在mysqld中一定是有一套对应的结构体/类对象,事务也有自己的结构体。

理解MVCC需要的三个前提知识:

3 个记录隐藏字段

undo 日志

Read View

3个记录隐藏字段:

其实我们在建表的时候,mysql会给我们加上3个隐藏字段。

DB_TRX_ID 6 byte ,最近修改 ( 修改 / 插入 ) 事务 ID ,记录创建这条记录 / 最后一次修改该记录的事务ID

DB_ROLL_PTR : 7 byte ,回滚指针,指向这条记录的上一个版本(简单理解成,指向历史版本就
行,这些数据一般在 undo log 中)

DB_ROW_ID : 6 byte ,隐含的自增 ID (隐藏主键),如果数据表没有主键, InnoDB 会自动以
DB_ROW_ID 产生一个聚簇索引 。如果我们指明了主键,那么就用我们指明的这个主键来建立索引。

补充:实际还有一个删除flag隐藏字段, 既记录被更新或删除并不代表真的删除,而是删除flag变了 

所以我们删除一条记录其实并不是真的把它删除了,而是改变了它的flag。这也是典型的用空间换时间的一种做法,并且如果出现了误删操作,还可以进行还原。

undo日志(log)

MYSQL将来是以服务进程的方式,在内存中运行。我们之前所讲的所有机制:索引,事务,隔离性,日志等,都是在内存中完成的,即在 MySQL 内部的相关缓冲区中,保存相关数据,完成各种判断操作。然后在合适的时候,将相关数据刷新到磁盘当中的。

所以可以简单理解为,undolog就是mysql中的一段内存缓冲区。

模拟MVCC的过程:

现在有一个事务 10( 仅仅为了好区分 ) ,对 student 表中记录进行修改 (update) :将 name( 张三 ) 改成
name( 李四 )
事务 10, 因为要修改,所以要先给该记录加行锁。
修改前,现将改行记录拷贝到 undo log 中,所以, undo log 中就有了一行副本数据。 ( 原理就是写
时拷贝 )
所以现在 MySQL 中有两行同样的记录。现在修改原始记录中的 name ,改成 ' 李四 ' 。并且修改原始
记录的隐藏字段 DB_TRX_ID 为当前 事务 10 ID, 我们默认从 10 开始,之后递增。而原始记录的回滚指针 DB_ROLL_PTR 列,里面写入 undo log 中副本数据的地址,从而指向副本记录,既表示我的上一个版本就是它。
事务 10 提交,释放锁。

 图中李四是最新的记录。

现在又有一个事务 11 ,对 student 表中记录进行修改 (update) :将 age(28) 改成 age(38)
事务 11, 因为也要修改,所以要先给该记录加行锁。
修改前,现将改行记录拷贝到 undo log 中,所以, undo log 中就又有了一行副本数据。此时,新的
副本,我们采用头插方式,插入 undo log
现在修改原始记录中的 age ,改成 38 。并且修改原始记录的隐藏字段 DB_TRX_ID 为当前 事务 11 的ID。而原始记录的回滚指针 DB_ROLL_PTR 列,里面写入 undo log 中副本数据的地址,从而指向副本记录,既表示我的上一个版本就是它。
事务 11 提交,释放锁。
这样,我们就有了一个基于链表记录的历史版本链。所谓的回滚,无非就是用历史数据,覆盖当前数据。
上面的一个一个版本,我们可以称之为一个一个的快照。

如果一个事务提交,undo log就清理掉了,自然也就不能回滚了。

一些思考:

上面是以更新( `upadte` )主讲的 , 如果是 `delete` 呢?一样的,别忘了,删数据不是清空,而是设置 flag为删除即可。也可以形成版本。

如果是 `insert` 呢?因为 `insert` 是插入,也就是之前没有数据,那么 `insert` 也就没有历史版本。但是 一般为了回滚操作,insert 的数据也是要被放入 undo log 中(此时对应的回滚操作就是delete),如果当前事务 commit 了,那么这个 undo log 的历史 insert 记录就可以被清空了。

总结一下,也就是我们可以理解成, `update` `delete` 可以形成版本链, `insert` 暂时不考虑。

那么 `select` 呢?
首先, `select` 不会对数据做任何修改,所以,为 `select` 维护多版本,没有意义。不过,此时有个问题,就是:
select 读取,是读取最新的版本呢?还是读取历史版本?

当前读:读取最新的记录,就是当前读。增删改,都叫做当前读, select 也有可能当前读,比如: select lock in share mode(共享锁 ), select for update (这个好理解,我们后面不讨论)
快照读:读取历史版本 ( 一般而言 ) ,就叫做快照读。

我们可以看到,在多个事务同时删改查的时候,都是当前读,是要加锁的。那同时有 select 过来,如果也要读取最新版( 当前读 ) ,那么也就需要加锁,这就是串行化。
但如果是快照读,读取历史版本的话,是不受加锁限制的。也就是可以并行执行!换言之,提高了效率,即MVCC的意义所在。

所以是隔离级别决定了select是当前读还是快照读。

那为什么要有隔离级别呢?
事务都是原子的。所以,无论如何,事务总有先有后。

但是经过上面的操作我们发现,事务从 begin->CURD->commit ,是有一个阶段的。也就是事务有执行前,执行中,执行后的阶段。但,不管怎么启动多个事务,总是有先有后的。

那么多个事务在执行中, CURD 操作是会交织在一起的。那么,为了保证事务的 有先有后 ,是不是应该让不同的事务看到它该看到的内容,这就是所谓的隔离性与隔离级别要解决的问题。

15.read view理论 

Read View 就是事务进行 快照读 操作的时候生产的 读视图 (Read View) ,在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID( 当每个事务开启时,都会被分配一个ID, 这个 ID 是递增的,所以最新的事务, ID 值越大 )

Read View MySQL 源码中 , 就是一个类,本质是用来进行可见性判断的。 即当我们某个事务执行快照读(也就是select的操作)的时候,对该记录创建一个 Read View 读视图,把它比作条件 , 用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的 undo log 里面的某个版本的数据。

read view结构体中重要的字段

class ReadView {
// 省略...
private:
/** 高水位,大于等于这个ID的事务均不可见*/
trx_id_t m_low_limit_id;

/** 低水位:小于这个ID的事务均可见 */
trx_id_t m_up_limit_id;

/** 创建该 Read View 的事务ID*/
trx_id_t m_creator_trx_id;

/** 创建视图时的活跃事务id列表*/
ids_t m_ids;

/** 配合purge,标识该视图不需要小于m_low_limit_no的UNDO LOG,
* 如果其他视图也不需要,则可以删除小于m_low_limit_no的UNDO LOG*/
trx_id_t m_low_limit_no;

/** 标记视图是否被关闭*/
bool m_closed;

// 省略...
};

// 重点是这四个字段
m_ids; //一张列表,用来维护Read View生成时刻,系统正活跃的事务ID
up_limit_id; //记录m_ids列表中事务ID最小的ID(没有写错)
low_limit_id; //ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的
最大值+1(也没有写错)
creator_trx_id //创建该ReadView的事务ID

我们在实际读取数据版本链的时候,是能读取到每一个版本对应的事务 ID 的,即:当前记录的
DB_TRX_ID

那么,我们现在手里面有的东西就有,当前快照读的 ReadView 和 版本链中的某一个记录的

DB_TRX_ID
所以现在的问题就是,当前快照读,应不应该读到当前版本记录。

 

read view它生成对象后,只初始化一次。此时里面的字段m_ids表示的是当这个read view起来的时候,此时活跃的事务ID。那么有两种情况,是可以select到的:

1.当前创建该read view时的事务ID等于遍历到的记录的事务ID(DB_TRX_ID),说明是select自己,那么当然可以查看。

2.当初跟我们同时运行的事务,它们的事务ID可能比我们大,但是它们可能比我们先提交了,既然已经提交了,我们也可以查看。

那么,不能查看的也有两种情况:

1.正在运行的事务,我们不能查看,在m_ids中的。

2.当前的事务ID>=low_limit_id。说明是快照之后才提交的事务,也不应该看到。

read view是从版本链中遍历的,也就是undo log中遍历。 

我们可以看一下在mysql的源码中,对每次遍历的判断

 可见与我们刚刚分析的差不多,如果id小于最低水位,说明这些事务是在这个read view之前就提交了,如果id == 当前事务id,那么也返回true。

并且要注意:这个id是指我们从版本链中遍历到的事务的ID( DB_TRX_ID)。

如果id大于最高水位,说明这个事务是在read view之后创建的,肯定不能查看,所以返回false。

另外,如果m_ids是空的,说明此时就只有一个事务,当然能查看,所以也返回true。

总结:

read view是事务可见性的一个类,但是注意,它不是事务一创建出来就跟着有的(read view对象),而是当这个事务(已经存在)首次进行快照读的时候,mysql才会形成read view对象。

16.read view实验 

 现在有这样一条记录

然后有四个事务:

 根据事务id可以判断它们的创建的先后顺序,纵向代表它们的执行状态,并且可以看到事务4是先提交了的。

事务4的修改操作是:

修改name(张三)为name(李四)

注意:low_limit_id代表的是系统分配的最大的事务id 再 + 1。

那么此时事务2在进行快照读的时候,形成的read view对象的字段为:

//事务2的 Read View
m_ids; // 1,3
up_limit_id; // 1
low_limit_id; // 4 + 1 = 5,原因:ReadView生成时刻,系统尚未分配的下一个事务ID
creator_trx_id // 2

那么此时的版本链:

 因为只有事务4进行了修改并且提交,那么当事务2的read view创建时,读取该记录时,就会拿这个事务的DB_TRX_ID开始进行比较

//事务2的 Read View
m_ids; // 1,3
up_limit_id; // 1
low_limit_id; // 4 + 1 = 5,原因:ReadView生成时刻,系统尚未分配的下一个事务ID
creator_trx_id // 2
//事务4提交的记录对应的事务ID
DB_TRX_ID=4
//比较步骤
DB_TRX_ID(4)< up_limit_id(1) ? 不小于,下一步
DB_TRX_ID(4)>= low_limit_id(5) ? 不大于,下一步
m_ids.contains(DB_TRX_ID) ? 不包含,说明,事务4不在当前的活跃事务中。

//结论
故,事务4的更改,应该看到。
所以事务2能读到的最新数据记录是事务4所提交的版本,而事务4提交的版本也是全局角度上最新的版本

到这里我们也发现,这不就是之前说的RC(读提交)隔离级别吗?

17.RC和RR的本质区别

我们在select语句后面加上 lock in share mode,表示加共享锁的方式读取,是当前读,不加就是快照读。

在RR级别下,(可重复读),有两个事务同时运行

 图中我们发现,事务B在事务A提交前就进行了快照读,那么也就形成了read view,在事务A提交后,事务B再使用快照读依旧不能读到更新后的结果。

还有另一种情况:

两种情况的唯一不同就是,后者事务B是在事务A提交后才进行的快照读,此时就能读到更新的结果。这就是RR隔离级别。

结论:

事务中快照读的结果是非常依赖该事务首次出现快照读的地方,即某个事务中首次出现快照读,决
定该事务后续快照读结果的能力

 

delete 同样如此

 

所以read view的形成的时机不同,会影响事务的可见性!! 

所以RC与RR的本质区别:

正是 Read View 生成时机的不同,从而造成 RC,RR 级别下快照读的结果的不同

 

RR 级别下的某个事务的对某条记录的第一次快照读会创建一个快照及 Read View, 将当前系统活
跃的其他事务记录起来(此后就不会变了!)

 

此后在调用快照读的时候,还是使用的是同一个 Read View ,所以只要当前事务在其他事务提交更
新之前使用过快照读,那么之后的快照读使用的都是同一个 Read View ,所以对之后的修改不可
见;

 

RR 级别下,快照读生成 Read View 时, Read View 会记录此时所有其他活动事务的快照,这些事
务的修改对于当前事务都是不可见的。而早于 Read View 创建的事务所做的修改均是可见

 

而在 RC 级别下的,事务中,每次快照读都会新生成一个快照和 Read View, 这就是我们在 RC 级别下的事务中可以看到别的事务提交的更新的原因

 

总之在 RC 隔离级别下,是每个快照读都会生成并获取最新的 Read View ;而在 RR 隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个 Read View

 

正是 RC 每次快照读,都会形成 Read View ,所以, RC 才会有不可重复读问题。

 

顺便说下读未提交,它直接都不形成read view,所以什么都能看到。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PCDN技术如何提高内容分发效率?(贰)

PCDN技术通过以下方式提高内容分发效率: 1.利用用户设备作为分发节点:与传统的 CDN技术主要依赖中心化服务器不同&#xff0c; PCDN技术利用用户的设备作为内容分发的节点。当用户下载内容时&#xff0c;他们的设备也会成为内容分发的一部分&#xff0c;将已下载的内容传递给其…

项目部署_持续集成_Jenkins

1 今日内容介绍 1.1 什么是持续集成 持续集成&#xff08; Continuous integration &#xff0c; 简称 CI &#xff09;指的是&#xff0c;频繁地&#xff08;一天多次&#xff09;将代码集成到主干 持续集成的组成要素 一个自动构建过程&#xff0c; 从检出代码、 编译构建…

树状数组实现 查找逆序对

题意&#xff1a; 输入一个整数n。 接下来输入一行n个整数 。 1< < n ,且每个数字只会出现一次 题解&#xff1a; 按每个数字的大小存入树状数组 #include<bits/stdc.h> using namespace std; #define ll long long const int N10000; int arr[N]; ll a[N];…

Java中关于构造代码块和静态代码块的解析

构造代码块 特点&#xff1a;优先于构造方法执行,每new一次,就会执行一次 public class Person {public Person(){System.out.println("我是无参构造方法");}{System.out.println("我是构造代码块"); //构造代码块} }public class Test {public stati…

golang与以太坊交互

文章目录 golang与以太坊交互什么是go-ethereum与节点交互前的准备使用golang与以太坊区块链交互查询账户的余额使用golang生成以太坊账户使用golang生成以太坊钱包使用golang在账户之间转移eth安装使用solc和abigen生成bin和abi文件生成go文件使用golang在测试网上部署智能合约…

GD32MCU如何实现掉电数据保存?

大家在GD32 MCU应用时&#xff0c;是否会碰到以下应用需求&#xff1a;希望在MCU掉电时保存一定的数据或标志&#xff0c;用以记录一些关键的数据。 以GD32E103为例&#xff0c;数据的存储介质可以选择内部Flash或者备份数据寄存器。 如下图所示&#xff0c;片内Flash具有10年…

【综合能源】计及碳捕集电厂低碳特性及需求响应的综合能源系统多时间尺度调度模型

目录 1 主要内容 2 部分程序 3 实现效果 4 下载链接 1 主要内容 本程序是对《计及碳捕集电厂低碳特性的含风电电力系统源-荷多时间尺度调度方法》方法复现&#xff0c;非完全复现&#xff0c;只做了日前日内部分&#xff0c;并在上述基础上改进升级为电热综合电源微网系统&…

力扣习题--找不同

目录 前言 题目和解析 1、找不同 2、 思路和解析 总结 前言 本系列的所有习题均来自于力扣网站LeetBook - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 题目和解析 1、找不同 给定两个字符串 s 和 t &#xff0c;它们只包含小写字母。 字符串 t…

智能光伏开发都能用到什么软件和工具?

随着全球对可再生能源的日益重视和光伏技术的快速发展&#xff0c;智能光伏开发已成为推动能源转型的重要力量。在光伏项目的全生命周期中&#xff0c;从设计、建设到运营管理&#xff0c;各种软件和工具的应用发挥着至关重要的作用。 一、光伏系统设计软件 1、PVsyst PVsyst…

Python创建MySQL数据库

一、使用Docker部署本地MySQL数据库 docker run --restartalways -p 3307:3306 --name mysql -e MYSOL_ROOT_PASSWORDlms123456 -d mysql:8.0.25 参数解析: 用户名:root 密码:lms123456 端口:3307 二、在Pycharm开发工具中配置连接MySQL数据库 三、安装zdppy_mysql pip inst…

【LabVIEW学习篇 - 2】:LabVIEW的编程特点

文章目录 LabVIEW的编程特点图形编程天然并行运行基于数据流运行 LabVIEW的编程特点 图形编程 LabVIEW使用图形化的图形化编程语言&#xff08;G语言&#xff09;&#xff0c;用户通过在程序框图中拖放和连接各种节点&#xff08;Nodes&#xff09;来编写程序。每个节点代表一…

tobias实现支付宝支付

tobias是一个为支付宝支付SDK做的Flutter插件。 如何使用 你需要在pubspec.yaml中配置url_scheme。url_scheme是一个独特的字符串&#xff0c;用来重新启动你的app&#xff0c;但是请注意字符串“_”是不合法的。 在iOS端&#xff0c;你还需要配置并传入一个universal link。…

动手学深度学习(Pytorch版)代码实践 -循环神经网络-53语言模型和数据集

53语言模型和数据集 1.自然语言统计 引入库和读取数据&#xff1a; import random import torch from d2l import torch as d2l import liliPytorch as lp import numpy as np import matplotlib.pyplot as plttokens lp.tokenize(lp.read_time_machine())一元语法&#xf…

利用Redis bitmap 实现签到案例

数据库实现 设计签到功能对应的数据库表 CREATE TABLE sign_record (id bigint NOT NULL AUTO_INCREMENT COMMENT 主键,user_id bigint NOT NULL COMMENT 用户id,year year NOT NULL COMMENT 签到年份,month tinyint NOT NULL COMMENT 签到月份,date date NOT NULL COMMENT 签…

物联网行业等保有什么要求

中国网络安全等级保护制度&#xff08;简称“等保”&#xff09;对物联网行业有特定的要求&#xff0c;以确保物联网系统的安全性。等保2.0在原有安全通用要求的基础上&#xff0c;增加了针对新技术如云计算、物联网、移动互联网等的扩展要求。以下是一些关键的物联网安全扩展要…

C语言编译和编译预处理

编译预处理 • 编译是指把高级语言编写的源程序翻译成计算机可识别的二进制程序&#xff08;目标程序&#xff09;的过程&#xff0c;它由编译程序完成。 • 编译预处理是指在编译之前所作的处理工作&#xff0c;它由编译预处理程序完成 在对一个源程序进行编译时&#xff0c;…

小红书矩阵系统源码:赋能内容创作与电商营销的创新工具

在内容驱动的电商时代&#xff0c;小红书凭借其独特的社区氛围和用户基础&#xff0c;成为品牌营销和个人创作者不可忽视的平台。小红书矩阵系统源码&#xff0c;作为支撑这一平台的核心技术&#xff0c;提供了一系列的功能和优势&#xff0c;助力用户在小红书生态中实现更高效…

简体一键转繁体,智能命名神器,轻松将文件名翻译为繁体中文并精准复制至指定文件夹!

在信息爆炸的时代&#xff0c;文件管理和命名变得愈发重要。你是否曾经因为文件名混乱、不易识别而头疼不已&#xff1f;是否想要让文件名称更符合你的阅读习惯&#xff0c;却又因为语言转换的繁琐而望而却步&#xff1f;今天&#xff0c;我们为你带来了一款文件改名神器——文…

S32DS S32 Design Studio for S32 Platform 3.5 软件安装离线激活

问题描述 重新下载安装 NXP s32系列芯片的集成开发环境&#xff08;IDE&#xff09; S32DS S32 Design Studio&#xff0c;当前版本 S32 Design Studio for S32 Platform 3.5&#xff0c;安装时遇到激活问题 在线激活&#xff0c;激活码哪里来&#xff1f; s32ds 不是免费的&a…

python: create Envircomnet in Visual Studio Code 创建虚拟环境

先配置python开发环境 1.在搜索栏输入“>" 或是用快捷组合键ctrlshiftP键 就会显示”>",再输入"python:" 选择已经安装好的python的版本,选定至当前项目中&#xff0c;都是按回车 就可以看到创建了一个虚拟环境的默认的文件夹名".venv" 2 …