深入理解分布式事务② ---->分布式事务基础(MySQL 的 4 种事务隔离级别【读未提交、读已提交、可重复读、串行化】的最佳实践演示)详解

目录

  • 深入理解分布式事务② ---->分布式事务基础(MySQL 的 4 种事务隔离级别【读未提交、读已提交、可重复读、串行化】的最佳实践演示)详解
    • 1、MySQL 事务基础
      • 1-1:MySQL 中 4 种事务隔离级别的区别
      • 1-2:MySQL 中 4 种事务隔离级别的最佳实践演示
        • 数据准备:启动两个 MySQL 服务器终端
        • 数据准备:创建数据库和表数据
        • 1-2-1:演示:读未提交(出现脏读问题)
          • 第一步:
          • 第二步:
          • 第三步:重点来了
          • 第四步:
          • 额外尝试:
            • 演示事务正常提交的结果
            • 演示锁等待超时的结果
            • 演示事务回滚后的结果
        • 1-2-2:演示:读已提交(解决脏读,但出现不可重复读问题)
          • 第一步:
          • 第二步:
          • 第三步:
          • 第四步:
          • 第五步:
          • 终端A 和 终端B 命令总流程对比:
        • 1-2-3:演示:可重复读(解决不可重复读问题,但出现幻读问题)
          • 第一步:
          • 第二步:
          • 第三步:
          • 第四步:
          • 第五步:演示:出现幻读
          • 第六步:
          • 第七步:
        • 1-2-4:串行化(解决幻读等所有并发问题)
          • 第一步:
          • 第二步:
          • 演示串行化级别下进行范围查询的实例:

深入理解分布式事务① ---->分布式事务基础(四大特性、五大类型、本地事务、MySQL并发事务问题、MySQL事务隔离级别命令设置)详解

深入理解分布式事务② ---->分布式事务基础(MySQL 的 4 种事务隔离级别【读未提交、读已提交、可重复读、串行化】的最佳实践演示)详解

1、MySQL 事务基础


1-1:MySQL 中 4 种事务隔离级别的区别

4 种事务隔离级别对于并发事务带来的问题的解决程度不一样。

在这里插入图片描述


1、读未提交允许脏读,即在读未提交的事务隔离级别下,可能读取到其他会话未提交的事务修改的数据。这种事务隔离级别下存在【脏读】、【不可重复读】和【幻读】的问题。

2、读已提交只能读取到已经提交的数据。Oracle 等数据库使用的默认事务隔离级别就是【读已提交】。这种事务隔离级别存在【不可重复读】和【幻读】的问题。

3、可重复读就是在同一个事务内,无论何时查询到的数据都与一开始查询到的数据一致,这就是 MySQL 中 InnoDB 存储引擎默认的事务隔离级别。
这种事务隔离级别下存在【幻读】的问题。

4、串行化是指完全串行的读,每次读取数据库中的数据时,都需要获得表级别的共享锁,读和写都会阻塞。
这种事务隔离级别解决了并发事务带来的问题,但是完全的串行化操作使得数据库失去了并发特性,所以这种事务隔离级别往往在互联网行业中不太常用。


1-2:MySQL 中 4 种事务隔离级别的最佳实践演示


数据准备:启动两个 MySQL 服务器终端

演示在一台Windows主机上运行两个Mysql服务器(端口号3306 和 3307),安装步骤详解


因为要两个服务器终端来演示,因为都是要访问同一个数据库,所以我只需要简单的启动两个命令行窗口,都去访问3306 端口号的 MySQL 服务器就可以了。

3306端口号的bin目录位置:

E:\install\mysql8\mysql-8.0.21-winx64\bin

win+r 打开运行窗口,输入 cmd 打开命令行窗口,输入如下命令启动两个 MySQL 服务器:

e:
cd E:\install\mysql8\mysql-8.0.21-winx64\bin
mysql -u root -p
密码:123456
# 使用这个test数据库
use test;


查看数据库
show databases;

查看端口号
show global variables like 'port';

在这里插入图片描述


数据准备:创建数据库和表数据

创建一个test数据库和一张account账户数据表。

在这里插入图片描述


在这里插入图片描述


# 创建数据库test
create database test;

# 使用数据库test
use test;

# 创建 account 账户表
# auto_increment 自动递增
create table account(
    id int not null auto_increment,
    name varchar(30) not null default '',
    balance int not null default 0,
    primary key(id)
    ) engine = InnoDB default charset=utf8mb4;


# 往 account 账户表插入数据
insert into
   test.account(name,balance)
    values
    ('张三',300),
    ('李四',350),
    ('王五',500);


接下来演示 MySQL 中每种事务隔离级别下数据的处理情况。


1-2-1:演示:读未提交(出现脏读问题)

注意:终端A 和 终端B 就是打开两个命令行窗口,同时登录 3306 这个端口号的 MySQL 服务器而已。

第一步:

打开服务器终端A ,登录MySQL,将当前终端的事务隔离级别设置为 read uncommitted ,也就是读未提交。

在这里插入图片描述

# 终端A 设置事务隔离级别为:读未提交
set session transaction isolation level read uncommitted;

在终端A 开启事务并查询 account 数据表中的数据,如图:

此时可以看到表中的每个人的名字和账户余额

在这里插入图片描述

# 开启事务
start transaction;
# 执行查询
select * from account;

第二步:

在 终端A 的事务提交之前,打开服务器的另一个终端B,连接MySQL,将当前事务模式设置为 read uncommitted (读未提交) 并更新 account 表的数据,将张三的账户余额 +100 元。

注意点:终端A 和 终端B 都是开启了事务,但是还没有提交。

在这里插入图片描述

# 这是在 终端B 的命令行窗口操作的,也就是另一个MySQL服务器

# 使用 test 数据库
use test;

# 修改终端B的事务隔离级别为:读未提交
set session transaction isolation level read uncommitted;

# 修改 test 数据库中的acoount 表中的张三的账户余额
update account set balance = balance + 100 where id = 1;

# 执行查询
select * from account;

通过上面截图,可以看到,在 终端B 中,当前事务未提交时,张三的账户余额变为更新后的值,即 400 元。

在 终端A 中,可以看到,虽然 终端B 的事务还没有提交,但是 终端A 可以查询到 终端B 已经更新的数据。(这就是读取到其他事务未提交的数据了)


第三步:重点来了

如果此时终端B的事务由于某种原因执行了回滚操作,那么终端B中执行的所有操作都会被撤销。
也就是说,终端A 刚刚查询到的数据其实就是脏数据。

就是 终端B 这边原本修改了张三的账户余额为400,但是因为某些问题回滚了,所以终端B这边的张三的数据又变回300了,而终端A 刚刚已经查到了张三的账户余额为 400 了,那么终端A此时拿到的400元数据就是脏数据,如果终端A拿着这脏数据去执行业务逻辑,那么就会出错。


在终端B 执行事务回滚操作,并查询 account 数据表中的数据,如图:

可以看到,在终端B执行了事务的回滚操作后,张三的账户余额重新变为300元。

在这里插入图片描述

# 执行事务回滚操作
rollback;

# 执行查询
select * from account;

第四步:

此时,画面回到终端A这边,因为终端A查到了张三的账户余额为400元,发现账户余额不对,正确应该是 300 元,所以终端A 这边就会将张三的账户余额 -100 元。

所以最终,因为终端B 那边已经回滚了,终端A不知道,所以实际上 300 -100 = 200,而不是 400 -100 = 300;

在这里插入图片描述

# 终端A 这边,对张三的余额 -100 
update account set balance = balance - 100 where id = 1;

# 执行查询操作
select * from account;

因为在应用程序中,并不知道其他会话回滚了事务,所以就会导致拿到的脏数据执行了业务逻辑后,出现错误问题。

重点是:终端A 拿到了 终端B 还未提交的数据,所以拿到的这个数据就是脏数据。

这个就是脏读的问题。

可以采用【读已提交】的事务隔离级别来解决这个问题


额外尝试:
演示事务正常提交的结果

我这里尝试在 终端B 的事务还没有提交之前,终端A 能不能对张三的数据进行修改。

结果是不能的,因为 MySQL的InnoDB 默认是行级锁,得等终端B的事务线程结束,释放锁后,终端A 才能对张三的数据执行操作。

如图,终端B 是正常提交,没有回滚,所以数据是正确的。

在这里插入图片描述


演示锁等待超时的结果

就是张三的数据被终端B的事务线程占据着,在终端B 的事务还没有提交时,也就是该线程还没有执行完;终端A 这边试图获取张三这行数据的锁,因为被 终端B 的线程占据着,所以只能等待,然后一段时间后,终端B 的事务还没有提交,也就是线程还没有执行完,所以终端A 这边就出现了 等待锁超时。
在这里插入图片描述


演示事务回滚后的结果

我这里再尝试在 终端B 的事务还没有回滚之前,终端A 对张三的数据进行修改出现的问题演示:

继续从【演示锁等待超时】那里继续演示:

上面是 终端B 修改张三的数据变成 400元,在事务没提交时,终端A 这边拿到了 张三余额400 元的脏数据,发现余额不对,正确应该是 300元,所以执行了 update 操作,要执行 -100 元的操作。

接着如图:终端B 这边执行了回滚,终端A那边并不知道,所以又对数据进行 update 操作。
终端A 想要的是 400-100 = 300,但实际上,因为终端B 那边回滚,导致终端A 这边变成了 300 - 100 = 200。

这就是因为拿到脏数据,导致执行业务逻辑的时候出现了问题。

在这里插入图片描述



1-2-2:演示:读已提交(解决脏读,但出现不可重复读问题)

注意:终端A 和 终端B 就是打开两个命令行窗口,同时登录 3306 这个端口号的 MySQL 服务器而已。

演示之前,都会把数据恢复成最开始的数据。


第一步:

打开一个终端A(就是打开一个命令行窗口,进行登录3306端口号的MySQL服务器而已),将当前终端的事务隔离级别设置为 read committed,也就是【读已提交】。
如图:

在这里插入图片描述

# 设置当前终端的事务隔离级别设置为 read committed 读已提交
set session transaction isolation level read committed;

在终端A 开启事务并查询 account 数据表中的数据,如下所示:

在这里插入图片描述

# 开启事务
start transaction;
# 执行查询
select * from account;

可以看到,这几个人的账户余额。


第二步:

在终端A 的事务提交之前,打开终端B(就是打开另一个命令行窗口,也进行登录3306端口号的MySQL服务器而已),将当前终端的事务隔离级别也设置为 read committed 【读已提交】,开启事务并更新account 数据表中的数据,将张三的账户余额 +100元。

如下所示:

在这里插入图片描述


接着,在 终端B 查询 account 数据表中的数据,如下所示:

在这里插入图片描述

可以看到,在终端B 的查询结果中,张三的账户余额已经由原来的 300 元 变成 400 元。

# 使用 test 这个数据库
use test;

# 设置当前数据库连接的事务隔离级别为:读已提交
set session transaction isolation level read committed;

# 开启事务
start transaction;

# 修改张三的账户余额,+100 元
update account set balance = balance + 100 where id = 1;

# 执行查询
select * from  account;

第三步:

在终端B 的事务提交之前,在终端A中查询 account 数据表中的数据,如下所示:
在这里插入图片描述

可以看到,在终端A 查询出来的张三的账户余额仍然为 300 元,说明此时已经解决了脏读的问题。


第四步:

在 终端B 提交事务,如下所示
在这里插入图片描述

# 提交事务
commit;

第五步:

在终端B提交事务后,在终端A再次查询account数据表中的数据,如下所示:

在这里插入图片描述

可以看到,终端A 在 终端B 的事务提交前和提交后,读取到的 account 数据表中的数据不一致(张三的账户余额不一致),这就产生了不可重复读的问题。

要想解决这个问题,就需要使用可重复读的事务隔离级别。


终端A 和 终端B 命令总流程对比:

在这里插入图片描述



1-2-3:演示:可重复读(解决不可重复读问题,但出现幻读问题)

注意:终端A 和 终端B 就是打开两个命令行窗口,同时登录 3306 这个端口号的 MySQL 服务器而已。

演示之前,都会把数据恢复成最开始的数据。


第一步:

打开终端A,登录 MySQL , 将当前终端的事务隔离级别设置为 repeatable read,也就是【可重复读】。开启事务并查询 account 数据表中的数据。如下所示:

打开一个命令行窗口,作为终端A,登录 MySQL 服务器。
在这里插入图片描述


在这里插入图片描述

此时可以看到几个人的账户余额。

# 使用 test 数据库
use test;

# 将当前终端的事务隔离级别设置为 repeatable read,也就是【可重复读】
set session transaction isolation level repeatable read;

# 开启事务
start transaction;

# 执行查询
select * from account;

第二步:

在终端A 的事务提交之前,打开终端B,登录 MySQL ,将当前终端的事务隔离级别设置为【可重复读】。开启事务,将张三的账户余额 +100 元,随后提交事务,如下所示:

打开一个命令行窗口,作为终端B,登录 MySQL 服务器。

在这里插入图片描述


在这里插入图片描述

# 使用 test 数据库
use test;

# 将当前终端的事务隔离级别设置为 repeatable read,也就是【可重复读】
set session transaction isolation level repeatable read;

# 开启事务
start transaction;

# 修改张三的余额, + 100 元。
update account set balance = balance + 100 where id = 1;

# 提交事务
commit;


接下来,继续在终端B查询 account 数据表中的数据,如下所示:

在这里插入图片描述

可以看到,在终端B的查询结果中,张三的账户余额已经由原来的 300 元 变成 400 元。


第三步:

在终端A 查询 account 数据表中的数据,如下所示:

在这里插入图片描述

可以看到,在终端A 查询的结果中,张三的账户余额仍然为 300 元,并没有出现【不可重复读】的问题,说明可重复读的事务隔离级别解决了不可重复读的问题。

因为此时终端A是设置了【可重复读】的事务隔离级别,而且此时 终端A 的事务还没有提交,所以此时的两次查询都是在同一个事务里面执行的,所以用相同的查询条件,多次查询的结果都是一致的。所以无论终端B怎么修改张三的数据,终端A这边只要还在这个事务内,无论这个查询执行多少次,都是 300 元。


第四步:

在终端A 为张三的账户 + 100 元,如下所示:

在这里插入图片描述

# 张三余额 +100
update account set balance = balance + 100 where id = 1;

接下来,在终端A查询 account 数据表中的数据,如下所示:

在这里插入图片描述

可以看到,查询的时候余额还是300元,执行 +100 元的修改语句后,此时张三的余额竟然变成了 500 元,而不是 400 元,数据的一致性没有遭到破坏。这是因为在终端A 为张三的账户 +100 元之前,终端B 已经为张三的账户余额增加了 100 元,共计增加了 200 元,所以最终张三的账户余额是 500 元,是正确的。

数据的一致性: 就是指在分布式系统中,所有副本的数据在任何时刻都保持相同的状态。换句话说,当数据在一个副本上发生变化时,其他副本也会相应地进行更新,以保持数据的一致性


可重复读的隔离级别使用了 MVCC(Multi-Version Concurrency Control,多版本并发控制)机制,数据库中的查询(select)操作不会更新版本号,是快照读,而操作数据表中的数据(insert、update、delete)则会更新版本号,是当前读。


第五步:演示:出现幻读

在 终端B 开启事务,插入一条数据后提交事务,如下所示:

在这里插入图片描述


继续在 终端B 查询 account 数据表中的数据,如下所示:

在这里插入图片描述

可以看到,在 终端B 查询的结果中,已经显示出新插入的赵六的账户信息了。


# 开启事务
start transaction;

# 执行一条插入语句
insert into account(name,balance) values ('赵六',100);

#提交事务
commit;

# 执行查询
select * from account;


第六步:

在 终端A 查询 account 数据表中的数据,如下所示:

在这里插入图片描述

可以看到,在 终端A 查询的数据中,并没有出现赵六的账户信息,注意,此时的 终端A 一直都是处在最开始的那个事务中,还没有提交过。
而在同一个事务内,多次读取一个范围的数据记录,读到的结果都是相同的,说明没有出现【幻读】的情况。

【幻读:就是一个事务两次读取一个范围的数据记录,两次读取到的结果不同】


第七步:

在 终端A 为赵六的账户 +100 元,如下所示:

修改赵六余额的 SQL 语句执行成功。接下来,也是在终端A 查询 account 数据表中的数据:

在这里插入图片描述

可以看到,在 终端A 执行完数据更新操作之前是查不到赵六的信息的,
而在 终端A 执行完数据更新操作后,突然就能查询到赵六的账户信息了,这就出现了【幻读】的问题。

注意:这整个演示中,终端A 都是处在同一个事务内的。

要解决幻读问题,得使用串行化的事务隔离级别或者间隙锁和临键锁。



1-2-4:串行化(解决幻读等所有并发问题)

演示之前,都会把数据恢复成最开始的数据。


第一步:

打开 终端A ,登录 MySQL , 将当前终端的事务隔离级别设置为 serializable,也就是串行化,然后开启事务,再查询 account 数据表中 id = 1 的数据,如下所示:

在这里插入图片描述


# 打开 终端A (就是打开一个命令行窗口),登录 MySQL
e:
cd E:\install\mysql8\mysql-8.0.21-winx64\bin
mysql -u root -p
密码:123456

# 使用这个test数据库
use test;

# 将当前终端的事务隔离级别设置为 serializable,也就是串行化
set session transaction isolation level serializable;

# 开启事务
start transaction;

# 查询 account 数据表中 id = 1 的数据
select * from account where id = 1;


第二步:

打开终端B,登录 MySQL ,将当前终端的事务隔离级别设置为 serializable 串行化,修改 account 数据表中 id = 1 的数据,如下所示:

在这里插入图片描述

可以看到,在 终端B 中对 account 数据表中 id = 1 的数据执行更新操作时,会发生阻塞,锁超时后会抛出【ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction】异常,这就避免了幻读。


# 将当前终端的事务隔离级别设置为 serializable,也就是串行化
set session transaction isolation level serializable;

# 开启事务
start transaction;

# 终端B 修改 id = 1 的数据
update account set balance = balance + 100 where id = 1;

因为当 id = 1 的数据被终端A占据着,那么终端B就不能对其进行修改操作,只能等终端A事务提交后才可以。

简单来说,就是 id = 1 这行数据被终端A 的线程占据了,要等其事务执行完后,释放锁,其他线程才能够操作该条数据。

如果终端B只是查询,是没有影响的,修改就不行,如图:
在这里插入图片描述


如图:id = 1 这行数据还在终端A 的事务内操作着,终端B 无法对该数据执行更改操作,但是更改其他行数据就没有任何影响,比如更改 id = 2 的数据就没有影响。

在这里插入图片描述


演示串行化级别下进行范围查询的实例:

另外,在串行化的事务隔离级别下,如果终端A 执行的是一个范围查询,那么该范围内的所有行(包括每行记录所在的间隙区间范围,如果某行记录还未被插入数据,这行记录也会被加锁,这是一种间隙锁)都会被加锁。
此时 终端B 在此范围内插入数据,就会被阻塞,从而避免幻读,如下所示:

除了 start transaction; 可以开启事务外,begin 也可以,如下所示:

在这里插入图片描述

可以看到,终端A 这边的事务执行了一个 id < 3 的范围查询, 那么这个范围的数据,在【串行化】的事务隔离级别下,就都会被加锁。
因此,终端B 这边,在 终端A 的事务还没结束前,是无法对 id < 3 的这个范围的数据进行修改或删除操作的。


# 开启事务
begin;
# 修改数据
update account set balance = balance + 1000 where id = 3;


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

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

相关文章

Qt使用OPCUA

假如想在Qt下使用OPCUA通讯&#xff0c;貌似大家都是倾向于使用【qtopcua】这个库。但是在Qt6之前&#xff0c;假如想使用这个库&#xff0c;还得自己编译&#xff0c;比较繁琐。假如想开箱即用&#xff0c;而且没有使用太复杂的功能的话&#xff0c;其实可以直接使用open62541…

2024年最新一线互联网企业高级软件测试工程师面试题大全

1、功能测试 功能测试是游戏测试中跟“玩游戏”最相关的一个环节。 当然这里的“玩”不是要真的让你感受快乐&#xff0c;而是要通过“玩”游戏&#xff0c;发现存在的问题或不合理的地方。因此&#xff0c;这个“玩”的过程基本不会感受到游戏的乐趣。事实上&#xff0c;每一次…

决策树学习笔记

一、衡量标准——熵 随机变量不确定性的度量 信息增益&#xff1a;表示特征X使得类Y的不确定性减少的程度。 二、数据集 14天的打球情况 特征&#xff1a;4种环境变化&#xff08;天气、温度等等&#xff09; 在上述数据种&#xff0c;14天中打球的天数为9天&#xff1b;不…

LVGL移植

Lvgl介绍 LVGL是一个开源的图形库&#xff0c;专为嵌入式系统设计。它提供了丰富的图形元素和功能&#xff0c;可以帮助开发者快速构建现代化的用户界面。LVGL具有跨平台的特性&#xff0c;支持多种操作系统和硬件平台&#xff0c;包括ARM Cortex-M&#xff0c;ESP32&#xff…

基于springboot+vue+Mysql的漫画网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

等保测评与信息安全管理体系认证的区别

区别一、标准以及性质 等保测评以《中华人民共和国计算机信息系统安全保护条例》为基础&#xff0c;结合一系列的政策和标准&#xff0c;对信息安全水平进行评估。而安全管理系统的认证&#xff0c;是资讯安全管理系统的一种规范&#xff0c;本身并不具备强制性质。企业可根据…

这么全的权限系统设计方案,不值得收藏吗?

1 为什么需要权限管理 日常工作中权限的问题时时刻刻伴随着我们&#xff0c;程序员新入职一家公司需要找人开通各种权限&#xff0c;比如网络连接的权限、编码下载提交的权限、监控平台登录的权限、运营平台查数据的权限等等。 在很多时候我们会觉得这么多繁杂的申请给工作带…

未来想从事Linux 后台开发,需要学习linux内核吗?

先列出主要观点&#xff0c;有时间再补充细节&#xff1a; “学习Linux内核”对不同的人有不同的含义&#xff0c;学习方法、侧重点、投入的精力也大不相同。我大致分三类&#xff1a;reader、writer、hacker。reader 就是了解某个功能在内核的大致实现 how does it work&…

ZIP压缩输入流(将文件压缩为ZIP文件)

文章目录 前言一、ZIP压缩输入流是什么&#xff1f;二、使用介绍 1.使用方法2.实操展示总结 前言 该篇文章将会介绍如何使用java代码将各种文件&#xff08;文件夹&#xff09;的资源压缩为一个ZIP压缩包。通过java.util包中的ZipOutputStream类来实现。并且需要自定义压缩方法…

记录些AI Agents设计模式和NL2SQL知识

吴恩达分享的四种 自我反思&#xff08;Reflection&#xff09;&#xff1a;可以自我修正&#xff1b;使用工具&#xff08;Tool Use&#xff09;&#xff1a;链接其他系统去做一些事情&#xff0c;比如把电脑里面的未归档文件做好归档&#xff1b;规划&#xff08;Planning&a…

免费实用在线小工具

免费在线工具 https://orcc.online/ pdf在线免费转word文档 https://orcc.online/pdf 时间戳转换 https://orcc.online/timestamp Base64 编码解码 https://orcc.online/base64 URL 编码解码 https://orcc.online/url Hash(MD5/SHA1/SHA256…) 计算 https://orcc.online/ha…

软考之零碎片段记录(二十七)+复习巩固(十三、十四)

学习 1. 案例题 涉及到更新的。肯能会是数据流的终点E, P, D 数据流转。可能是 P->EP->D(数据更新)P->P(信息处理)D->P(提取数据信息) 2. 案例2 补充关系图时会提示不增加新的实体。则增加关联关系 3. 案例3 用例图 extend用于拓展&#xff0c;当一个用例…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-1.3

前言&#xff1a; 本文是根据哔哩哔哩网站上视频“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”的学习笔记&#xff0c;在这里会记录下正点原子Linux ARM MX6ULL 开发板根据配套的哔哩哔哩学习视频所作的实验和笔记内容。本文大量的引用了正点原子哔哔哩网…

Python 单例类中设置和获取属性的问题及解决方案

1、问题背景 在编写 Python 代码时&#xff0c;有时需要创建一个单例类&#xff0c;这样就可以在程序中使用该类的唯一实例。为了实现这一点&#xff0c;可以定义一个类&#xff0c;并在其 __new__ 方法中检查该类的实例是否已经存在。如果实例存在&#xff0c;则返回该实例&a…

stm32f4单片机强制类型转换为float程序跑飞问题

如题&#xff0c;在一个数据解析函数中使用了*(float *)&data[offset]&#xff0c;其中data为uint8类型指针&#xff0c;指向的value地址为 可以看到地址0x20013A31非对齐&#xff0c;最终在执行VLDR指令时导致跑飞 VLDR需要使用对齐访问 跑飞后查看SCB寄存器发现确实是非…

未授权/敏感信息/越权检测插件-BurpAPIFinder

简介 攻防演练过程中&#xff0c;我们通常会用浏览器访问一些资产&#xff0c;但很多未授权/敏感信息/越权隐匿在已访问接口过html、JS文件等&#xff0c;通过该Burp插件我们可以&#xff1a; 1、发现通过某接口可以进行未授权/越权获取到所有的账号密码、私钥、凭证 2、发现通…

【顺序表小题】

顺序表小题 移除元素思路一思路二 合并两个有序数组思路一思路二 移除元素 链接: 题目链接 思路一 创建新的数组&#xff0c;遍历原数组&#xff0c;将不为val的值放到新数组中 思路二 双指针法。 创建两个变量src,dst。 1)若src指向的值为val&#xff0c;则src 2)若sr…

点击劫持:X-Frame-Options未配置、nginx配置X-Frame-Options响应头

nginx配置X-Frame-Options响应头 X-Frame-Options X-Frame-Options 有三个值&#xff1a; DENY 表示该页面不允许在 frame 中展示&#xff0c;即便是在相同域名的页面中嵌套也不允许。SAMEORIGIN 表示该页面可以在相同域名页面的 frame 中展示。ALLOW-FROM uri 表示该页面可…

TechTool Pro for mac中文激活版:硬件监测和系统维护工具

TechTool Pro mac帮助用户实现系统硬件监测&#xff08;CPU、内存、硬盘、网络、USB等&#xff09;、内存测试、S.M.A.R.T检测、磁盘宗卷扫描、宗卷重建和优化、数据恢复和粉碎等等&#xff0c;定期使用&#xff0c;可以确保您的Mac保持优化和无故障。 TechTool Pro for mac v1…

小龙虾优化算法(Crayfish Optimization Algorithm,COA)

小龙虾优化算法&#xff08;Crayfish Optimization Algorithm&#xff0c;COA&#xff09; 前言一、小龙虾优化算法的实现1.初始化阶段2.定义温度和小龙虾的觅食量3.避暑阶段&#xff08;探索阶段&#xff09;4.竞争阶段&#xff08;开发阶段&#xff09;5.觅食阶段&#xff08…
最新文章