文章目录

    • 1 redo log
      • 1.1 redo log 和二进制日志的区别
      • 1.2 redo log 的基本概念
      • 1.3 日志块(log block)
      • 1.4 log group 和 redo log file
      • 1.5 redo log 的格式
      • 1.6 日志刷盘的规则
      • 1.7 数据页刷盘的规则及 checkpoint
      • 1.8 LSN 超详细分析
      • 1.9 InnoDB 的恢复行为
      • 1.10 和 redo log 有关的几个变量
    • 2 undo log
      • 2.1 基本概念
      • 2.2 undo log 的存储方式
      • 2.3 和 undo log 相关的变量
      • 2.4 delete/update 操作的内部机制
    • 3 binlog 和事务日志的先后顺序及 group commit

InnoDB 事务日志包括redo logundo log,其中redo log是重做日志,提供前滚操作;undo log是回滚日志,提供回滚操作。undo log不是redo log的逆向过程,其实它们都算是用来恢复的日志:

  • redo log通常是物理日志,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样,它用来恢复提交后的物理数据页,且只能恢复到最后一次提交的位置。
  • undo log用来回滚行记录到某个版本,undo log一般是逻辑日志,根据每行记录进行记录。

1 redo log

1.1 redo log 和二进制日志的区别

二进制日志相关内容,可以参考「MariaDB/MySQL 的二进制日志」这篇文章。

redo log不是二进制日志。虽然二进制日志中也记录了 InnoDB 表的很多操作,也能实现重做的功能,但是它们之间有很大区别。

  • 二进制日志是在存储引擎的上层产生的,不管是什么存储引擎,对数据库进行了修改都会产生二进制日志。而redo log是 InnoDB 层产生的,只记录该存储引擎中表的修改。并且二进制日志先于redo log被记录。具体的见后文group commit小结。
  • 二进制日志记录操作的方法是逻辑性的语句。即便它是基于行格式的记录方式,其本质也还是逻辑的 SQL 设置,如该行记录的每列的值是多少。而redo log是在物理格式上的日志,它记录的是数据库中每个页的修改。
  • 二进制日志只在每次事务提交的时候一次性写入缓存中的日志“文件”(对于非事务表的操作,则是每次执行语句成功后就直接写入)。而redo log在数据准备修改前写入缓存中的redo log中,然后才对缓存中的数据执行修改操作;而且保证在发出事务提交指令时,先向缓存中的redo log写入日志,写入完成后才执行提交动作。
  • 因为二进制日志只在提交的时候一次性写入,所以二进制日志中的记录方式和提交顺序有关,且一次提交对应一次记录。而redo log中是记录的物理页的修改,redo log文件中同一个事务可能多次记录,最后一个提交的事务记录会覆盖所有未提交的事务记录。例如事务T1,可能在redo log中记录了T1-1T1-2T1-3T1*共 4 个操作,其中T1*表示最后提交时的日志记录,所以对应的数据页最终状态是T1*对应的操作结果。而且redo log是并发写入的,不同事务之间的不同版本的记录会穿插写入到redo log文件中,例如可能redo log的记录方式为T1-1T1-2T2-1T2-2T2*T1-3T1*
  • 事务日志记录的是物理页的情况,它具有幂等性,因此记录日志的方式极其简练。幂等性的意思是多次操作前后状态是一样的,例如新插入一行后又删除该行,前后状态没有变化。而二进制日志记录的是所有影响数据的操作,记录的内容较多。例如插入一行记录一次,删除该行又记录一次。

1.2 redo log 的基本概念

redo log包括两部分:一是内存中的日志缓冲(redo log buffer),该部分日志是易失性的;二是磁盘上的重做日志文件(redo log file),该部分日志是持久的。

在概念上,InnoDB 通过force log at commit机制实现事务的持久性,即在事务提交的时候,必须先将该事务的所有事务日志写入到磁盘上的redo log fileundo log file中进行持久化。

为了确保每次日志都能写入到事务日志文件中,在每次将log buffer中的日志写入日志文件的过程中都会调用一次操作系统的fsync操作(即fsync()系统调用)。因为 MariaDB/MySQL 是工作在用户空间的,MariaDB/MySQL 的log buffer处于用户空间的内存中。要写入到磁盘上的log file中(redo:ib_logfileN文件、undo:share tablespace.ibd文件),中间还要经过操作系统内核空间的os buffer,调用fsync()的作用就是将os buffer中的日志刷到磁盘上的log file中。

也就是说,从redo log buffer写日志到磁盘的redo log file中,过程如下:

innodb-engine
在此处需要注意一点,一般所说的log file并不是磁盘上的物理日志文件,而是操作系统缓存中的log file,官方手册上的意思也是如此,例如:With a value of 2, the contents of the InnoDB log buffer are written to the log file after each transaction commit and the log file is flushed to disk approximately once per second。但说实话,这不太好理解,既然都称为file了,应该已经属于物理文件了。所以在本文后续内容中都以os buffer或者file system buffer来表示官方手册中所说的log file,然后log file则表示磁盘上的物理日志文件,即log file on disk

另外,之所以要经过一层os buffer,是因为open日志文件的时候,open没有使用O_DIRECT标志位,该标志位意味着绕过操作系统层的os buffer,IO 直写到底层存储设备。不使用该标志位意味着将日志进行缓冲,缓冲到了一定容量,或者显式fsync()才会将缓冲中的刷到存储设备。使用该标志位意味着每次都要发起系统调用。比如写abcde,不使用o_direct将只发起一次系统调用,使用o_object将发起 5 次系统调用。

MySQL 支持用户自定义在commit时如何将log buffer中的日志刷log file中。这种控制通过变量innodb_flush_log_at_trx_commit的值来决定。该变量有 3 种值:0、1、2,默认为 1。但注意,这个变量只是控制commit动作是否刷新log buffer到磁盘。

  • 当设置为 1 的时候,事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO 的性能较差。
  • 当设置为 0 的时候,事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为 0 时是每秒刷新写入到磁盘中的,当系统崩溃,会丢失 1 秒钟的数据。
  • 当设置为 2 的时候,每次提交都仅写入到os buffer,然后是每秒调用fsync()os buffer中的日志写入到log file on disk

memory-buffer
注意,有一个变量innodb_flush_log_at_timeout的值为 1 秒,该变量表示的是刷日志的频率,很多人误以为是控制innodb_flush_log_at_trx_commit值为 0 和 2 时的 1 秒频率,实际上并非如此。测试时将频率设置为 5 和设置为 1,当innodb_flush_log_at_trx_commit设置为 0 和 2 的时候性能基本都是不变的。关于这个频率是控制什么的,在后面的“刷日志到磁盘的规则”中会说。

在主从复制结构中,要保证事务的持久性和一致性,需要对日志相关变量设置为如下:

  • 如果启用了二进制日志,则设置sync_binlog=1,即每提交一次事务同步写到磁盘中。
  • 总是设置innodb_flush_log_at_trx_commit=1,即每提交一次事务都写到磁盘中。

上述两项变量的设置保证了:每次提交事务都写入二进制日志和事务日志,并在提交时将它们刷新到磁盘中。选择刷日志的时间会严重影响数据修改时的性能,特别是刷到磁盘的过程。下例就测试了innodb_flush_log_at_trx_commit分别为 0、1、2 时的差距。

#创建测试表
drop table if exists test_flush_log;
create table test_flush_log(id int,name char(50))engine=innodb;#创建插入指定行数的记录到测试表中的存储过程
drop procedure if exists proc;
delimiter $$
create procedure proc(i int)
begindeclare s int default 1;declare c char(50) default repeat('a',50);while s<=i dostart transaction;insert into test_flush_log values(null,c);commit;set s=s+1;end while;
end$$
delimiter ;

当前环境下,innodb_flush_log_at_trx_commit的值为 1,即每次提交都刷日志到磁盘。测试此时插入 10W 条记录的时间。

mysql> call proc(100000);
Query OK, 0 rows affected (15.48 sec)

结果是 15.48 秒。

再测试值为 2 的时候,即每次提交都刷新到os buffer,但每秒才刷入磁盘中。

mysql> set @@global.innodb_flush_log_at_trx_commit=2;    
mysql> truncate test_flush_log;mysql> call proc(100000);
Query OK, 0 rows affected (3.41 sec)

结果插入时间大减,只需 3.41 秒。

最后测试值为 0 的时候,即每秒才刷到os buffer和磁盘。

mysql> set @@global.innodb_flush_log_at_trx_commit=0;
mysql> truncate test_flush_log;mysql> call proc(100000);
Query OK, 0 rows affected (2.10 sec)

结果只有2.10秒。

最后可以发现,其实值为 2 和 0 的时候,它们的差距并不太大,但 2 却比 0 要安全的多。它们都是每秒从os buffer刷到磁盘,它们之间的时间差体现在log buffer刷到os buffer上。因为将log buffer中的日志刷新到os buffer只是内存数据的转移,并没有太大的开销,所以每次提交和每秒刷入差距并不大。可以测试插入更多的数据来比较,以下是插入 100W 行数据的情况。从结果可见,值为 2 和 0 的时候差距并不大,但值为 1 的性能却差太多。

test-flush-log
尽管设置为 0 和 2 可以大幅度提升插入性能,但是在故障的时候可能会丢失 1 秒钟数据,这 1 秒钟很可能有大量的数据,从上面的测试结果看,100W 条记录也只消耗了 20 多秒,1 秒钟大约有 4W ~ 5W 条数据,尽管上述插入的数据简单,但却说明了数据丢失的大量性。更好的插入数据的做法是将值设置为 1,然后修改存储过程,将每次循环都提交修改为只提交一次,这样既能保证数据的一致性,也能提升性能,修改如下:

drop procedure if exists proc;
delimiter $$
create procedure proc(i int)
begindeclare s int default 1;declare c char(50) default repeat('a',50);start transaction;while s<=i DOinsert into test_flush_log values(null,c);set s=s+1;end while;commit;
end$$
delimiter ;

测试值为 1 时的情况。

mysql> set @@global.innodb_flush_log_at_trx_commit=1;
mysql> truncate test_flush_log;mysql> call proc(1000000);
Query OK, 0 rows affected (11.26 sec)

1.3 日志块(log block)

在 InnoDB 存储引擎中,redo log是以块为单位进行存储的,每个块占 512 字节,这称为redo log block。所以不管是log buffer中还是os buffer中以及redo log file on disk中,都是这样以 512 字节的块存储的。

每个redo log block由 3 部分组成:日志块头、日志块尾和日志主体。其中日志块头占用 12 字节,日志块尾占用 8 字节,所以每个redo log block的日志主体部分只有512 - 12 - 8 = 492字节。

redo-log-block

因为redo log记录的是数据页的变化,当一个数据页产生的变化需要使用超过 492 字节的redo log来记录,那么就会使用多个redo log block来记录该数据页的变化。

日志块头包含 4 部分:

  • log_block_hdr_no:占 4 字节,表示该日志块在redo log buffer中的位置 ID。
  • log_block_hdr_data_len:占 2 字节,表示该log block中已记录的log大小,写满该log block时为0x200,表示 512 字节。
  • log_block_first_rec_group:占 2 字节,表示该log block中第一个log的开始偏移位置。
  • log_block_checkpoint_no:占 4 字节,表示该log block写入检查点信息的位置。

关于log block块头的第三部分log_block_first_rec_group,因为有时候一个数据页产生的日志量超出了一个日志块,这是需要用多个日志块来记录该页的相关日志。例如,某一数据页产生了 552 字节的日志量,那么需要占用两个日志块,第一个日志块占用 492 字节,第二个日志块需要占用 60 个字节,那么对于第二个日志块来说,它的第一个log的开始位置就是73字节(60+12)。如果该部分的值和log_block_hdr_data_len相等,则说明该log block中没有新开始的日志块,即表示该日志块用来延续前一个日志块。

日志尾只有一个部分:log_block_trl_no,该值和块头的log_block_hdr_no相等。

上面所说的是一个日志块的内容,在redo log buffer或者redo log file on disk中,由很多log block组成。如下图:

redo-log-buffer

1.4 log group 和 redo log file

log group表示的是redo log group,一个组内由多个大小完全相同的redo log file组成。组内redo log file的数量由变量innodb_log_files_group决定,默认值为 2,即两个redo log file。这个组是一个逻辑的概念,并没有真正的文件来表示这是一个组,但是可以通过变量innodb_log_group_home_dir来定义组的目录,redo log file都放在这个目录下,默认是在datadir下。

mysql> show global variables like "innodb_log%";
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| innodb_log_buffer_size      | 8388608  |
| innodb_log_compressed_pages | ON       |
| innodb_log_file_size        | 50331648 |
| innodb_log_files_in_group   | 2        |
| innodb_log_group_home_dir   | ./       |
+-----------------------------+----------+[root@xuexi data]# ll /mydata/data/ib*
-rw-rw---- 1 mysql mysql 79691776 Mar 30 23:12 /mydata/data/ibdata1
-rw-rw---- 1 mysql mysql 50331648 Mar 30 23:12 /mydata/data/ib_logfile0
-rw-rw---- 1 mysql mysql 50331648 Mar 30 23:12 /mydata/data/ib_logfile1

可以看到在默认的数据目录下,有两个ib_logfile开头的文件,它们就是log group中的redo log file,而且它们的大小完全一致且等于变量innodb_log_file_size定义的值。第一个文件ibdata1是在没有开启innodb_file_per_table时的共享表空间文件,对应于开启innodb_file_per_table时的.ibd文件。

在 InnoDB 将log buffer中的redo log block刷到这些log file中时,会以追加写入的方式循环轮询写入。即先在第一个log file(即ib_logfile0)的尾部追加写,直到满了之后向第二个log file(即ib_logfile1)写。当第二个log file满了会清空一部分第一个log file继续写入。

由于是将log buffer中的日志刷到log file,所以在log file中记录日志的方式也是log block的方式。

在每个组的第一个redo log file中,前 2KB 记录 4 个特定的部分,从 2KB 之后才开始记录log block。除了第一个redo log file中会记录,log group中的其他log file不会记录这 2KB,但是却会腾出这 2KB 的空间。如下:

log-group

redo log file的大小对 InnoDB 的性能影响非常大,设置的太大,恢复的时候就会时间较长,设置的太小,就会导致在写redo log的时候循环切换redo log file

1.5 redo log 的格式

因为 InnoDB 存储引擎存储数据的单元是页(和 SQL Server 中一样),所以redo log也是基于页的格式来记录的。默认情况下,InnoDB 的页大小是 16KB(由innodb_page_size变量控制),一个页内可以存放非常多的log block(每个 512 字节),而log block中记录的是数据页的变化。其中,log block中 492 字节的部分是log body,该log body的格式分为 4 部分:

  • redo_log_type:占用 1 个字节,表示redo log的日志类型。
  • space:表示表空间的 ID,采用压缩的方式后,占用的空间可能小于 4 字节。
  • page_no:表示页的偏移量,同样是压缩过的。
  • redo_log_body:表示每个重做日志的数据部分,恢复时会调用相应的函数进行解析。例如insert语句和delete语句写入redo log的内容是不一样的。

如下图,分别是insertdelete大致的记录方式。

mlog-rec

1.6 日志刷盘的规则

log buffer中未刷到磁盘的日志称为脏日志(dirty log),其过程称之为“刷脏”。

在上面说过,默认情况下事务每次提交的时候都会刷事务日志到磁盘中,这是因为变量innodb_flush_log_at_trx_commit的值为 1。但是 InnoDB 不仅仅只会在有commit动作后才会刷日志到磁盘,这只是 InnoDB 存储引擎刷日志的规则之一。

刷日志到磁盘有以下几种规则:

  1. 发出commit动作时。已经说明过,commit发出后是否刷日志由变量innodb_flush_log_at_trx_commit控制。
  2. 每秒刷一次。这个刷日志的频率由变量innodb_flush_log_at_timeout值决定,默认是 1 秒。要注意,这个刷日志频率和commit动作无关。
  3. log buffer中已经使用的内存超过一半时。
  4. 当有checkpoint时,checkpoint在一定程度上代表了刷到磁盘时日志所处的 LSN 位置。

1.7 数据页刷盘的规则及 checkpoint

内存中(buffer pool)未刷到磁盘的数据称为脏数据(dirty data)。由于数据和日志都以页的形式存在,所以脏页表示脏数据和脏日志。上一节介绍了日志是何时刷到磁盘的,不仅仅是日志需要刷盘,脏数据页也一样需要刷盘。

在 InnoDB 中,数据刷盘的规则只有一个:checkpoint。但是触发checkpoint的情况却有几种。不管怎样,checkpoint触发后,会将buffer中脏数据页和脏日志页都刷到磁盘。

InnoDB 存储引擎中checkpoint分为两种:

  • sharp checkpoint:在重用redo log文件(例如切换日志文件)的时候,将所有已记录到redo log中对应的脏数据刷到磁盘。
  • fuzzy checkpoint:一次只刷一小部分的日志到磁盘,而非将所有脏日志刷盘。有以下几种情况会触发该检查点:
    • master thread checkpoint:由master线程控制,每秒或每 10 秒刷入一定比例的脏页到磁盘。
    • flush_lru_list checkpoint:从 MySQL5.6 开始可通过innodb_page_cleaners变量指定专门负责脏页刷盘的page cleaner线程的个数,该线程的目的是为了保证lru列表有可用的空闲页。
    • async/sync flush checkpoint:同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘(非常多是多少,有比例控制),这时候会选择同步刷到磁盘,但这很少出现;如果脏页不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘
    • dirty page too much checkpoint:脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量innodb_max_dirty_pages_pct控制,MySQL 5.6 默认的值为 75,即当脏页占缓冲池的 75% 后,就强制刷一部分脏页到磁盘。

由于刷脏页需要一定的时间来完成,所以记录检查点的位置是在每次刷盘结束之后才在redo log中标记的。

MySQL 停止时是否将脏数据和脏日志刷入磁盘,由变量innodb_fast_shutdown={0|1|2}控制,默认值为 1,即停止时只做一部分purge,忽略大多数flush操作(但至少会刷日志),在下次启动的时候再flush剩余的内容,实现fast shutdown

1.8 LSN 超详细分析

LSN 称为日志的逻辑序列号(log sequence number),在 InnoDB 存储引擎中,LSN 占用 8 个字节。LSN 的值会随着日志的写入而逐渐增大。

根据 LSN,可以获取到几个有用的信息:

  1. 数据页的版本信息。
  2. 写入的日志总量,通过 LSN 开始号码和结束号码可以计算出写入的日志量。
  3. 可以知道检查点的位置。

实际上,还可以获得很多隐式的信息。

LSN 不仅存在于redo log中,还存在于数据页中,在每个数据页的头部,有一个fil_page_lsn记录了当前页最终的 LSN 值是多少。通过数据页中的 LSN 值和redo log中的 LSN 值比较,如果页中的 LSN 值小于redo log中 LSN 值,则表示数据丢失了一部分,这时候可以通过redo log的记录来恢复到redo log中记录的 LSN 值时的状态。

redo log的 LSN 信息可以通过show engine innodb status来查看。MySQL 5.5 版本的show结果中只有 3 条记录,没有pages flushed up to

mysql> show engine innodb stauts
---
LOG
---
Log sequence number 2225502463
Log flushed up to   2225502463
Pages flushed up to 2225502463
Last checkpoint at  2225502463
0 pending log writes, 0 pending chkp writes
3201299 log i/o's done, 0.00 log i/o's/second

其中:

  • log sequence number就是当前的redo log(in buffer)中的 LSN;
  • log flushed up to是刷到redo log file on disk中的 LSN;
  • pages flushed up to是已经刷到磁盘数据页上的 LSN;
  • last checkpoint at是上一次检查点所在位置的 LSN。

InnoDB 从执行修改语句开始:

  1. 首先修改内存中的数据页,并在数据页中记录 LSN,暂且称之为data_in_buffer_lsn
  2. 并且在修改数据页的同时(几乎是同时)向redo log in buffer中写入redo log,并记录下对应的 LSN,暂且称之为redo_log_in_buffer_lsn
  3. 写完buffer中的日志后,当触发了日志刷盘的几种规则时,会向redo log file on disk刷入重做日志,并在该文件中记下对应的 LSN,暂且称之为redo_log_on_disk_lsn
  4. 数据页不可能永远只停留在内存中,在某些情况下,会触发checkpoint来将内存中的脏页(数据脏页和日志脏页)刷到磁盘,所以会在本次checkpoint脏页刷盘结束时,在redo log中记录checkpoint的 LSN 位置,暂且称之为checkpoint_lsn
  5. 要记录checkpoint所在位置很快,只需简单的设置一个标志即可,但是刷数据页并不一定很快,例如这一次checkpoint要刷入的数据页非常多。也就是说要刷入所有的数据页需要一定的时间来完成,中途刷入的每个数据页都会记下当前页所在的 LSN,暂且称之为data_page_on_disk_lsn

详细说明如下图:

checkpoint-lsn
在上图中,从上到下的横线分别代表:时间轴、buffer中数据页中记录的 LSN(data_in_buffer_lsn)、磁盘中数据页中记录的 LSN(data_page_on_disk_lsn)、buffer中重做日志记录的 LSN(redo_log_in_buffer_lsn)、磁盘中重做日志文件中记录的 LSN(redo_log_on_disk_lsn)以及检查点记录的 LSN(checkpoint_lsn)。

假设在最初时(12:0:00)所有的日志页和数据页都完成了刷盘,也记录好了检查点的 LSN,这时它们的 LSN 都是完全一致的。

假设此时开启了一个事务,并立刻执行了一个update操作,执行完成后,buffer中的数据页和redo log都记录好了更新后的 LSN 值,假设为 110。这时候如果执行show engine innodb status看各 LSN 的值,即图中处的位置状态,结果会是:

  • log sequence number(110) > log flushed up to(100) = pages flushed up to = last checkpoint at

之后又执行了一个delete语句,LSN 增长到 150。等到12:00:01时,触发redo log刷盘的规则(其中有一个规则是innodb_flush_log_at_timeout控制的默认日志刷盘频率为 1 秒),这时redo log file on disk中的 LSN 会更新到和redo log in buffer的 LSN 一样,所以都等于 150,这时show engine innodb status,即图中的位置,结果将会是:

  • log sequence number(150) = log flushed up to > pages flushed up to(100) = last checkpoint at

再之后,执行了一个update语句,缓存中的 LSN 将增长到 300,即图中的位置。

假设随后检查点出现,即图中的位置,正如前面所说,检查点会触发数据页和日志页刷盘,但需要一定的时间来完成,所以在数据页刷盘还未完成时,检查点的 LSN 还是上一次检查点的 LSN,但此时磁盘上数据页和日志页的 LSN 已经增长了,即:

  • log sequence number > log flushed up to 和 pages flushed up to > last checkpoint at

但是log flushed up topages flushed up to的大小无法确定,因为日志刷盘可能快于数据刷盘,也可能等于,还可能是慢于。但是checkpoint机制有保护数据刷盘速度是慢于日志刷盘的:当数据刷盘速度超过日志刷盘时,将会暂时停止数据刷盘,等待日志刷盘进度超过数据刷盘。

等到数据页和日志页刷盘完毕,即到了位置的时候,所有的 LSN 都等于 300。

随着时间的推移到了12:00:02,即图中位置,又触发了日志刷盘的规则,但此时buffer中的日志 LSN 和磁盘中的日志 LSN 是一致的,所以不执行日志刷盘,即此时show engine innodb status时各种 LSN 都相等。

随后执行了一个insert语句,假设buffer中的 LSN 增长到了 800,即图中位置。此时各种 LSN 的大小和位置时一样。

随后执行了提交动作,即位置。默认情况下,提交动作会触发日志刷盘,但不会触发数据刷盘,所以show engine innodb status的结果是:

  • log sequence number = log flushed up to > pages flushed up to = last checkpoint at

最后随着时间的推移,检查点再次出现,即图中位置。但是这次检查点不会触发日志刷盘,因为日志的 LSN 在检查点出现之前已经同步了。假设这次数据刷盘速度极快,快到一瞬间内完成而无法捕捉到状态的变化,这时show engine innodb status的结果将是各种 LSN 相等。

1.9 InnoDB 的恢复行为

在启动 InnoDB 的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。

因为redo log记录的是数据页的物理变化,因此恢复的时候速度比逻辑日志(如二进制日志)要快很多。而且,InnoDB 自身也做了一定程度的优化,让恢复速度变得更快。

重启 InnoDB 时,checkpoint表示已经完整刷到磁盘上data page上的 LSN,因此恢复时仅需要恢复从checkpoint开始的日志部分。例如,当数据库在上一次checkpoint的 LSN 为 10000 时宕机,且事务是已经提交过的状态。启动数据库时会检查磁盘中数据页的 LSN,如果数据页的 LSN 小于日志中的 LSN,则会从检查点开始恢复。

还有一种情况,在宕机前正处于checkpoint的刷盘过程,且数据页的刷盘进度超过了日志页的刷盘进度。这时候一宕机,数据页中记录的 LSN 就会大于日志页中的 LSN,在重启的恢复过程中会检查到这一情况,这时超出日志进度的部分将不会重做,因为这本身就表示已经做过的事情,无需再重做。

另外,事务日志具有幂等性,所以多次操作得到同一结果的行为在日志中只记录一次。而二进制日志不具有幂等性,多次操作会全部记录下来,在恢复的时候会多次执行二进制日志中的记录,速度就慢得多。例如,某记录中id初始值为 2,通过update将值设置为了 3,后来又设置成了 2,在事务日志中记录的将是无变化的页,根本无需恢复;而二进制会记录下两次update操作,恢复时也将执行这两次update操作,速度比事务日志恢复更慢。

1.10 和 redo log 有关的几个变量

  • innodb_flush_log_at_trx_commit={0|1|2}:指定何时将事务日志刷到磁盘,默认为 1。
    • 0 表示每秒将log buffer同步到os buffer且从os buffer刷到磁盘日志文件中。
    • 1 表示每事务提交都将log buffer同步到os buffer且从os buffer刷到磁盘日志文件中。
    • 2 表示每事务提交都将log buffer同步到os buffer但每秒才从os buffer刷到磁盘日志文件中。
  • innodb_log_buffer_sizelog buffer的大小,默认 8M
  • innodb_log_file_size:事务日志的大小,默认 5M
  • innodb_log_files_group = 2:事务日志组中的事务日志文件个数,默认 2 个
  • innodb_log_group_home_dir = ./:事务日志组路径,当前目录表示数据目录
  • innodb_mirrored_log_groups = 1:指定事务日志组的镜像组个数,但镜像功能好像是强制关闭的,所以只有一个log group。在 MySQL5.7 中该变量已经移除。

2 undo log

2.1 基本概念

undo log有两个作用:提供回滚和多个行版本控制(MVCC)。

在数据修改的时候,不仅记录了redo log,还记录了相对应的undo log,如果因为某些原因导致事务失败或回滚了,可以借助该undo log进行回滚。

undo logredo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。

当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。在应用进行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。

undo log是采用段(segment)的方式来记录的,每个undo操作在记录的时候占用一个undo log segment

另外,undo log也会产生redo log,因为undo log也要实现持久性保护。

2.2 undo log 的存储方式

InnoDB 存储引擎对undo log的管理采用段的方式。rollback segment称为回滚段,每个回滚段中有 1024 个undo log segment

在以前老版本,只支持 1 个rollback segment,这样就只能记录 1024 个undo log segment。后来 MySQL5.5 可以支持 128 个rollback segment,即支持128*1024undo操作,还可以通过变量 innodb_undo_logs (MySQL5.6 版本以前该变量是innodb_rollback_segments)自定义多少个rollback segment,默认值为 128。

undo log默认存放在共享表空间中。

[root@xuexi data]# ll /mydata/data/ib*
-rw-rw---- 1 mysql mysql 79691776 Mar 31 01:42 /mydata/data/ibdata1
-rw-rw---- 1 mysql mysql 50331648 Mar 31 01:42 /mydata/data/ib_logfile0
-rw-rw---- 1 mysql mysql 50331648 Mar 31 01:42 /mydata/data/ib_logfile1

如果开启了innodb_file_per_table,将放在每个表的.ibd文件中。

在 MySQL5.6 中,undo log的存放位置还可以通过变量innodb_undo_directory来自定义存放目录,默认值为.表示datadir

默认rollback segment全部写在一个文件中,但可以通过设置变量innodb_undo_tablespaces平均分配到多少个文件中。该变量默认值为 0,即全部写入一个表空间文件。该变量为静态变量,只能在数据库示例停止状态下修改,如写入配置文件或启动时带上对应参数。但是 InnoDB 存储引擎在启动过程中提示,不建议修改为非 0 的值,如下:

2017-03-31 13:16:00 7f665bfab720 InnoDB: Expected to open 3 undo tablespaces but was able
2017-03-31 13:16:00 7f665bfab720 InnoDB: to find only 0 undo tablespaces.
2017-03-31 13:16:00 7f665bfab720 InnoDB: Set the innodb_undo_tablespaces parameter to the
2017-03-31 13:16:00 7f665bfab720 InnoDB: correct value and retry. Suggested value is 0

2.3 和 undo log 相关的变量

undo log相关的变量在 MySQL5.6 中已经变得很少。如下:它们的意义在上文中已经解释了。

 mysql> show variables like "%undo%";
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_undo_directory   | .     |
| innodb_undo_logs        | 128   |
| innodb_undo_tablespaces | 0     |
+-------------------------+-------+

2.4 delete/update 操作的内部机制

当事务提交的时候,InnoDB 不会立即删除undo log,因为后续还可能会用到undo log,如隔离级别为repeatable read时,事务读取的都是开启事务时的最新提交行版本,只要该事务不结束,该行版本就不能删除,即undo log不能删除。

但是在事务提交的时候,会将该事务对应的undo log放入到删除列表中,未来通过purge来删除。并且提交事务时,还会判断undo log分配的页是否可以重用,如果可以重用,则会分配给后面来的事务,避免为每个独立的事务分配独立的undo log页而浪费存储空间和性能。

通过undo log记录deleteupdate操作的结果发现:(insert操作无需分析,就是插入行而已)

  • delete操作实际上不会直接删除,而是将delete对象打上delete flag,标记为删除,最终的删除操作是purge线程完成的。
  • update分为两种情况:update的列是否是主键列。
    • 如果不是主键列,在undo log中直接反向记录是如何update的,即update是直接进行的。
    • 如果是主键列,update分两部执行:先删除该行,再插入一行目标行。

3 binlog 和事务日志的先后顺序及 group commit

如果事务不是只读事务,即涉及到了数据的修改,默认情况下会在commit的时候调用fsync()将日志刷到磁盘,保证事务的持久性。

但是一次刷一个事务的日志性能较低,特别是事务集中在某一时刻时事务量非常大的时候。 InnoDB 提供了group commit功能,可以将多个事务的事务日志通过一次fsync()刷到磁盘中。

因为事务在提交的时候不仅会记录事务日志,还会记录二进制日志,但是它们谁先记录呢?二进制日志是 MySQL 的上层日志,先于存储引擎的事务日志被写入。

在 MySQL5.6 以前,当事务提交(即发出commit指令)后,MySQL 接收到该信号进入commit prepare阶段;进入prepare阶段后,立即写内存中的二进制日志,写完内存中的二进制日志后就相当于确定了commit操作;然后开始写内存中的事务日志;最后将二进制日志和事务日志刷盘,它们如何刷盘,分别由变量sync_binloginnodb_flush_log_at_trx_commit控制。

但因为要保证二进制日志和事务日志的一致性,在提交后的prepare阶段会启用一个prepare_commit_mutex锁来保证它们的顺序性和一致性。但这样会导致开启二进制日志后group commmit失效,特别是在主从复制结构中,几乎都会开启二进制日志。

在 MySQL5.6 中进行了改进。提交事务时,在存储引擎层的上一层结构中会将事务按序放入一个队列,队列中的第一个事务称为leader,其他事务称为followerleader控制着follower的行为。虽然顺序还是一样先刷二进制,再刷事务日志,但是机制完全改变了:删除了原来的prepare_commit_mutex行为,也能保证即使开启了二进制日志,group commit也是有效的。

MySQL5.6 中分为 3 个步骤:flush阶段、sync阶段以及commit阶段。

flush-sync-commit

  • flush阶段:向内存中写入每个事务的二进制日志。
  • sync阶段:将内存中的二进制日志刷盘。若队列中有多个事务,那么仅一次fsync操作就完成了二进制日志的刷盘操作。这在 MySQL5.6 中称为 BLGC(binary log group commit)。
  • commit阶段:leader根据顺序调用存储引擎层事务的提交,由于 InnoDB 本就支持group commit,所以解决了因为锁prepare_commit_mutex而导致的group commit失效问题。

flush阶段写入二进制日志到内存中,但不是写完就进入sync阶段的,而是要等待一定的时间,多积累几个事务的binlog一起进入sync阶段,等待时间由变量binlog_max_flush_queue_time决定,默认值为 0 表示不等待直接进入sync,设置该变量为一个大于 0 的值的好处是group中的事务多了,性能会好一些,但是这样会导致事务的响应时间变慢,所以建议不要修改该变量的值,除非事务量非常多并且不断的在写入和更新。

进入到sync阶段,会将binlog从内存中刷入到磁盘,刷入的数量和单独的二进制日志刷盘一样,由变量sync_binlog控制。

当有一组事务在进行commit阶段时,其他新事务可以进行flush阶段,它们本就不会相互阻塞,所以group commit会不断生效。当然,group commit的性能和队列中的事务数量有关,如果每次队列中只有 1 个事务,那么group commit和单独的commit没什么区别,当队列中事务越来越多时,即提交事务越多越快时,group commit的效果越明显。

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

相关文章

  1. Python编程思想【系列文章】

    本系列文章持续更新中.......李宁老师已经在「极客起源」 微信公众号推出《Python编程思想》电子书,囊括了Python的核心技术,以及Python的主要函数库的使用方法。读者可以在「极客起源」 公众号中输入 160442 开始学习,或点击「极客起源」公众号下方的「编程思想」 > 「…...

    2024/4/27 17:51:11
  2. 要学就学透彻!Spring Security 中 CSRF 防御源码解析

    上篇文章松哥和大家聊了什么是 CSRF 攻击,以及 CSRF 攻击要如何防御。主要和大家聊了 Spring Security 中处理该问题的几种办法。 今天松哥来和大家简单的看一下 Spring Security 中,CSRF 防御源码。 本文是本系列第 19 篇,阅读本系列前面文章有助于更好的理解本文:挖一个大…...

    2024/4/27 18:06:52
  3. OpenCV图像相似度检测,Python实现

    OpenCV图像相似度检测,简单的说是大图中找小图,以图找图。假设把大图中的一部分图Android小机器人检测出来并用红色的线框出来。# OpenCV图像相似度检测matchTemplate,Python实现 import cv2 as cvif __name__ == "__main__":# 先把图片灰度处理。img = cv.imread…...

    2024/4/27 14:03:58
  4. 整理了八个开源的 Spring Boot 学习资源

    Spring Boot 算是目前 Java 领域最火的技术栈了,松哥年初出版的 《Spring Boot + Vue 全栈开发实战》迄今为止已经加印了多次,Spring Boot 的受欢迎程度可见一斑。今天松哥整理了几个优质 Spring Boot 开源项目给大家参考,希望能够帮助到正在学习 Spring Boot 的小伙伴! 1.…...

    2024/4/23 15:09:12
  5. 自定义mvc框架

    自定义mvc框架分享 文章目录自定义mvc框架分享实现效果图使用工具类程序运行流程总结 实现效果图使用工具类程序运行流程 1,发送一个请求跳转到xml配置文件中处理请求进入主控制器拦截到.action进行处理获取到请求路径再获取* 号部分的内容进行截取,根据*查找子控制器将请求委…...

    2024/4/27 17:56:40
  6. solr —— 1 全文检索Solr8.0第一部分

    solr,毕设啊,快被写完吧1 solr介绍什么是solrLucene 与 Solr 与 ES为什么要用slor2 HelloWorld2.1 项目安装部署2.2 项目安装配置创建核心创建document(表)添加文件查询数据3 solr后台管理页面详解 控制面板5 全文检索千万级别数据实战,全面剖析架构设计,大数据瓶颈突破6 数…...

    2024/4/27 16:21:48
  7. Git的常用命令

    一,.gitignore文件的配置 在提交代码的时候,有些东西比如.idea这类本地的文件,是不需要提交到远程的,这个时候,我们就需要进行.gitignore文件的配置 1,在本地克隆仓库 2,进入仓库,创建.gitignore文件:vim .gitignore 3,编辑.gitignore文件 *.aa 忽略以.aa结尾的…...

    2024/4/27 14:27:14
  8. iptables 基础知识

    文章目录基础概念基本命令--help 参数查看增加删除修改保存规则匹配条件基本匹配条件扩展匹配条件tcp 扩展模块iprange 扩展模块string 扩展模块time 扩展模块state自定义链动作REJECTLOGSNATDNATMASQUERADEREDIRECT 基础概念 四张表:raw mangle nat filter当表位于同一个链时…...

    2024/4/27 18:31:23
  9. Python if __name__ == __main__的简单理解

    通俗来讲,if __name__ == __main__就是实现在程序/模块之间互相调用时声明一个运行界限的功能。程序/模块之间互相调用时if __name__ == __main__之前的语句将被执行,而之后的将被忽略。 举个小例子: 新建一个py文件,命名为’ t ‘. a = 1 b = 2 if __name__ == __main__:p…...

    2024/4/19 11:18:00
  10. OpenCV学习笔记

    一、图像的加载、修改、保存图像加载:cv:imread—加载图像文件成文一个Mat对象 图像修改:cv:cvtColor—把图像从一个色彩空间转到另一个色彩空间(输 入,输出,色彩空间转换) 图像保存:imwrite 创建openCV窗口:nameWindow 图像显示到窗口:imshow二、矩阵的掩膜操作获取像…...

    2024/4/27 16:44:07
  11. 我的码农时代

    我的码农时代大学期间敲代码经常给我带来小小的收获感,因此我逐渐喜欢上了编程。由于是机械大类专业,我的第一份工作是一个汽车制造企业的研发岗。但是工作后我的脑海里时常会浮现出自己代码运行成功后的喜悦,最后我决定追寻我内心深处的想法,现在我将以我内心的的这份炽热…...

    2024/4/27 14:32:23
  12. 使用python批量解压7z格式压缩包

    最近下载了许多7z格式的压缩包,但又不想一个个单独的去解压,所以便百度了下python解压压缩包的方法,常见的有导入zipfile模块,我这里用的是使用系统的cmd命令去调用7-zip软件去进行解压缩。首先到网上下载7-zip软件安装下载地址 安装完成后找到安装路径,等下使用cmd命令要…...

    2024/4/27 17:25:51
  13. 扇型域上的Dirichlet问题 | 分离变量法(七)| 偏微分方程(十九)

    求解扇型域上的Dirichlet问题 {Δ2u=0,1<r<e,0<θ<π2u∣r=1=u∣r=e=0u∣θ=0=0,u∣θ=π2=g(r)(15) \begin{cases} \Delta_2u=0, \quad 1<r<e,0<\theta<\frac{\pi}{2} \\ u|_{r=1}=u|_{r=e}=0 \\ u|_{\theta=0}=0, \quad u|_{\theta=\frac{\pi}{2}}=g…...

    2024/4/19 11:24:43
  14. volatile可见性禁重排原理以及不保证原子性解决方案,volatile下的双端检锁机制单例模式的原理

    先说说并发和并行的区别 1.并发是多个线程同时访问 2.并行是多个方面一起正在做 volatile是Java虚拟机提供的轻量级同步机制 三大特性:保证可见性,不保证原子性,禁止指令重排 JMM(java内存模型) 高并发系统还是单机版系统(高并发伴随很多问题,不得不研究底层JMM)JMM第一…...

    2024/4/17 4:17:13
  15. python基础语法之模块

    模块 1.模块化模块化指将一个完整的程序分解为一个一个小模块通过将这些模块足额,来搭建出一个完整的程序2.模块的优点1.方便开发2.方便维护3。模块可以服用3.创建模块在Python中一个py文件就是一个模块在一个模块中引入外部模块可以引入同一个模块多次,单模块的实例只会执行…...

    2024/4/23 15:09:12
  16. 攻防世界web新手区webshell

    打开场景后发现页面上有一句话木马,密码是shell,打开中国蚁剑等扫描工具,添加地址输入密码扫描(以下一蚁剑为例):添加场景URL(即网址),填写密码:打开,发现有flag的txt文件,打开即得flag:...

    2024/4/23 15:09:16
  17. docker 运行portainer

    portainer:docker图像化管理工具,提供一个后台管理面板: (1)下载安装: docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --name prtainer portainer/portainer2.界面查看...

    2024/4/23 15:09:10
  18. 【Learning】《项目管理》相关基础工具

    工具格式将随具体业务及实际应用场景调整 一、项目限制三角形 成本、进度、质量 二、 工作陈述模板项目工作陈述书 说明项目名称项目目的 为什么要做这个项目?项目目标及衡量标准 项目实现的目标是什么?(目标要符合SMART原则)项目范围 必须做什么——需要哪些工作?是否有相…...

    2024/4/25 21:31:24
  19. linux服务器部署SpringBoot项目并查看项目运行日志

    在Linux服务器上部署SpringBoot项目: 1.首先将SpringBoot项目打包成JAR包,通过xFTP或者其他工具将JAR包上传到Linux上,然后执行如下命令启动项目: java -jar xxx.jar & 该命令启动jar,一旦Xshell窗口关闭,JAR就停止运行了. 如果想让项目在后台一直运行,通过如下命令启动JAR…...

    2024/4/23 15:09:12
  20. 我的shiro自白-2

    一. Shiro 集成 Web 可以参考http://shiro.apache.org/web.html 实例代码可参考这里新建maven项目上边使用webapp是开发maven下的jsp项目,需要修改JRE到1.8。webapp/下就是存放jsp等静态网络资源的地方。pom.xml配置如下:<project xmlns="http://maven.apache.org/PO…...

    2024/4/23 15:09:07

最新文章

  1. java中http调用组件深入详解

    目录 一、前言 二、http调用概述 2.1 什么是http调用 2.1.1 http调用步骤 2.2 HTTP调用特点 2.3 HTTP调用应用场景 三、微服务场景下http调用概述 3.1 微服务开发中http调用场景 3.2 微服务组件中http的应用 四、常用的http调用组件 4.1 java中常用的http组件介绍 4…...

    2024/4/27 18:58:12
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 从头开发一个RISC-V的操作系统(二)RISC-V 指令集架构介绍

    文章目录 前提ISA的基本介绍ISA是什么CISC vs RISCISA的宽度 RISC-V指令集RISC-V ISA的命名规范模块化的ISA通用寄存器Hart特权级别内存管理与保护异常和中断 目标&#xff1a;通过这一个系列课程的学习&#xff0c;开发出一个简易的在RISC-V指令集架构上运行的操作系统。 前提…...

    2024/4/24 5:34:22
  4. 手机无线投屏到windows11电脑

    1 安装无线投影组件 2 电脑端打开允许其他设备投影的开关 3 手机找到投屏选项 4 手机搜索可用设备连接即可 这里的官方文档给的不太好,给了一些让人眼花撩乱的信息,以下是经过整合的有效信息...

    2024/4/26 12:46:48
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/26 18:09:39
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/26 20:12:18
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/26 23:05:52
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/27 4:00:35
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/26 21:56:58
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/27 9:01:45
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/25 18:39:16
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/26 22:01:59
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/25 18:39:14
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/26 23:04:58
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/25 2:10:52
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/25 18:39:00
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/26 19:46:12
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/27 11:43:08
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/27 8:32:30
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57