当前位置:首页 > 文章列表 > 数据库 > MySQL > 【Mysql源码分析】基于行的复制实现之“主从复制”

【Mysql源码分析】基于行的复制实现之“主从复制”

来源:SegmentFault 2023-02-17 14:58:31 0浏览 收藏

本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《【Mysql源码分析】基于行的复制实现之“主从复制”》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~

  在开始交接之前,我们带着几个问题切入:

  1. 如何查看binlog和relaylog事件?
  2. relaylog是如何写入?
  3. binlog是如何同步?
  4. binlog格式如何解析?

1.如何查看binlog和relaylog

   在mysql中可以通过如下命令可以查看都有哪些binlog日志,如图1-1:

mysql> show binary logs; 

11.png

图1-1 查看binlog日志
  • Log_name 日志文件名称。
  • File_size 文件大小。
  • Encrypted 是否加密“No”代表未加密。

  在查看binlog时、主有自己的binlog、从也有自己的binlog。

  如果要查看最新的binlog,可以通过如下命令查看,如图1-2

mysql> show master status; 

12.png

图1-2 查看最新binlog

  通过如下命令可以查看当前binlog事件,如图1-3:

mysql> show relaylog events;

14.png

图1-4 查看relaylog事件

relaylog事件的参数含义和binlog的一致,可参考binlog。

  除了查看relaylog事件外,还可以查看relaylog参数,如图1-5所示。通过如下命令可以查看:

mysql> show variables like '%relay%';

15.png

图1-5 relaylog参数
  • max_relay_log_size:标记relay log 允许的最大值,如果该值为0,则默认值为max_binlog_size(1G);如果不为0,则max_relay_log_size则为最大的relay_log文件大小;
  • relay_log:定义relay_log的位置和名称,如果值为空,则默认位置在数据文件的目录,文件名为host_name-relay-bin.nnnnnn;
  • relay_log_index:同relay_log,定义relay_log的位置和名称;
  • relay_log_info_file:设置relay-log.info的位置和名称(relay-log.info记录MASTER的binary_log的恢复位置和relay_log的位置)
  • relay_log_purge:是否自动清空不再需要中继日志时。默认值为1(启用)。
  • relay_log_recovery:当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。默认情况下该功能是关闭的,将relay_log_recovery的值设置为 1时,可在slave从库上开启该功能,建议开启。
  • relay_log_space_limit:防止中继日志写满磁盘,这里设置中继日志最大限额。但此设置存在主库崩溃,从库中继日志不全的情况,不到万不得已,不推荐使用;
  • sync_relay_log:这个参数和sync_binlog是一样的,当设置为1时,slave的I/O线程每次接收到master发送过来的binlog日志都要写入系统缓冲区,然后刷入relay log中继日志里,这样是最安全的,因为在崩溃的时候,你最多会丢失一个事务,但会造成磁盘的大量I/O。当设置为0时,并不是马上就刷入中继日志里,而是由操作系统决定何时来写入,虽然安全性降低了,但减少了大量的磁盘I/O操作。这个值默认是0,可动态修改,建议采用默认值。
  • sync_relay_log_info:这个参数和sync_relay_log参数一样,当设置为1时,slave的I/O线程每次接收到master发送过来的binlog日志都要写入系统缓冲区,然后刷入relay-log.info里,这样是最安全的,因为在崩溃的时候,你最多会丢失一个事务,但会造成磁盘的大量I/O。当设置为0时,并不是马上就刷入relay-log.info里,而是由操作系统决定何时来写入,虽然安全性降低了,但减少了大量的磁盘I/O操作。这个值默认是0,可动态修改,建议采用默认值。

2.slave_relay_log_info与slave_master_info

  slave_relay_log_info和slave_master_info分别为relaylog-info和master-info信息。relaylog-info和master-info信息可以使用FILE或这TABLE存储。relaylog-info有三种形式,分为为FILE、TABLE、DUMMY。

21.png

图2-1 查看relaylog-info和master-info

  通过relay_log_info_repository和master_info_repository可以得知relaylog-info和master-info是用什么形式存储,如图2-1所示。

3.binlog文件格式解析

  想了解binlog的格式,可以通过十六进制的形式去查看,如图3-1所示。

31.png

图3-1 binlog十六进制格式

  查看十六进制格式可以使用hexdump命令,命令格式如下:

#hexdump -C  mysql-bin.000024 

  通过hexdump得到如下内容:

00000000  fe 62 69 6e 41 93 92 5f  0f 0a 00 00 00 79 00 00  |.binA.._.....y..|
00000010  00 7d 00 00 00 01 00 04  00 38 2e 30 2e 32 30 2d  |.}.......8.0.20-|
00000020  64 65 62 75 67 00 00 00  00 00 00 00 00 00 00 00  |debug...........|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  00 00 00 00 00 00 00 00  00 00 00 41 93 92 5f 13  |...........A.._.|
00000050  00 0d 00 08 00 00 00 00  04 00 04 00 00 00 61 00  |..............a.|
00000060  04 1a 08 00 00 00 08 08  08 02 00 00 00 0a 0a 0a  |................|
00000070  2a 2a 00 12 34 00 0a 28  01 3a 50 74 ce 41 93 92  |**..4..(.:Pt.A..|
00000080  5f 23 0a 00 00 00 1f 00  00 00 9c 00 00 00 80 00  |_#..............|
00000090  00 00 00 00 00 00 00 00  56 4b 92 11              |........VK..|

  也可以mysqlbinlog命令得到binlog信息,如图3-2。命令格式如下:

#mysqlbinlog   --base64-output='decode-rows' mysql-bin.000024 

32.png

图3-2 binlog信息

  可以通过一张图解析下图3-2中内容,从十六进制格式中解析一下binlog格式,如图3-3所示。
image

图3-3 binlog格式解析

  可以关注下如下内容和图3-3还有图3-2中关系:

fe 62 69 6e 对应魔术头 0xFE 'bin'

41 93 92 5f timestamp时间戳1603441473,对应时间"2020/10/23 16:24:33"
0f          event_type对应十进制15对应FORMAT_DESCRIPTION_EVENT
0a 00 00 00 server_id 0x0a对应十进制10
79 00 00 00 event_size 对应十进制121
7d 00 00 00 log_pos 对应十进制125
01 00       flags 状态

04 00       binlog version对应版本4
38 2e 30 2e 32 30 2d 64 65 62 75 67 00 00 00  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  00 00 00 
mysql-server version 对应版本号8.0.20-debug
41 93 92 5f create-timestamp 创建时间戳,对应1603441473,对应时间2020/10/23 16:24:33 
13          Event-header-length对应19
00 0d 00 08 00 00 00 00  04 00 04 00 00 00 61 00  
04 1a 08 00 00 00 08 08  08 02 00 00 00 0a 0a 0a  
2a 2a 00 12 34 00 0a 28  01   Event-type-header-length 对应41个event类型
3a 50 74 ce  CRC32 对应 0xce74503a  

41 93 92 5f  timestamp对应时间2020/10/23 16:24:33
23           event_type对应35对应PREVIOUS_GTIDS_LOG_EVENT
0a 00 00 00  server_id对应服务ID为10
1f 00 00 00  event_size对应大小31
9c 00 00 00  log_pos对应156
80 00        flags 状态

00 00 00 00 00 00 00 00  Next pos

56 4b 92 11 CRC 0x11924b56      

  Event-type-header-length对41为什么是41?可以看一下源码,对应libbinlogevents/include/binlog_event.h

enum Log_event_type {
  /**
    Every time you add a type, you have to
    - Assign it a number explicitly. Otherwise it will cause trouble
      if a event type before is deprecated and removed directly from
      the enum.
    - Fix Format_description_event::Format_description_event().
  */
  UNKNOWN_EVENT = 0,
  /*
    自MySQL8.0.2以来已弃用。它只是一个占位符,不应该在其他地方使用。
  */
  START_EVENT_V3 = 1,  //起始事件是二进制日志版本1至3的二进制日志的第一个事件。
  QUERY_EVENT = 2,     //查询事件用于向binlog发送文本查询。
  STOP_EVENT = 3,      //停止事件
  ROTATE_EVENT = 4,    //将Rotate事件作为最后一个事件添加到binlog中,以告诉读者接下来要请求的binlog。
  INTVAR_EVENT = 5,   //基于整数的会话变量


  SLAVE_EVENT = 7,   //从事件

  APPEND_BLOCK_EVENT = 9,  //将块数据追加到文件
  DELETE_FILE_EVENT = 11,  //删除文件事件

  RAND_EVENT = 13,         //RAND() 函数的 内部状态。
  USER_VAR_EVENT = 14,     //用户变量
  FORMAT_DESCRIPTION_EVENT = 15, //格式描述事件是binlog版本4的binlog的第一个事件。它描述了其他事件的布局方式。
  XID_EVENT = 16,          //2PC的事务处理ID,在需要时写入 COMMIT。
  BEGIN_LOAD_QUERY_EVENT = 17,  //截断文件并设置块数据
  EXECUTE_LOAD_QUERY_EVENT = 18,

  TABLE_MAP_EVENT = 19,        //基于行的复制中 使用的第一个事件 声明如何定义将要更改的表。

  /**
    V1事件号从5.1.16一直使用到mysql-5.6。 
  */
  WRITE_ROWS_EVENT_V1 = 23,
  UPDATE_ROWS_EVENT_V1 = 24,
  DELETE_ROWS_EVENT_V1 = 25,

  /**
    主发生了不寻常的事
   */
  INCIDENT_EVENT = 26,

  /**
    主机在空闲时间发送的心跳事件确保主机联机状态为从机
  */
  HEARTBEAT_LOG_EVENT = 27,

  /**
    在某些情况下,有必要把不可忽视的东西送过去数据到从机:
    在这种情况下,从机可以处理的数据是用于处理它的代码,
    但如果不是,则可以忽略它辨识。
  */    
  IGNORABLE_LOG_EVENT = 28,
  ROWS_QUERY_LOG_EVENT = 29, //ROWS_EVENT的查询

  /** 行事件的版本2 */
  WRITE_ROWS_EVENT = 30,
  UPDATE_ROWS_EVENT = 31,
  DELETE_ROWS_EVENT = 32,

  GTID_LOG_EVENT = 33,    //gtid 
  ANONYMOUS_GTID_LOG_EVENT = 34, //匿名gtid

  PREVIOUS_GTIDS_LOG_EVENT = 35, //上一个gtid

  TRANSACTION_CONTEXT_EVENT = 36, //事务上下文事件

  VIEW_CHANGE_EVENT = 37,

  /* 准备了类似于Xid的XA事务终端事件 */
  XA_PREPARE_LOG_EVENT = 38,

  /**
    UPDATE_ROWS_事件的扩展,允许根据到 binlog_row_value_options配置中。
  */
  PARTIAL_UPDATE_ROWS_EVENT = 39,

  TRANSACTION_PAYLOAD_EVENT = 40,


  ENUM_END_EVENT /* 终点标记 */
};

  在mysql5中只有39个event-type。

  基于行复制实现的的事件为TABLE_MAP_EVENT、ROWS_EVENT、ROWS_QUERY_EVENT三大类。
可以看官方: https://dev.mysql.com/doc/internals/en/row-based-replication.html

4.Mysql主从同步源码解析

41.jpg

图4-1 主从同步

  在主从同步过程中、我们可以把同步过程分为10个阶段,如图4-1。

  经过对之前的《【Mysql源码分析】基于行的复制实现之“主从关系建立”》的学习,得知dump线程会接收到COM_BINLOG_DUMP指令后触发。然而从服务器请求二进制日志流中分为几个参数:

1字节              [12] COM_BINLOG_DUMP
4字节              binlog-pos  binlog对应到位置
2字节              flags       状态
4字节              server-id   服务ID
string[EOF]    binlog-filename 文件名称   

  当接收到COM_BINLOG_DUMP指令后会触发调用com_binlog_dump方法,com_binlog_dump方法中会调用mysql_binlog_send函数用于发送binlog,如图图4-2所示。

42.png

图4-2 发送binlog

void mysql_binlog_send(THD *thd, char *log_ident, my_off_t pos,
                       Gtid_set *slave_gtid_executed, uint32 flags) {
  //log_ident发送binlog名称
  //pos 当前行号,后续会作为开始行号
  Binlog_sender sender(thd, log_ident, pos, slave_gtid_executed, flags);

  sender.run();
}

  在调用mysql_binlog_send方法后,会调用Binlog_sender::send_events方法发送事件,在发送事件时会调用Binlog_sender::check_event_type方法对事件进行检测,如图4-3。

43.png

图4-3 事件检测方法

  用Binlog_sender::check_event_type检测方法原型如下:

bool Binlog_sender::check_event_type(Log_event_type type, const char *log_file,
                                     my_off_t log_pos) {
  if (type == binary_log::ANONYMOUS_GTID_LOG_EVENT) {
    /*
     通常情况下,当自动位置被启用,因为主设备和从设备
     如果主机未使用GTID_MODE=ON,则拒绝连接。
     但是,如果主机在连接后更改了GTID_模式初始化,
     或者如果从属请求复制出现在最后一个匿名事件之前
     的事务,则这可能发生。然后生成此错误以阻止发送
     到从属服务器的匿名事务。
    */
    if (m_using_gtid_protocol) { //判断是否使用gtid
      DBUG_EXECUTE_IF("skip_sender_anon_autoposition_error",
                      { return false; };);
      char buf[MYSQL_ERRMSG_SIZE];
      snprintf(buf, MYSQL_ERRMSG_SIZE,
               ER_THD(m_thd, ER_CANT_REPLICATE_ANONYMOUS_WITH_AUTO_POSITION),
               log_file, log_pos);
      set_fatal_error(buf);
      return true;
    }
    /*
      通常情况下,当master有GTID_MODE=ON,因为当GTID_MODE=ON。但是,如果主控形状发生更改,则可能会发生这种情况当从属服务器尚未复制所有匿名交互。
    */
    else if (get_gtid_mode_from_copy(GTID_MODE_LOCK_NONE) == GTID_MODE_ON) {
      char buf[MYSQL_ERRMSG_SIZE];
      snprintf(buf, MYSQL_ERRMSG_SIZE,
               ER_THD(m_thd, ER_CANT_REPLICATE_ANONYMOUS_WITH_GTID_MODE_ON),
               log_file, log_pos);
      set_fatal_error(buf);
      return true;
    }
  } else if (type == binary_log::GTID_LOG_EVENT) {
    /*
      通常情况下,当主服务器有GTID_MODE=OFF,因为当
      GTID_MODE=OFF。但是,如果主控形状发生更改,则
      可能会发生这种情况当从机尚未复制所有GTID时,GTID_MODE关闭交互。
    */
    if (get_gtid_mode_from_copy(GTID_MODE_LOCK_NONE) == GTID_MODE_OFF) {
      char buf[MYSQL_ERRMSG_SIZE];
      snprintf(buf, MYSQL_ERRMSG_SIZE,
               ER_THD(m_thd, ER_CANT_REPLICATE_GTID_WITH_GTID_MODE_OFF),
               log_file, log_pos);
      set_fatal_error(buf);
      return true;
    }
  }
  return false;
}

44.png

图4-4 Log_event::write

  在写入binlog时会调用Log_event::write进行写入,如图4-4。Log_event::write在log_event.h头文件中。

  写入master-info信息调度如下:

(lldb) bt
* thread #36, stop reason = breakpoint 8.1
  * frame #0: 0x0000000109a10c80 mysqld`Master_info::write_info(this=0x00007fe416209200, to=0x00007fe418204230) at rpl_mi.cc:666
    frame #1: 0x0000000109a0e9ba mysqld`Master_info::flush_info(this=0x00007fe416209200, force=false) at rpl_mi.cc:380
    frame #2: 0x0000000109a987eb mysqld`flush_master_info(mi=0x00007fe416209200, force=false, need_lock=false, do_flush_relay_log=false) at rpl_slave.cc:1424
    frame #3: 0x0000000109ab4565 mysqld`queue_event(mi=0x00007fe416209200, buf="\a�\x8e_\"\n", event_len=77, do_flush_mi=true) at rpl_slave.cc:7956
    frame #4: 0x0000000109a9e063 mysqld`::handle_slave_io(arg=0x00007fe416209200) at rpl_slave.cc:5462
    frame #5: 0x000000010ac5a6c5 mysqld`pfs_spawn_thread(arg=0x00007fe4175b28b0) at pfs.cc:2854
    frame #6: 0x00007fff7e063305 libsystem_pthread.dylib`_pthread_body + 126
    frame #7: 0x00007fff7e06626f libsystem_pthread.dylib`_pthread_start + 70
    frame #8: 0x00007fff7e062415 libsystem_pthread.dylib`thread_start + 13

  写入Relay-log-info信息调度如下:

(lldb) bt
* thread #41, stop reason = breakpoint 2.1
  * frame #0: 0x000000010c36f990 mysqld`Relay_log_info::write_info(this=0x00007f8a53de3400, to=0x00007f8a5512af50) at rpl_rli.cc:2200
    frame #1: 0x000000010c3677e1 mysqld`Relay_log_info::flush_info(this=0x00007f8a53de3400, force=true) at rpl_rli.cc:1905
    frame #2: 0x000000010c371fe8 mysqld`Relay_log_info::commit_positions(this=0x00007f8a53de3400) at rpl_rli.cc:2730
    frame #3: 0x000000010a4b72eb mysqld`Relay_log_info::pre_commit(this=0x00007f8a53de3400) at rpl_rli.h:1986
    frame #4: 0x000000010a4b6655 mysqld`ha_commit_trans(thd=0x00007f8a5605fa00, all=true, ignore_global_read_lock=false) at handler.cc:1656
    frame #5: 0x000000010aefeab4 mysqld`trans_commit(thd=0x00007f8a5605fa00, ignore_global_read_lock=false) at transaction.cc:241
    frame #6: 0x000000010ab202d3 mysqld`mysql_create_db(thd=0x00007f8a5605fa00, db="t136", create_info=0x000070000d37a898) at sql_db.cc:405
    frame #7: 0x000000010ac6f026 mysqld`mysql_execute_command(thd=0x00007f8a5605fa00, first_level=true) at sql_parse.cc:3660
    frame #8: 0x000000010ac676ad mysqld`mysql_parse(thd=0x00007f8a5605fa00, parser_state=0x000070000d37e028) at sql_parse.cc:5306
    frame #9: 0x000000010c24dc6c mysqld`Query_log_event::do_apply_event(this=0x00007f8a520d0620, rli=0x00007f8a53de3400, query_arg="create database t136", q_len_arg=20) at log_event.cc:4804
    frame #10: 0x000000010c24af13 mysqld`Query_log_event::do_apply_event(this=0x00007f8a520d0620, rli=0x00007f8a53de3400) at log_event.cc:4415
    frame #11: 0x000000010c2458fe mysqld`Log_event::apply_event(this=0x00007f8a520d0620, rli=0x00007f8a53de3400) at log_event.cc:3241
    frame #12: 0x000000010c4047e7 mysqld`apply_event_and_update_pos(ptr_ev=0x000070000d37f860, thd=0x00007f8a5605fa00, rli=0x00007f8a53de3400) at rpl_slave.cc:4350
    frame #13: 0x000000010c3f2032 mysqld`exec_relay_log_event(thd=0x00007f8a5605fa00, rli=0x00007f8a53de3400, applier_reader=0x000070000d3803d8, in=0x00007f8a520d0620) at rpl_slave.cc:4867
    frame #14: 0x000000010c3db543 mysqld`::handle_slave_sql(arg=0x00007f8a52b43200) at rpl_slave.cc:7022
    frame #15: 0x000000010d5936c5 mysqld`pfs_spawn_thread(arg=0x00007f8a554bcbf0) at pfs.cc:2854
    frame #16: 0x00007fff7e063305 libsystem_pthread.dylib`_pthread_body + 126
    frame #17: 0x00007fff7e06626f libsystem_pthread.dylib`_pthread_start + 70
    frame #18: 0x00007fff7e062415 libsystem_pthread.dylib`thread_start + 13

Master断点

#发送binlog
(lldb)b mysql_binlog_send

#发送binlog包
(lldb)b Binlog_sender::send_packet

#循环事件
(lldb)b Binlog_sender::run

#发送binlog
(lldb)b Binlog_sender::send_binlog

#发送心跳包事件
(lldb)b Binlog_sender::send_heartbeat_event

Slave 断点

#读取头文件事件
b Binlog_event_data_istream::read_event_header

#填充时间数据
b Binlog_event_data_istream::fill_event_data

#读取下一个事件
b Rpl_applier_reader::read_next_event

#slave sal处理
b handle_slave_sql

#写入relay-log-info
b Relay_log_info::write_info

#relay_log事件
b exec_relay_log_event  

#写入binlog或者relaylog断点
b handler::ha_write_row
b MYSQL_BIN_LOG::write_event
b binlog_cache_data::write_event

#写入relaylog之后操作
MYSQL_BIN_LOG::after_write_to_relay_log

#写入binlog
b MYSQL_BIN_LOG::write_buffer
b MYSQL_BIN_LOG::Binlog_ofile::write

总结

  1. 通过“show binary logs;” 可以查看binlog日志。
  2. 通过“show relaylog events;”可以查看relaylog事件。
  3. 在mysql8.0.20中有41个事件,mysql5.1中有39个。
  4. 基于行复制实现的的事件为TABLE_MAP_EVENT、ROWS_EVENT、ROWS_QUERY_EVENT三大类。
  5. relaylog-info和binlog-info可以使用file或者table形式记录。

参考献文

复制协议
https://dev.mysql.com/doc/internals/en/replication-protocol.html

事件含义
https://dev.mysql.com/doc/internals/en/event-meanings.html

基于行的二进制日志记录
[https://dev.mysql.com/doc/int...
](https://dev.mysql.com/doc/int...

文中关于mysql的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《【Mysql源码分析】基于行的复制实现之“主从复制”》文章吧,也可关注golang学习网公众号了解相关技术文章。

版本声明
本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
07-SpringBoot+MyBatis+Spring 技术整合实现商品模块的CRUD操作07-SpringBoot+MyBatis+Spring 技术整合实现商品模块的CRUD操作
上一篇
07-SpringBoot+MyBatis+Spring 技术整合实现商品模块的CRUD操作
Linux Mysql集群搭建
下一篇
Linux Mysql集群搭建
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 笔灵AI生成答辩PPT:高效制作学术与职场PPT的利器
    笔灵AI生成答辩PPT
    探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
    14次使用
  • 知网AIGC检测服务系统:精准识别学术文本中的AI生成内容
    知网AIGC检测服务系统
    知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
    22次使用
  • AIGC检测服务:AIbiye助力确保论文原创性
    AIGC检测-Aibiye
    AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
    30次使用
  • 易笔AI论文平台:快速生成高质量学术论文的利器
    易笔AI论文
    易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
    40次使用
  • 笔启AI论文写作平台:多类型论文生成与多语言支持
    笔启AI论文写作平台
    笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
    35次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码