MySQL redo log及recover过程浅析

2023-11-14

MySQL redo log及recover过程浅析

写在前面:作者水平有限,欢迎不吝赐教,一切以最新源码为准。

InnoDB redo log

首先介绍下Innodb redo log是什么,为什么需要记录redo log,以及redo log的作用都有哪些。这些作为常识,只是为了本文完整。
 
InnoDB有buffer pool(简称bp)。bp是数据库页面的缓存,对InnoDB的任何修改操作都会首先在bp的page上进行,然后这样的页面将被标记为dirty并被放到专门的flush list上,后续将由master thread或专门的刷脏线程阶段性的将这些页面写入磁盘(disk or ssd)。这样的好处是避免每次写操作都操作磁盘导致大量的随机IO,阶段性的刷脏可以将多次对页面的修改merge成一次IO操作,同时异步写入也降低了访问的时延。然而,如果在dirty page还未刷入磁盘时,server非正常关闭,这些修改操作将会丢失,如果写入操作正在进行,甚至会由于损坏数据文件导致数据库不可用。为了避免上述问题的发生,Innodb将所有对页面的修改操作写入一个专门的文件,并在数据库启动时从此文件进行恢复操作,这个文件就是redo log file。这样的技术推迟了bp页面的刷新,从而提升了数据库的吞吐,有效的降低了访问时延。带来的问题是额外的写redo log操作的开销(顺序IO,当然很快),以及数据库启动时恢复操作所需的时间。
 
接下来将结合MySQL 5.6的代码看下Log文件的结构、生成过程以及数据库启动时的恢复流程。
 
Log文件结构
Redo log文件包含一组log files,其会被循环使用。Redo log文件的大小和数目可以通过特定的参数设置,详见: innodb_log_file_size 和  innodb_log_files_in_group 。每个log文件有一个文件头,其代码在"storage/innobase/include/log0log.h"中,我们看下log文件头都记录了哪些信息:
669 /* Offsets of a log file header */
670 #define LOG_GROUP_ID    0 /* log group number */
671 #define LOG_FILE_START_LSN  4 /* lsn of the start of data in this
672           log file */
673 #define LOG_FILE_NO   12  /* 4-byte archived log file number;
674           this field is only defined in an
675           archived log file */
676 #define LOG_FILE_WAS_CREATED_BY_HOT_BACKUP 16
677           /* a 32-byte field which contains
678           the string 'ibbackup' and the
679           creation time if the log file was
680           created by ibbackup --restore;
681           when mysqld is first time started
682           on the restored database, it can
683           print helpful info for the user */
684 #define LOG_FILE_ARCH_COMPLETED OS_FILE_LOG_BLOCK_SIZE
685           /* this 4-byte field is TRUE when
686           the writing of an archived log file
687           has been completed; this field is
688           only defined in an archived log file */
689 #define LOG_FILE_END_LSN  (OS_FILE_LOG_BLOCK_SIZE + 4)
690           /* lsn where the archived log file
691           at least extends: actually the
692           archived log file may extend to a
693           later lsn, as long as it is within the
694           same log block as this lsn; this field
695           is defined only when an archived log
696           file has been completely written */
697 #define LOG_CHECKPOINT_1  OS_FILE_LOG_BLOCK_SIZE
698           /* first checkpoint field in the log
699           header; we write alternately to the
700           checkpoint fields when we make new
701           checkpoints; this field is only defined
702           in the first log file of a log group */
703 #define LOG_CHECKPOINT_2  (3 * OS_FILE_LOG_BLOCK_SIZE)
704           /* second checkpoint field in the log
705           header */
706 #define LOG_FILE_HDR_SIZE (4 * OS_FILE_LOG_BLOCK_SIZE)
日志文件头共占用4个OS_FILE_LOG_BLOCK_SIZE的大小,这里对部分字段做简要介绍:
1.    LOG_GROUP_ID               这个log文件所属的日志组,占用4个字节,当前都是0;
2.    LOG_FILE_START_LSN     这个log文件记录的初始数据的lsn,占用8个字节;
3.    LOG_FILE_WAS_CRATED_BY_HOT_BACKUP   备份程序所占用的字节数,共占用32字节,如xtrabackup在备份时会在xtrabackup_logfile文件中记录"xtrabackup backup_time";
4.    LOG_CHECKPOINT_1/LOG_CHECKPOINT_2   两个记录InnoDB checkpoint信息的字段,分别从文件头的第二个和第四个block开始记录,只使用日志文件组的第一个日志文件。
       这里多说两句,每次checkpoint后InnoDB都需要更新这两个字段的值,因此redo log的写入并非严格的顺序写;
    
每个log文件包含许多log records。log records将以OS_FILE_LOG_BLOCK_SIZE(默认值为512字节)为单位顺序写入log文件。每一条记录都有自己的LSN(log sequence number,表示从日志记录创建开始到特定的日志记录已经写入的字节数)。每个Log Block包含一个header段、一个tailer段,以及一组log records。
 
首先看下Log Block header。block header的开始4个字节是log block number,表示这是第几个block块。其是通过LSN计算得来,计算的函数是log_block_convert_lsn_to_no();接下来两个字节表示该block中已经有多少个字节被使用;再后边两个字节表示该block中作为一个新的MTR开始log record的偏移量,由于一个block中可以包含多个MTR记录的log,所以需要有记录表示此偏移量。再然后四个字节表示该block的checkpoint number。block trailer占用四个字节,表示此log block计算出的checksum值,用于正确性校验,MySQL5.6提供了若干种计算checksum的算法,这里不再赘述。我们可以结合代码中给出的注释,再了解下header和trailer的各个字段的含义。
580 /* Offsets of a log block header */
581 #define LOG_BLOCK_HDR_NO  0 /* block number which must be > 0 and
582           is allowed to wrap around at 2G; the
583           highest bit is set to 1 if this is the
584           first log block in a log flush write
585           segment */
586 #define LOG_BLOCK_FLUSH_BIT_MASK 0x80000000UL
587           /* mask used to get the highest bit in
588           the preceding field */
589 #define LOG_BLOCK_HDR_DATA_LEN  4 /* number of bytes of log written to
590           this block */
591 #define LOG_BLOCK_FIRST_REC_GROUP 6 /* offset of the first start of an
592           mtr log record group in this log block,
593           0 if none; if the value is the same
594           as LOG_BLOCK_HDR_DATA_LEN, it means
595           that the first rec group has not yet
596           been catenated to this log block, but
597           if it will, it will start at this
598           offset; an archive recovery can
599           start parsing the log records starting
600           from this offset in this log block,
601           if value not 0 */
602 #define LOG_BLOCK_CHECKPOINT_NO 8 /* 4 lower bytes of the value of
603           log_sys->next_checkpoint_no when the
604           log block was last written to: if the
605           block has not yet been written full,
606           this value is only updated before a
607           log buffer flush */
608 #define LOG_BLOCK_HDR_SIZE  12  /* size of the log block header in
609           bytes */
610
611 /* Offsets of a log block trailer from the end of the block */
612 #define LOG_BLOCK_CHECKSUM  4 /* 4 byte checksum of the log block
613           contents; in InnoDB versions
614           < 3.23.52 this did not contain the
615           checksum but the same value as
616           .._HDR_NO */
617 #define LOG_BLOCK_TRL_SIZE  4 /* trailer size in bytes */

 

Log 记录生成
在介绍了log file和log block的结构后,接下来描述log record在InnoDB内部是如何生成的,其“生命周期”是如何在内存中一步步流转并最终写入磁盘中的。这里涉及到两块内存缓冲,涉及到mtr/log_sys等内部结构,后续会一一介绍。
 
首先介绍下log_sys。log_sys是InnoDB在内存中保存的一个全局的结构体(struct名为log_t,global object名为log_sys),其维护了一块全局内存区域叫做log buffer(log_sys->buf),同时维护有若干lsn值等信息表示logging进行的状态。其在log_init函数中对所有的内部区域进行分配并对各个变量进行初始化。
 
log_t的结构体很大,这里不再粘出来,可以自行看"storage/innobase/include/log0log.h: struct log_t"。下边会对其中比较重要的字段值加以说明:
log_sys->lsn 接下来将要生成的log record使用此lsn的值
log_sys->flushed_do_disk_lsn
redo log file已经被刷新到此lsn。比该lsn值小的日志记录已经被安全的记录在磁盘上
log_sys->write_lsn
当前正在执行的写操作使用的临界lsn值;
log_sys->current_flush_lsn
当前正在执行的write + flush操作使用的临界lsn值,一般和log_sys->write_lsn相等;
log_sys->buf
内存中全局的log buffer,和每个mtr自己的buffer有所区别;
log_sys->buf_size
log_sys->buf的size
log_sys->buf_free
写入buffer的起始偏移量
log_sys->buf_next_to_write
buffer中还未写到log file的起始偏移量。下次执行write+flush操作时,将会从此偏移量开始
log_sys->max_buf_free
确定flush操作执行的时间点,当log_sys->buf_free比此值大时需要执行flush操作,具体看log_check_margins函数
lsn是联系dirty page,redo log record和redo log file的纽带。在每个redo log record被拷贝到内存的log buffer时会产生一个相关联的lsn,而每个页面修改时会产生一个log record,从而每个数据库的page也会有一个相关联的lsn,这个lsn记录在每个page的header字段中。为了保证WAL(Write-Ahead-Logging)要求的逻辑,dirty page要求其关联lsn的log record已经被写入log file才允许执行flush操作。
 
接下来介绍mtr。mtr是mini-transactions的缩写。其在代码中对应的结构体是mtr_t,内部有一个局部buffer,会将一组log record集中起来,批量写入log buffer。mtr_t的结构体如下所示:
376 /* Mini-transaction handle and buffer */
377 struct mtr_t{
378 #ifdef UNIV_DEBUG
379   ulint   state;  /*!< MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED */
380 #endif
381   dyn_array_t memo; /*!< memo stack for locks etc. */
382   dyn_array_t log;  /*!< mini-transaction log */
383   unsigned  inside_ibuf:1;
384         /*!< TRUE if inside ibuf changes */
385   unsigned  modifications:1;
386         /*!< TRUE if the mini-transaction
387         modified buffer pool pages */
388   unsigned  made_dirty:1;
389         /*!< TRUE if mtr has made at least
390         one buffer pool page dirty */
391   ulint   n_log_recs;
392         /* count of how many page initial log records
393         have been written to the mtr log */
394   ulint   n_freed_pages;
395         /* number of pages that have been freed in
396         this mini-transaction */
397   ulint   log_mode; /* specifies which operations should be
398         logged; default value MTR_LOG_ALL */
399   lsn_t   start_lsn;/* start lsn of the possible log entry for
400         this mtr */
401   lsn_t   end_lsn;/* end lsn of the possible log entry for
402         this mtr */
403 #ifdef UNIV_DEBUG
404   ulint   magic_n;
405 #endif /* UNIV_DEBUG */
406 };
mtr_t::log        --作为mtr的局部缓存,记录log record;
mtr_t::memo    --包含了一组由此mtr涉及的操作造成的脏页列表,其会在mtr_commit执行后添加到flush list(参见mtr_memo_pop_all()函数);
 
mtr的一个典型应用场景如下:
1.    创建一个mtr_t类型的对象;
2.    执行mtr_start函数,此函数将会初始化mtr_t的字段,包括local buffer;
3.    在对内存bp中的page进行修改的同时,调用mlog_write_ulint类似的函数,生成redo log record,保存在local buffer中;
4.    执行mtr_commit函数,此函数将会将local buffer中的redo log拷贝到全局的log_sys->buffer,同时将脏页添加到flush list,供后续执行flush操作时使用;
 
mtr_commit函数调用mtr_log_reserve_and_write,进而调用log_write_low执行上述的拷贝操作。如果需要,此函数将会在log_sys->buf上创建一个新的log block,填充header、tailer以及计算checksum。
 
我们知道,为了保证数据库ACID特性中的原子性和持久性,理论上,在事务提交时,redo log应已经安全原子的写到磁盘文件之中。回到MySQL,文件内存中的log_sys->buffer何时以及如何写入磁盘中的redo log file与innodb_flush_log_at_trx_commit的设置密切相关。无论对于DBA还是MySQL的使用者对这个参数都已经相当熟悉,这里直接举例不同取值时log子系统是如何操作的。
 
innodb_flush_log_at_trx_commit=1/2。此时每次事务提交时都会写redo log,不同的是1对应write+flush,2只write,而由指定线程周期性的执行flush操作(周期多为1s)。执行write操作的函数是log_group_write_buf,其由log_write_up_to函数调用。一个典型的调用栈如下:
(trx_commit_in_memory()  /
trx_commit_complete_for_mysql()  /
trx_prepare() e.t.c)->
trx_flush_log_if_needed()->
trx_flush_log_if_needed_low()->
log_write_up_to()->
log_group_write_buf().
log_group_write_buf会再调用innodb封装的底层IO系统,其实现很复杂,这里不再展开。
 
innodb_flush_log_at_trx_commit=0时,每次事务commit不会再调用写redo log的函数,其写入逻辑都由master_thread完成,典型的调用栈如下:
srv_master_thread()->
(srv_master_do_active_tasks() / srv_master_do_idle_tasks() / srv_master_do_shutdown_tasks())->
srv_sync_log_buffer_in_background()->
log_buffer_sync_in_background()->log_write_up_to()->... .
除此参数的影响之外,还有一些场景下要求刷新redo log文件。这里举几个例子:
1)为了保证write ahead logging(WAL),在刷新脏页前要求其对应的redo log已经写到磁盘,因此需要调用log_write_up_to函数;
2)为了循环利用log file,在log file空间不足时需要执行checkpoint(同步或异步),此时会通过调用log_checkpoint执行日志刷新操作。checkpoint会极大的影响数据库的性能,这也是log file不能设置的太小的主要原因;
3)在执行一些管理命令时要求刷新redo log文件,比如关闭数据库;
 
这里再简要总结一下一个log record的“生命周期”:
1.    redo log record首先由mtr生成并保存在mtr的local buffer中。这里保存的redo log record需要记录数据库恢复阶段所需的所有信息,并且要求恢复操作是幂等的;
2.    当mtr_commit被调用后,redo log record被记录在全局内存的log buffer之中;
3.    根据需要(需要额外的空间?事务commit?),redo log buffer将会write(+flush)到磁盘上的redo log文件中,此时redo log已经被安全的保存起来;
4.    mtr_commit执行时会给每个log record生成一个lsn,此lsn确定了其在log file中的位置;
5.    lsn同时是联系redo log和dirty page的纽带,WAL要求redo log在刷脏前写入磁盘,同时,如果lsn相关联的页面都已经写入了磁盘,那么磁盘上redo log file中对应的log record空间可以被循环利用;
6.    数据库恢复阶段,使用被持久化的redo log来恢复数据库;
 
接下来介绍redo log在数据库恢复阶段所起的重要作用。
 
Log Recovery
InnoDB的recovery的函数入口是innobase_start_or_create_for_mysql,其在mysql启动时由innobase_init函数调用。我们接下来看下源码,在此函数内可以看到如下两个函数调用:
1.    recv_recovery_from_checkpoint_start
2.    recv_recovery_from_checkpoint_finish
代码注释中特意强调,在任何情况下,数据库启动时都会尝试执行recovery操作,这是作为函数启动时正常代码路径的一部分。
主要恢复工作在第一个函数内完成,第二个函数做扫尾清理工作。这里,直接看函数的注释可以清楚函数的具体工作是什么。
146 /** Wrapper for recv_recovery_from_checkpoint_start_func().
147 Recovers from a checkpoint. When this function returns, the database is able
148 to start processing of new user transactions, but the function
149 recv_recovery_from_checkpoint_finish should be called later to complete
150 the recovery and free the resources used in it.
151 @param type in: LOG_CHECKPOINT or LOG_ARCHIVE
152 @param lim  in: recover up to this log sequence number if possible
153 @param min  in: minimum flushed log sequence number from data files
154 @param max  in: maximum flushed log sequence number from data files
155 @return error code or DB_SUCCESS */
156 # define recv_recovery_from_checkpoint_start(type,lim,min,max)    \
157   recv_recovery_from_checkpoint_start_func(type,lim,min,max)
与log_t结构体相对应,恢复阶段也有一个结构体,叫做recv_sys_t,这个结构体在recv_recovery_from_checkpoint_start函数中通过recv_sys_create和recv_sys_init两个函数初始化。recv_sys_t中同样有几个和lsn相关的字段,这里做下介绍。
recv_sys->limit_lsn
恢复应该执行到的最大的LSN值,这里赋值为LSN_MAX(uint64_t的最大值)
recv_sys->parse_start_lsn
恢复解析日志阶段所使用的最起始的LSN值,这里等于最后一次执行checkpoint对应的LSN值
recv_sys->scanned_lsn
当前扫描到的LSN值
recv_sys->recovered_lsn
当前恢复到的LSN值,此值小于等于recv_sys->scanned_lsn
parse_start_lsn值是recovery的起点,其通过recv_find_max_checkpoint函数获取,读取的就是log文件LOG_CHECKPOINT_1/LOG_CHECKPOINT_2字段的值。
 
在获取start_lsn后,recv_recovery_from_checkpoint_start函数调用recv_group_scan_log_recs函数读取及解析log records。
我们重点看下recv_group_scan_log_recs函数:
2908 /*******************************************************//**
2909 Scans log from a buffer and stores new log data to the parsing buffer. Parses
2910 and hashes the log records if new data found. */
2911 static
2912 void
2913 recv_group_scan_log_recs(
2914 /*=====================*/
2915   log_group_t*  group,    /*!< in: log group */
2916   lsn_t*    contiguous_lsn, /*!< in/out: it is known that all log
2917           groups contain contiguous log data up
2918           to this lsn */
2919   lsn_t*    group_scanned_lsn)/*!< out: scanning succeeded up to
2920           this lsn */


2930   while (!finished) {
2931     end_lsn = start_lsn + RECV_SCAN_SIZE;
2932
2933     log_group_read_log_seg(LOG_RECOVER, log_sys->buf,
2934                group, start_lsn, end_lsn);
2935
2936     finished = recv_scan_log_recs(
2937       (buf_pool_get_n_pages()
2938       - (recv_n_pool_free_frames * srv_buf_pool_instances))
2939       * UNIV_PAGE_SIZE,
2940       TRUE, log_sys->buf, RECV_SCAN_SIZE,
2941       start_lsn, contiguous_lsn, group_scanned_lsn);
2942     start_lsn = end_lsn;
2943   }
此函数内部是一个while循环。log_group_read_log_seg函数首先将log record读取到一个内存缓冲区中(这里是log_sys->buf),接着调用recv_scan_log_recs函数用来解析这些log record。解析过程会计算log block的checksum以及block no和lsn是否对应。解析过程完成后,解析结果会存入recv_sys->addr_hash维护的hash表中。这个hash表的key是通过space id和page number计算得到,value是一组应用到指定页面的经过解析后的log record,这里不再展开。
 
上述步骤完成后,recv_apply_hashed_log_recs函数可能会在recv_group_scan_log_recs或recv_recovery_from_checkpoint_start函数中调用,此函数将addr_hash中的log应用到特定的page上。此函数会调用recv_recover_page函数做真正的page recovery操作,此时会判断页面的lsn要比log record的lsn小。
105 /** Wrapper for recv_recover_page_func().
106 Applies the hashed log records to the page, if the page lsn is less than the
107 lsn of a log record. This can be called when a buffer page has just been
108 read in, or also for a page already in the buffer pool.
109 @param jri  in: TRUE if just read in (the i/o handler calls this for
110 a freshly read page)
111 @param block  in/out: the buffer block
112 */
113 # define recv_recover_page(jri, block)  recv_recover_page_func(jri, block)
如上就是整个页面的恢复流程。
 
附一个问题环节,后续会将redo log相关的问题记录在这里。
1. Q: Log_file, Log_block, Log_record的关系?
    A: Log_file由一组log block组成,每个log block都是固定大小的。log block中除了header\tailer以外的字节都是记录的log record
2. Q: 是不是每一次的Commit,产生的应该是一个Log_block ?
    A: 这个不一定的。写入log_block由mtr_commit确定,而不是事务提交确定。看log record大小,如果大小不需要跨log block,就会继续在当前的log block中写 。
3. Q: Log_record的结构又是怎么样的呢?
    A: 这个结构很多,也没有细研究,具体看后边登博图中的简要介绍吧;
4. Q: 每个Block应该有下一个Block的偏移吗,还是顺序即可,还是记录下一个的Block_number
    A: block都是固定大小的,顺序写的 
5. Q: 那如何知道这个Block是不是完整的,是不是依赖下一个Block呢?
    A: block开始有2个字节记录 此block中第一个mtr开始的位置,如果这个值是0,证明还是上一个block的同一个mtr。
6. Q: 一个事务是不是需要多个mtr_commit
    A: 是的。mtr的m == mini;
7. Q: 这些Log_block是不是在Commit的时候一起刷到当中?
    A: mtr_commit时会写入log buffer,具体什么时候写到log file就不一定了
8. Q: 那LSN是如何写的呢?
    A: lsn就是相当于在log file中的位置,那么在写入log buffer时就会确定这个lsn的大小了 。当前只有一个log buffer,在log buffer中的位置和在log file中的位置是一致的
9. Q: 那我Commit的时候做什么事情呢? 
    A: 可能写log 、也可能不写,由innodb_flush_log_at_trx_commit这个参数决定啊 
10. Q: 这两个值是干嘛用的: LOG_CHECKPOINT_1/LOG_CHECKPOINT_2   
      A: 这两个可以理解为log file头信息的一部分(占用文件头第二和第四个block),每次执行checkpoint都需要更新这两个字段,后续恢复时,每个页面对应lsn中比这个checkpoint值小的,认为是已经写入了,不需要再恢复 
 
文章最后,将网易杭研院何登成博士-登博博客上的一个log block的结构图放在这,再画图也不会比登博这张图画的更清晰了,版权属于登博。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL redo log及recover过程浅析 的相关文章

  • SQL视图View的总结和使用

    实际工作当中 数据交互查询返回结果 SQL你是没办法找其他的完美替代的 但有的时候还是会遇到一些很头痛的问题需要视图view来解决 比如以下场景 view日常使用场景 场景一 有的时候 多个表并表条件查询 尤其是好几张表那种一起查询的那种
  • JS 使用正则

    在JS中如何使用正则来校验字符串 1 使用RegExpObject test string 匹配则为true否则为false 声明一个正则对象 var a 0 9 需要注意的是 a不是字符串 而是一个对象 我们可以打印下a的构造函数 没错
  • ESP32-WROVER-E无法正常写入固件

    在之前用模块下载程序都是好的 然后突然就出现了无法下载的现象 打印了他的输出都是 rst 0x10 RTCWDT RTC RESET boot 0x13 SPI FAST FLASH BOOT invalid header 0xffffff
  • 【2023】华为OD机试真题Java-题目0219-查找充电设备组合

    非常典型的动态规划问题 package com company test import java util Arrays public class Main1 public static void main String args int
  • Matlab使用LSTM网络做classification和regression时XTrain的若干种数据结构-part I

    目前看来 Deep learning的两大用途是classification和regression 以LSTM为例 它的优势在于对时序数据 sequence data 强大的处理能力 简单来说 可以用作 1 sequence to labe
  • 浅谈C++

    重载原因 C 中的运算符重载是一种特性 允许程序员定义自定义类类型的运算符操作 通过运算符重载 可以对类对象执行类似于内置类型的操作 例如加法 减法 乘法等 运算符重载通过定义特定的成员函数或非成员函数来实现 成员函数的运算符重载为类的成员
  • 【通过粒子滤波进行地形辅助导航】用于地形辅助导航的粒子滤波器和 PCRB研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 粒子滤波 Particle Filter
  • linux搭建 sftp服务 && sftp自动上传脚本

    1 新建sftp用户组 sftp 用户家目录 groupadd sftp mkdir p sftpdata sftp 2 新建sftp用户 useradd d sftpdata sftp tester m g sftp s sbin nol
  • 安装 Hana Studio

    1 从sap 官网下载下来的安装包是 sar 类型的压缩包 2 需要用专门的解压工具 SAPCAR 3 运行sapcar 工具和安装包放到英文路径下 win r 输入cmd 输入CD SAPCAR保存路径 我的保存在 出现这种 没有打开相应
  • pandas之Series()菜鸟教程

    Pandas数据结构Series 基本概念及创建 一维数组 Serise import numpy as np import pandas as pd import time Series 数据结构 Series 是带有标签的一维数组 可以
  • CUDA安装详细教程

    一 CUDA下载 CUDA官网 二 CUDA具体安装步骤 1 检查电脑的NVIDIA版本 在cmd中输入nvidia smi 注意nvidia smi中的是驱动对应的cuda最高版本 只要此版本大于等于你安装的cuda即可 若命令nvidi
  • 机器学习笔试面试超详细总结(一)

    文章目录 1 判别模型和生成模型 2 最大概率分词 3 中文分词的基本方法 4 CRF 条件随机场 的特点 5 隐马尔可夫模型 HMM 时间复杂度及可以使用的数据集 6 在二分类问题中的评价方案 7 决策树特点 8 过拟合 9 异方差性 1

随机推荐

  • 关于gitlab的使用1——拉取代码

    1 快速上手 1 1注册 1 2登录 1 3选择 1 4选择所要拉取代码到idea的项目 1 5 选择索要拉取的模块 1 6选择clone按钮进行操作 1 7复制ssh或者http协议地址 1 8打开idea 1 9输入协议地址和保存路径
  • 关于Ajax跨域提交时session丢失的问题

    今天在工作中遇到了一个问题 就是当使用ajax和jsonp进行跨域时 每一服务器都会在cookie里set一个新的sessionId 会将原有的sessionId覆盖 也就是说客户端对于服务器来说始终处于未登录状态 我使用谷歌浏览器是没有问
  • R语言gg3D包绘制3D图形

    本次分享一个绘图还不错的包 gg3D 2018年1月公布 一 安装包 gg3D包目前 写该文章时 在R语言官方网站还不能找到并下载 但可以通过开源的托管平台gitHub下载 运行如下代码 install packages devtools
  • React Router中useRoutes()方法的使用

    运用场景 当我们需要路由权限控制点时候 对路由数组做一些权限的筛选过滤 这时需要把路由进行集中式管理 所谓的集中式路由配置就是用一个数组统一把所有的路由对应关系写好替换本来的Roues组件 便于管理路由 更加灵活 原来的路由写法 impor
  • STM32 基础系列教程 45 - FSMC_LCD_Touch

    前言 上一节我们完成了用 STM32F4的 FSMC接口来控制 TFTLCD的显示的操作 其实正点原子的探索者F4开发板带的屏幕支持触摸操作 笔者用的是4 3寸的电容触摸屏 本节我们继续实验 来完成基于STM32的触摸屏的实验 关于触摸屏的
  • Xshell的下载与安装

    引言 上一篇文章有介绍Windows子系统的安装与使用 安装Ubuntu桌面版确实可以直接使用Ubuntu子系统 但是Ubuntu桌面版的界面不是很好看 并且不能直接上传文件到服务器中 所以本篇章介绍SSH远程终端工具Xshell的下载与安
  • Springboot的application.properties或者application.yml环境的指定运行与配置

    Springboot的application properties或者application yml文件的配置 1 关于多个配置环境的指定运行 我们在主配置文件编写的时候 文件名可以是 application profile propert
  • 【k8s】ImagePullBackOff 错误处理

    文章目录 1 概述 2 问题复现 参考 1 概述 ImagePullBackOff错误比较简单 镜像下载失败 要么网络设置有问题 要么没有设置镜像源 另外一个比较隐蔽的问题是 当你在集群环境下 假设有3个节点 那么这三个节点都要设置镜像源
  • 物联网专业毕业设计题目大全

    文章目录 1 前言 2 选题分享 2 1 嵌入式方向 2 2 算法方向 2 3 移动通信方向 2 4 学长作品展示 3 选题技巧 3 1 如何避坑 重中之重 3 2 难度把控 3 3 题目名称 4 最后 1 前言 这是学长亲手整理的物联网相
  • k8s部署gitlab最新版并初始化和登录

    前提条件是已经部署了k8s环境 采用k8s部署gitlab作为devops的测试环境 更加简洁和方便 1 准备工作 1 1 创建nfs共享目录 在nfs服务器创建共享目录 部署的gitlib使用共享目录来进行持久化 这样不管在哪个节点运行g
  • 一个程序员的成长历程(持续更新)

    此处将是我学习编程的整个简单过程将持续记录只想在这里见证我一步步的成长 此时学习编程200天 2016 8 1 大一刚接触时的冲动和欣喜 认为语言种类积累学习越多我将走向成功 如今大一暑假 经过这一阶段对c语言与c 学习过后 喜欢上了算法
  • 使用windows自带的任务计划程序定时运行python程序(详细教程)

    最近写了一段微信定时发送消息的代码 但是这样需要一直将代码运行 现在运用windows自带的任务计划程序来实现代码自动运行 以达到定时发送消息的效果 将此记录下来方便下次使用时查找 1 打开搜索框搜索windows管理工具 并打开 2 在w
  • UML2面向对象分析与设计(第2版) 谭火彬 期末复习整理+部分答案【超实用】

    所用教材 谭火彬 编著 笔者纯手打整理 喜欢的话请点赞 关注我哦 UML相关的书就不能精简一点嘛 配套答案在公众号 书圈 内下载 也可以通过百度网盘链接 https pan baidu com s 1IPFlXBCVItuXrPZzY6qv
  • 程序员的自我修养--链接、装载与库笔记:目标文件里有什么

    编译器编译源代码后生成的文件叫做目标文件 目标文件从结构上讲 它是已经编译后的可执行文件格式 只是还没有经过链接的过程 其中可能有些符号或有些地址还没有被调整 其实它本身就是按照可执行文件格式存储的 只是跟真正的可执行文件在结构上稍有不同
  • 合并两数组(并排序)

    将两个数组num1和num2合并 升序排序 代码如下 import java util Arrays public class LangSuZu public int Hebing int num1 int num2 int num3 ne
  • 操作系统4小时速成:进程管理复习重点,进程,线程,处理机调度,进程同步,死锁

    操作系统4小时速成 进程管理复习重点 进程 线程 处理机调度 进程同步 死锁 2022找工作是学历 能力和运气的超强结合体 遇到寒冬 大厂不招人 可能很多算法学生都得去找开发 测开 测开的话 你就得学数据库 sql oracle 尤其sql
  • Altium Designer(五)光耦元件模型的创建

    软件 Altium Designer 16 往期博客 AD 一 AD的工程创建 AD 二 电阻 电容 模型的创建 AD 三 IC类元件模型创建 AD 四 排针类元件模型的创建 AD 五 光耦元件模型的创建 AD 六 已有元件库的调用 AD
  • CentOS8 MySQL 主主模式+keepalived高可用环境搭建非docker版

    概述 采用了MySQL KeepAlived实现MySQL高可用 旨在当主机发生宕机等异常情况时 使用备机的MySQL服务 以此保证系统服务的高可用 这套环境的搭建过程中 需要注意的事项如下 1 MySQL是否数据同步 在大批量数据写入的情
  • TCP —— TCP的可靠传输

    一 TCP的可靠传输 二 序号 TCP首部的序号字段用来保证数据能有序提交给应用层 序号建立在传送的字节流上 而不建立在报文段之上 三 确认 四 重传 1
  • MySQL redo log及recover过程浅析

    MySQL redo log及recover过程浅析 写在前面 作者水平有限 欢迎不吝赐教 一切以最新源码为准 InnoDB redo log 首先介绍下Innodb redo log是什么 为什么需要记录redo log 以及redo l