MySQL进阶之(十一)MySQL事务日志-redo log

十一、MySQL事务日志-redo log

  • 11.1 Buffer Pool
    • 11.1.1 缓存的重要性
    • 11.1.2 InnoDB 的 Buffer Pool
    • 11.1.3 InnoDB 存储引擎线程
  • 11.2 redo 日志引入
  • 11.3 redo 日志的好处和特点
    • 11.3.1 好处
    • 11.3.2 特点
  • 11.4 redo 日志的组成
  • 11.5 redo 日志的整体流程
  • 11.6 redo 日志的刷盘策略
  • 11.7 redo 日志不同刷盘策略举例
    • 01、提交事务时不操作
    • 02、提交事务时刷盘
    • 03、提交事务后只写入日志文件
    • 04 不同刷盘策略的速度和安全性
  • 11.8 写入 redo log buffer 过程
    • 01、Mini-Transaction
    • 02、redo 写入 log buffer
    • 03、redo log block 结构
  • 11.9 写入 redo log file 过程
    • 01、相关参数设置
    • 02、日志文件组
    • 04、checkpoint 引入
    • 05、checkpoint
    • 06、checkpoint 举例
    • 07、刷新时机(了解)

11.1 Buffer Pool

11.1.1 缓存的重要性

对于使用 InnoDB 存储引擎的表来说,无论是用于存储用户数据的索引,还是各种系统数据,都是以【页】的形式存放在表空间中的。所谓的表空间,只不过是 InnoDB 对于一个或几个实际文件的抽象,但其实,这些数据说到底还是存储在磁盘上的。

但是,磁盘的速度是很慢的。所以 InnoDB 存储引擎在处理客户端的请求时,如果需要访问某个页的数据,就会先把完整的页中的数据全部加载到内存中。即使只需要访问一个页的一条记录,也需要把整个页的数据先加载到内存中。这样在后续的读写访问后,也并不着急把该页对应的内存空间释放掉,而是将其缓存起来,这样将来有请求再次访问该页面时,就可以省下磁盘 I/O 的开销了。

11.1.2 InnoDB 的 Buffer Pool

为了缓存磁盘中的页,在 MySQL 服务器启动的时候就向操作系统申请了一片连续的内存,这片内存就叫做 Buffer Pool(缓冲池),默认情况下,Buffer Pool 只有128 MB。Buffer Pool 对应的一片连续的内存被划分为若干个页面(缓冲页),页面大小与 InnoDB 表空间的页面大小一致,默认都是 16KB。为了更好地管理这些缓冲页,给每个缓冲页都创建了一些控制信息,并把每个页对应的控制信息占用的内存称为一个控制块,控制块与缓冲页是一一对应的。

每个控制块都对应一个缓冲页,在分配足够多的控制块和缓冲页后,剩余的那点空间可能不够一对控制块和缓冲页的大小了,那么就称这个内存空间为碎片。当然,如果把 Buffer Pool 的大小设置的刚刚好,也可能不产生碎片。

11.1.3 InnoDB 存储引擎线程

InnoDB 存储引擎是多线程的模型,也就是说它拥有多个不同的后台线程,负责处理不同的任务。下面是几种不同的后台线程:

  • Master Thread:主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性。
  • IO Thread:在 InnoDB 存储引擎中大量使用了 AIO(Async IO)来处理写 IO 请求,这样可以极大提高数据库的性能。IO Thread 的工作主要是负责这些 IO 请求的回调处理。
  • Purge Thread:回收已经使用并分配的 undo 页。
  • Page Cleaner Thread:将之前版本中脏页的刷新操作都放入到单独的线程中来完成。其目的是为了减轻原 Master Thread 的工作及对于用户查询线程的阻塞,进一步提高 InnoDB 存储引擎的性能。

Master Thread 每秒操作:

  • redo日志缓冲刷新到磁盘,即使这个事务还没有提交(总是):即使某个事务还没有提交,InnoDB 仍然每秒会将重做日志缓冲中的内容刷新到重做日志文件。这一点是必须要知道的,因为这可以很好地解释为什么再大的事务提交(commit)的时间也是很短的。
  • 合并插入缓冲(可能):合并插入缓冲(Insert Buffer)并不是每秒都会发生的。InnoDB 会判断当前一秒内发生的 IO 次数是否小于 5 次,如果小于 5 次,InnoDB 认为当前的 IO 压力很小,可以执行合并插入缓冲的操作。
  • 至多刷新 100 个 InnoDB 的缓冲池中的脏页到磁盘(可能):刷新 100 个脏页也不是每秒都会发生的。InnoDB 通过判断当前缓冲池脏页的比例(buf_get_modified_ratio_pct)是否超过了配置文件中innodb_max_dirty_pages_pct 这个参数(默认为90,代表90%),如果超过了这个阈值,InnoDB 认为需要做磁盘同步操作,将100个脏页写入磁盘。
  • 如果当前没有用户活动,则切换到background loop(可能)

11.2 redo 日志引入

为什么需要 redo 日志?

内存中的缓冲池里的数据是定期刷新到磁盘的,并不是每次变更都会实时刷盘。

如果一个事务提交了,刚写进内存,还没来得及刷盘,这时数据库宕机了,那么这段数据就丢失了,后续也无法恢复。从另一方面看,事务的持久性要求事务一旦提交,即使数据库崩溃,该事务对数据库的操作也不能丢失。

如何保证这个持久性呢?一个简单的做法就是:在事务提交完成之前把该事务所修改的所有页面都刷新到磁盘,但是这个简单粗暴的做法有些问题:

  1. 修改量与刷新磁盘工作量严重不成比例(每次改动无论改动多少都要刷新一整个页面,即使改动的点非常小)。
  2. 随机 IO 刷新比较慢。

InnoDB 引擎的事务采用了 WAL 技术(Write-Ahead Logging 日志优先),即:先写日志再写磁盘。只有日志写入成功才算事务提交成功,这里的日志指的就是 redo log。当发生宕机且数据未写入磁盘时,可以通过 redo log 来恢复,保证 ACID 中的 D。

例如:某个事务将系统表空间中的第 10 号页面,偏移量为 100 处的字节由 1 改为 2,这时只需要记录一下 “将 0 号表空间的第10 号页面的偏移量为 100 处的值更新为 2”。
在这里插入图片描述

11.3 redo 日志的好处和特点

11.3.1 好处

  • redo 日志降低了刷盘频率

  • redo 日志空间占用很小

    存储了表空间 ID、页号、偏移量以及需要更新的值,索引存储空间很小。

11.3.2 特点

  • redo 日志是顺序写入磁盘

    在执行事务的过程中,每执行一条语句,就可能产生若干条 redo 记录,这些日志按照产生的顺序依次写入磁盘,即顺序 IO,效率比随机 IO快。

  • 事务执行过程中,redo log 不断记录

    redo 日志是存储引擎层产生的,而 bin-log 是 Server 层产生。假设一个事务,对表进行批量插入,在这个过程中会一直不断的向 redo 日志中顺序写入数据,而 bin-log 不会记录,直到这个事务提交时,才会一次性写入 bin-log 文件中。

11.4 redo 日志的组成

redo log 由两部分组成:

  • redo log buffer 日志缓存:重做日志缓存。存在于内存中,容易发生丢失。
  • redo log file 日志文件:重做日志文件。存在于磁盘中,不容易丢失。

在服务启动时候就申请了一段名为 redo log buffer 的连续内存空间,这片内存空间被划分为若干个连续的 redo log block。一个 block 的大小为 512 字节。

在这里插入图片描述
参数设置:innodb_log_buffer_size 默认值16M

mysql> show variables like 'innodb_log_buffer_size';
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set, 1 warning (0.00 sec)

11.5 redo 日志的整体流程

以一个更新事务为例 ,redo log 流转过程如图所示:
在这里插入图片描述

  1. 将磁盘的原始数据加载进内存,修改内存中的数据;
  2. 生成一条 redo log,并写入到 redo log buffer 中,记录的是数据被修改后的值;
  3. 当事务 commit 时,将 redo log buffer 中的内容按照追加的方式将数据刷新到 redo log file 中;
  4. 定期将内存中修改的数据刷新到磁盘中。

Write-Ahead Log(预先日志持久化):在持久化一个数据页之前,先将内存中相应的日志页持久化。

11.6 redo 日志的刷盘策略

redo log 的写入并不是直接写入磁盘的,InnoDB 存储引擎会在写 redo log 的时候先写入到 redo log buffer,之后以一定的频率刷入到真正的 redo log file 中。其中,一定的频率就是指刷盘策略
在这里插入图片描述
这里需要注意,redo log 由 buffer 刷新到 redo log file,并不是真正的刷新到磁盘,只是刷新到文件系统缓存(page cache)中去(现代操作系统提高文件写入效率做的优化),而什么时候真正的写入则由操作系统自己决定。

那么对于 InnoDB 就会存在一个问题:如果系统宕机,那么 page cache 中的数据也会丢失,造成 redo log file 写入失败,数据也就丢失了(尽管这种情况的概率是非常小的)。

针对这种情况,InnoDB 给出三种策略,通过 innodb_flush_log_at_trx_commit 参数控制在提交事务时,如何刷新 redo log 到 redo log file 中:

  1. 设置为 0:每次提交事务时不进行刷盘操作(系统默认 master thread 每间隔一秒进行一次同步)。
  2. 设置为 1:每次提交事务时把 redo log buffer 内容写入到日志文件中,并将日志文件中的数据更新到磁盘(默认值)。
  3. 设置为 2:每次提交事务时只把 redo log buffer 内容写入到日志文件中。每秒钟将日志文件中的数据更新到磁盘一次,该操作由操作系统调度。
mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set, 1 warning (0.00 sec)

另外,在 InnoDB 引擎中有一个后台线程,每隔一秒就会把 redo buffer log 中的内容写入到文件系统缓存 page buffer,然后调用刷盘操作。
在这里插入图片描述
也就是说,一个没有提交事务的 redo log 记录,也可能会刷盘。因为在事务执行过程 redo log 记录是会写入 redo log buffer 中,这些 redo log 记录会被后台线程刷盘。

在这里插入图片描述
除了后台线程每秒 1 次的轮询操作,还有一种情况,当 redo log buffer 占用的空间即将达到 innodb_flush_log_at_trx_commit(默认是 16M)的一半的时候,后台线程会主动刷盘。

11.7 redo 日志不同刷盘策略举例

01、提交事务时不操作

innodb_flush_log_at_trx_commit 0

异步刷盘:日志缓存区将每隔一秒写到日志文件中,并且将日志文件的数据刷新到磁盘上。该模式下在事务提交时不会主动触发写入磁盘的操作。

除了后台线程每秒 1 次的轮询操作,还有当 redo log buffer占用的空间即将达到innodb_log_buffer_size (这个参数默认是 16M) 的一半的时候,后台线程会主动刷盘。

该模式下一个事务如果还没有提交,但产生的 redo log 记录也有可能被刷盘,这部分 redo log buffer 中的数据会被后台线程刷新到磁盘。
在这里插入图片描述

02、提交事务时刷盘

innodb_flush_log_at_trx_commit 1

主动刷盘:每次事务提交时 MySQL 都会把日志缓存区的数据写入日志文件中,并且刷新到磁盘中,该模式为系统默认。
在这里插入图片描述

  • 当 innodb_flush_log_at_trx_commit 值为 1 时,只要事务提交成功,redo log 记录就一定在硬盘里,不会有任何数据丢失。
  • 如果事务执行期间 MySQL 服务宕机,若事务未提交,则不影响数据。
  • 此方式可以保证事务 ACID 中的 D,但是是效率最差的。
  • 建议使用默认值。即使操作系统宕机的概率小于数据库宕机的概率,既然使用了事务,那么数据的安全相对来说更重要些。

03、提交事务后只写入日志文件

innodb_flush_log_at_trx_commit 2

操作系统决定刷盘:每次提交事务时只把 redo log buffer 内容写入到 page cache 中,但不进行刷盘。该模式下,MySQL 会每秒将日志文件中的数据更新到磁盘执行一次刷盘操作。

也就是说,该模式下 redo log 写入缓存不受参数 innodb_flush_log_at_trx_commit 的影响,因为后台会实时将记录写入缓存。
在这里插入图片描述

04 不同刷盘策略的速度和安全性

  • 当设置为 0,该模式速度最快,但不太安全,mysqld 进程的崩溃会导致上一秒钟所有事务数据的丢失;
  • 当设置为 1,该模式是最安全的,但也是最慢的一种方式。在 mysqld 服务崩溃或者服务器主机宕机的情况下,日志缓存区只有可能丢失最多一个语句或者一个事务;
  • 当设置为 2,该模式速度较快,较取值为 0 情况下更安全,只有在操作系统崩溃或者系统断电的情况下,上一秒钟所有事务数据才可能丢失。

11.8 写入 redo log buffer 过程

01、Mini-Transaction

MySQL 把对底层页面的一次原子访问的过程称为一个 Mini-Transaction,简称 mtr。比如向某个索引的 B+Tree 中插入一条记录的过程就是一个 mtr,一个 mtr 包含一组 redo log,在进行崩溃恢复时,这组日志是一个不可分割的整体。

一个事务可以包含若干条语句,一个语句包含若干个 mtr,每个 mtr 又可以包含若干条 redo log:
在这里插入图片描述

02、redo 写入 log buffer

向 log buffer 中写入 redo log 的过程是顺序的,也就是先往前面的 block 中写,当该 block 的空闲空间用完之后再往下一个 block 中写。当我们想往 log buffer 中写入 redo log 时,第一个遇到的问题就是应该写在哪个 block 的哪个偏移量处,所以 InnoDB 的设计者特意提供了一个称之为 buf_free 的全局变量,该变量指明后续写入的 redo log 应该写入到 log buffer 中的哪个位置:
在这里插入图片描述
其中,一个 block 的大小时 512字节。

一个 mtr 执行过程中可能产生若干条 redo log,这些 redo log 是一个不可分割的组(在 log buffer 中必须存在在一起),所以其实并不是每生成一条 redo log,就将其插入到 log buffer 中,而是每个 mtr 运行过程中产生的日志先暂时存到一个地方,当该 mtr 结束的时候,将过程中产生的一组 redo log 再全部复制到 log buffer 中。

假设现在有两个名为 T1、T2 的事务,每个事务都包含 2 个 mtr,给这几个 mtr 命名一下:

  • 事务 T1 的两个 mtr 分别称为 mtr_T1_1 和 mtr_T1_2
  • 事务 T2 的两个 mtr 分别称为 mtr_T2_1 和 mtr_T2_2

每个 mtr 都会产生一组 redo log:
在这里插入图片描述
不同的事务可能是并发执行的,所以 T1、T2 事务的 mtr 可能是交替执行存储的,一个 mtr 执行完,伴随着一组 redo log 就会被复制到 log buffer 中:
在这里插入图片描述
其中,有的 mtr 产生的 redo log 量非常大,比如 mtr_t1_2 产生的 redo log 占用的空间就比较大,占用了 3 个 block 来存储。

03、redo log block 结构

一个 redo log buffer 是由日志头、日志体、日志尾组成。日志头占用 12 字节,日志尾占用 8 字节,所以一个 block 真正能存储的数据也就是 512-12-8 = 492 字节。

为什么一个 block 设计成 512 字节?这个和磁盘的扇区有关,机械磁盘默认的扇区就是 512 字节,如果要写入的数据大于 512 字节,那么要写入的扇区肯定不止一个,这时就要设计到盘片的转动,找到下一个扇区,假设需要写入两个扇区 A 和 B,如果扇区 A 写入成功,而扇区 B 写入失败,那么就会出现非原子性的写入,而如果每次只写入和扇区的大小一样的 512 字节,那么每次的写入都是原子性的。

11.9 写入 redo log file 过程

01、相关参数设置

  • innodb_log_file_size:用于设定 MySQL 日志组中每个日志文件的大小。

    mysql> show variables like 'innodb_log_file_size';
    +----------------------+----------+
    | Variable_name        | Value    |
    +----------------------+----------+
    | innodb_log_file_size | 50331648 |
    +----------------------+----------+
    1 row in set, 1 warning (0.01 sec)
    
  • innodb_log_files_in_group:指定日志组个数。默认为 2 个日志组。

    mysql> show variables like 'innodb_log_files_in_group';
    +---------------------------+-------+
    | Variable_name             | Value |
    +---------------------------+-------+
    | innodb_log_files_in_group | 2     |
    +---------------------------+-------+
    1 row in set, 1 warning (0.00 sec)
    
  • innodb_log_group_home_dir:redo log 日志文件存储位置,默认 ./ 当前数据目录。

    mysql> show variables like 'innodb_log_group_home_dir';
    +---------------------------+-------+
    | Variable_name             | Value |
    +---------------------------+-------+
    | innodb_log_group_home_dir | .\    |
    +---------------------------+-------+
    1 row in set, 1 warning (0.00 sec)
    
  • innodb_log_buffer_size: redo log 缓存大小默认 16M。

    mysql> show variables like 'innodb_log_buffer_size';
    +------------------------+----------+
    | Variable_name          | Value    |
    +------------------------+----------+
    | innodb_log_buffer_size | 16777216 |
    +------------------------+----------+
    1 row in set, 1 warning (0.00 sec)
    

02、日志文件组

磁盘上的 redo log 文件不止一个,而是以一个日志文件组的形式出现的。这些文件以 ib_logfilr[数字] (数字可以是 0、1、2)的形式进行命名,每个 redo log 文件大小都是一样的。在将 redo log 写入文件组时,是以 ib_logfile0 开始写,如果 ib_logfile0 写满了,就接着 ib_logfile1 写。同理,ib_logfile1 写满了就去写 ib_logfile2,依次类推。如果写到最后一个文件该怎么办呢?那就重新转到 ib_logfile0 继续写,整个过程如下:

在这里插入图片描述

总共的 redo log 文件大小其实就是:innodb_log_file_size ✖ innodb_log_files_in_group。

这种采用循环写的方式,会覆盖掉前面的文件内容,所以就提出了 checkpoint 的概念。

04、checkpoint 引入

有了 redo log,我们仍然会面临这样 3 个问题:

  1. 缓冲池 buffer pool 不是无限大的,也就是说,不能一直不断地存储数据,然后等待一起刷新到磁盘;
  2. redo log 是循环使用而不是无限大(也有这个可能 ,但是成本太高,同时不便于运维),那么当所有的 redo log file 都写满了怎么办?
  3. 当数据库运行了几个月甚至几年时,一旦发生宕机,redo log 不做处理的话会非常大,重新应用 redo log 的时间会非常久,恢复的代价也会非常大。

所以,引入了 checkpoint:

  • 缓冲池不够用时,将脏页刷新到磁盘:所谓缓冲池不够用的意思就是缓冲池的空间无法存放新读取到的页,这个时候 InnoDB 引擎会怎么办呢?LRU 算法。InnoDB 存储引擎对传统的 LRU 算法做了一些优化,用其来管理缓冲池这块空间。
  • redo log 不可用时,将脏页刷新到磁盘:文件组写满了,需要推进 checkpoint,擦除部分数据。
  • 缩短数据库的恢复时间:当数据库发生宕机时,数据库不需要重做所有的日志,因为 checkpoint 之前的页都已经刷新回磁盘。所以数据库只需对 checkpoint 后的 redo log 进行恢复就行了,这显然大大缩短了恢复的时间。

一句话概括就是:checkpoint 其实就是在 redo log file 中找到一个位置,将这个位置的页都从 buffer pool 中刷新到磁盘中去,这个位置就成为 checkpoint(检查点)。

05、checkpoint

在整个日志文件组中有两个重要的属性,分别是 write-ops、checkpoint:

  • write pos:当前记录的位置,一边写一边往后记录。
  • checkpoint:当前可以擦除的位置,也是不断往后移动的。

当所有的 redo log file 都写满了,无法写入新的数据时,就需要清理掉无用的 redo log 了。

小贴士:redo log 中的数据并不是时时刻刻都是有用的,那些已经不再需要的部分就称为 “可以被重用的部分”,即当数据库发生宕机时,数据库恢复操作不需要这部分的 redo log,因此这部分就可以被覆盖重用(或者说被擦除)。

每次刷盘 redo log 记录到日志文件组中 ,write pos 位置就会后移更新。每次 MySQL 加载日志文件组恢复数据时,会清空加载过的 redo log 记录,并把 checkpoint 后移更新,wriite pos 和 checkpoint 之间的还空着的部分可以用来写入新的 redo log 记录。

在这里插入图片描述
如果 write pos 追上 checkpoint,表示日志文件组满了 ,这时就不能再写入新的 redo log 记录了,MySQL 得停下来,清空一些记录,把 checkpoint 推进一下。
在这里插入图片描述

06、checkpoint 举例

举个具体的例子解释一下:一组 4 个文件 ,每个文件大小都是 1GB,那么总共有 4GB 的 redo log file 空间。

  1. write pos 是当前 redo log 记录的位置,随着不断地写入磁盘,write pos 也不断地往后移,写到 file3 末尾后就回到 file0 开头。

  2. checkpoint 是要擦除的位置(将 checkpoint 之前的页刷新到磁盘),也是往后推移并且循环的。

在这里插入图片描述
write pos 和 checkpoint 之间的就是 redo log file 上还空着的部分,可以用来记录新的操作。如果 write pos 追上 checkpoint,就表示 redo log file 满了,这时不能再执行新的更新,得停下来先覆盖 (擦掉)一些 redo log 把 checkpoint 推进一下。

07、刷新时机(了解)

在 InnoDB 存储引擎内部,有两种 checkpoint,分别为:

  1. Sharp Checkpoint:发生在数据库关闭时将所有的脏页都刷新回磁盘,这是默认的工作方式,即参数 innodb_fast_shutdown=1 (所有的脏页)。

  2. Fuzzy Checkpoint:发生在运行时。如果数据库在运行时也使用 Sharp Checkpoint,那么数据库的可用性就会受到很大的影响。故在 InnoDB 存储引擎内部使用 Fuzzy Checkpoint 进行页的刷新,即只刷新一部分脏页,而不是刷新所有的脏页回磁盘。(一部分脏页)

  • Master Thread Checkpoint

    对于 Master Thread 中发生的 Checkpoint,差不多以每秒或每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘。这个过程是异步的,即此时 InnoDB存储引擎可以进行其他的操作,用户查询线程不会阻塞。

  • LUSH LRU LIST Checkpoint

    FLUSH LRU_LIST Checkpoint 是因为 InnoDB 存储引擎需要保证 LRU 列表中需要有差不多 100 个空闲页可供使用,可以通过参数 innodb_lru_scan_depth 控制 LRU 列表中可用页的数量,该值默认为1024,buffer pool 中 LRU 列表剩余空间低于 innodb_lru_scan_depth,移除列表尾端页时,若是脏页则触发 checkpoint。

  • Async/Sync Flush Checkpoint

    Async/Sync Flush Checkpoint 指的是重做日志文件不可用的情况,这时需要强制将一些页刷新回磁盘,而此时脏页是从脏页列表中选取的。

  • Dirty Page too much Checkpoint

    Dirty Page too much,即脏页的数量太多导致 InnoDB 存储引擎强制进行 Checkpoint。其目的总的来说还是为了保证缓冲池中有足够可用的页。其可由参数 innodb_maxdirty_pages_pct 控制。

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

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

相关文章

nodejs 实现docker 精简可视化控制

地址 https://github.com/xiaobaidadada/filecat 说明 使用react 和nodejs 实现的非常轻量的服务docker管理。

YOLOv11改进-卷积-引入小波卷积WTConv 解决多尺度小目标问题

本篇文章将介绍一个新的改进机制——WTConv(小波卷积),并阐述如何将其应用于YOLOv11中,显著提升模型性能。YOLOv11模型相比较于前几个模型在检测精度和速度上有显著提升,但其仍然受卷积核感受野大小的限制。因此&#…

【Wireshark笔记】如何在Wireshark中使用过滤器去除TCP Dup ACK

【Wireshark笔记】如何在Wireshark中使用过滤器去除TCP Dup ACK 在网络分析和故障排查中,Wireshark是最常用的工具之一。当分析TCP流量时,我们经常会遇到TCP Dup ACK(重复ACK)包。这些包通常意味着网络中的丢包或重传&#xff0c…

JRT怎么从IRIS切换到PostGreSql库

1.执行M导出得到建库脚本文件 2.下载生成的脚本到本地D盘 3.修改驱动为PostGreSql 4.修改连接串 5.到PostGreSql里面创建一个jrtlis的数据库,模式为jrt 6.启动网站点击导入脚本按钮 导入完成了就可以正常使用PostGreSql库了

QToolButton工具按钮控件

QToolButton是Qt框架中的一个特殊且功能丰富的控件,它主要用于工具栏或类似场景中,为用户提供快速访问命令或选项的按钮。通常是文字或图片或者图片文字! 构造函数 explicit QToolButton(QWidget *parent nullptr); 初始化添加图片 QToolB…

Redis中String类型常见的应用场景

目录 一. 缓存功能什么是缓存?Redis的工作原理热点数据的过期策略是什么? 二. 计数功能三. 会话(session)共享Session会话是用来解决什么问题的使用Redis集中管理Session 一. 缓存功能 什么是缓存? 缓存是一种用于存储数据的计算机硬件或软件组件. 缓存核心功能是加快数据…

VSCODE 导入cubeide工程

1.下载vscode及插件STM32 VS Code Ectersion 版本号1.0.0,之后这个有导入功能。 2.等待自动安装对应插件,提示缺少什么就补什么 3.在左侧出现stm32图标。点击Import a local project导入本地项目。 4.报错 [{"resource": "/f:V11/cmak…

批量合并同名Labelme标注文件内容

假如一批数据,分两批分别标注了分割和关键点的json数据,或是分别标注了不同的类别,使用时如果要合并使用,就需要对两个同名的json文件进行合并。 json1: json2: 合并后json: 脚本内容如下: import os imp…

HubSpot的AI技术:企业营销和销售的好帮手

现在做生意,竞争真挺大的。大家都想找到更好的方法来做营销和销售。HubSpot的AI技术,就像是给我们企业配了个智能小助手,让营销和销售变得更加轻松、高效。 推荐你喜欢的东西,购物更开心 企业老板肯定知道,让客户开心…

html 登入界面,用户注册界面相关的标签及案例

案例效果图 以上界面的完整代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</titl…

C++ 游戏开发:从基础到进阶

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Mistral AI推超强边缘AI模型Ministral 8B,支持128000个token

最近&#xff0c;法国人工智能初创公司 Mistral AI 宣布了他们的新一代语言模型 ——Ministral3B 和 Ministral8B。 这两款新模型是 “Ministraux” 系列的一部分&#xff0c;专为边缘设备和边缘计算场景而设计&#xff0c;支持高达128&#xff0c;000个 token 的上下文长度。…

Leetcode 字符串解码

该代码的算法思想可以分为以下几个步骤&#xff1a; 1. 使用栈来处理嵌套结构&#xff1a; 我们需要处理像 k[encoded_string] 这种格式&#xff0c;其中的 encoded_string 可能是嵌套的&#xff0c;即像 3[a2[c]] 这样的输入。因此&#xff0c;我们可以借助 栈&#xff08;S…

springboot 项目集成spring security(极简版)

背景 当服务需要暴露于公网的时候&#xff0c;经常需要有登录功能。通过sping security 进行一个简单的登录功能。 导入依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web<…

Android Framework AMS(06)startActivity分析-3(补充:onPause和onStop相关流程解读)

该系列文章总纲链接&#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节主要解读AMS通过startActivity启动Activity的整个流程的补充&#xff0c;更新了startActivity流程分析部分。 一般来说&#xff0c;有Activ…

第 2 章 ROS通信机制

机器人是一种高度复杂的系统性实现&#xff0c;在机器人上可能集成各种传感器(雷达、摄像头、GPS...)以及运动控制实现&#xff0c;为了解耦合&#xff0c;在ROS中每一个功能点都是一个单独的进程&#xff0c;每一个进程都是独立运行的。更确切的讲&#xff0c;ROS是进程&#…

关于Linux自带的python2.6.6升级到2.7.5版本步骤详解

CentOS 6 系统默认 Python 版本是:2.6.6 平时在使用中遇到很多的库要求是 2.7.x 版本的库。比如使用UFR升级启动脚本用python2.6.6的版本启动状态检测报错: 第一步:安装相关的编译依赖包: [root@testhost250 ~]# sudo yum install -y gcc [root@testhost250 ~]# sudo yum …

使用JMeter录制元件来录制HTTPS下的脚本

1.给测试计划添加一个线程组 2.给线程组添加【HTTP请求默认值】 3.配置【HTTP请求默认值】下面的【web服务器】参数&#xff0c;这里举例为www.baidu.com 4.在测试计划(注意是测试计划哦)上添加【非测试元件】->【HPPT(S)测试脚本记录器】 5.记下默认端口号&#xff0c;此处…

浏览器控制的无线开关

esp32-c3 作为HTTP server 控制led 灯。服务器注册两个uri 。一个"/open" 控制开&#xff0c;一个"/close"控制关。下一步再用一片c3作为客户端&#xff0c;运行http client 发送/open. /Close 模拟浏览器&#xff0c;控制led. 其实只要用手机或pc或平…

Apache Lucene 10 已发布!Lucene 硬件效率改进及其他改进

作者&#xff1a;来自 Elastic Adrien Grand Apache Lucene 10 刚刚发布&#xff0c;重点关注硬件效率&#xff01;查看主要版本亮点。 Apache Lucene 10 终于发布了&#xff01;自 Lucene 9.0&#xff08;于 2021 年 12 月发布&#xff0c;距今已有近 3 年&#xff09;以来&a…