MySQL的日志机制

news/2024/12/19 16:09:53/文章来源:https://www.cnblogs.com/wbstudy/p/18617442

MySQL日志机制随笔(redolog、binlog、undolog)

img

redolog相关

作用:保证数据库的恢复能力,数据库崩溃了,能使用redolog恢复数据

是什么?redolog是物理日志,记录的是哪个数据页哪个字段被哪个事务改变了,

速记:redolog是一种写前日志,先写redolog,等到数据库闲的时候再去写数据库文件

redolog是先写到内存中,然后再异步的写到磁盘

redolog关键参数

innodb_log_buffer_size:设置redo log buffer大小参数,默认16M ,最大值是4096M,最小值为1M。

写redolog内存空间的大小

innodb_log_group_home_dir:设置redo log文件存储位置参数,默认值为"./",即innodb数据文件存储位置,其中的 ib_logfile0 和 ib_logfile1 即为redo log文件。

show variables like '%innodb_log_group_home_dir%';

https://note.youdao.com/yws/public/resource/f030268c54f18d2116837f8f3ef045bf/xmlnote/3C06200D1CC0491BB5F5CBCBC6907803/129431

innodb_log_files_in_group:设置redo log文件的个数,命名方式如: ib_logfile0, iblogfile1... iblogfileN。默认2个,最大100个。

show variables like '%innodb_log_files_in_group%';

innodb_log_file_size:设置单个redo log文件大小,默认值为48M。最大值为512G,注意最大值指的是整个 redo log系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size)不能大于最大值512G。

show variables like '%innodb_log_file_size%';

总结一下:redolog的个数、大小、存储文件夹、内存buffer大小都能设置

redolog写入磁盘过程分析

redolog从一个文件开始写,写完一个文件写另一个文件,写到最后一个文件的末尾,就又回到第一个文件的开头循环写。

https://note.youdao.com/yws/public/resource/f030268c54f18d2116837f8f3ef045bf/xmlnote/997BB72845AA4B2788DCB7258821E360/128993

write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。

checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件里。

擦除完就说明已经更新到redolog文件中了

write pos 和 checkpoint 之间的部分就是空着的可写部分,可以用来记录新的操作。如果 write pos 追上checkpoint,表示redo log写满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,,也就是说这时候需要持久化一些记录了,把 checkpoint 推进一下。

innodb_flush_log_at_trx_commit:这个参数控制 redo log 的写入策略,它有三种可能取值:

  • 设置为0:日志每秒刷新到磁盘一次,事务提交时不刷新,性能最好,数据库宕机可能会丢失数据。
  • 设置为1(默认值):表示每次事务提交时都将 redo log 直接持久化到磁盘,数据最安全,不会因为数据库宕机丢失数据,但是效率稍微差一点,线上系统推荐这个设置。事务提交就持久化到磁盘
  • 设置为2:表示每次事务提交时都只是把 redo log 写到操作系统的缓存page cache里,这种情况如果数据库宕机是不会丢失数据的,但是操作系统如果宕机了,page cache里的数据还没来得及写入磁盘文件的话就会丢失数据。事务提交之后持久化到操作系统层,由操作系统决定多久写入磁盘

InnoDB 有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的日志,调用 操作系统函数 write 写到文件系统的 page cache,然后调用操作系统函数 fsync 持久化到磁盘文件。

https://note.youdao.com/yws/public/resource/f030268c54f18d2116837f8f3ef045bf/xmlnote/D5A4E61D80474D1D9C651FB0E2215EFB/128992

Redo Log 主要用于 崩溃恢复,保证已提交事务的持久性,crush-safe。

Binlog 主要用于 增量备份点时间恢复,能够让你恢复到某个特定的时间点或操作状态。

binlog日志

binlog二进制日志记录保存了所有执行过的修改操作语句,不保存查询操作。如果 MySQL 服务意外停止,可通过二进制日志文件排查,用户操作或表结构操作,从而来恢复数据库数据。

启动binlog记录功能,会影响服务器性能,但如果需要恢复数据或主从复制功能,则好处则大于对服务器的影响。

# 查看binlog相关参数
show variables like '%log_bin%';

https://note.youdao.com/yws/public/resource/f030268c54f18d2116837f8f3ef045bf/xmlnote/4F09294084C54A659E15E3645FE591E6/128995

log_bin:binlog日志是否打开状态
log_bin_basename:是binlog日志的基本文件名,后面会追加标识来表示每一个文件,binlog日志文件会滚动增加
log_bin_index:指定的是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录。
sql_log_bin:sql语句是否写入binlog文件,ON代表需要写入,OFF代表不需要写入。如果想在主库上执行一些操作,但不复制到slave库上,可以通过修改参数sql_log_bin来实现。比如说,模拟主从同步复制异常。

MySQL5.7 版本中,binlog默认是关闭的,8.0版本默认是打开的。上图中log_bin的值是OFF就代表binlog是关闭状态,打开binlog功能,需要修改配置文件my.ini(windows)或my.cnf(linux),然后重启数据库。

在配置文件中的[mysqld]部分增加如下配置:

# log-bin设置binlog的存放位置,可以是绝对路径,也可以是相对路径,这里写的相对路径,则binlog文件默认会放在data数据目录下
log-bin=mysql-binlog
# Server Id是数据库服务器id,随便写一个数都可以,这个id用来在mysql集群环境中标记唯一mysql服务器,集群环境中每台mysql服务器的id不能一样,不加启动会报错
server-id=1
# 其他配置
binlog_format = row # 日志文件格式,下面会详细解释
expire_logs_days = 15 # 执行自动删除距离当前15天以前的binlog日志文件的天数, 默认为0, 表示不自动删除

重启数据库后我们再去看data数据目录会多出两个文件,第一个就是binlog日志文件,第二个是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录。

https://note.youdao.com/yws/public/resource/f030268c54f18d2116837f8f3ef045bf/xmlnote/D0379C7E25EE443484A3BF893BB0A0C5/128994

binlog的日志格式

三种类型:

  • STATEMENT:基于SQL语句的复制,每一条会修改数据的sql都会记录到master机器的bin-log中,这种方式日志量小,节约IO开销,提高性能,但是对于一些执行过程中才能确定结果的函数,比如UUID()、SYSDATE()等函数如果随sql同步到slave机器去执行,则结果跟master机器执行的不一样。 这个直接记录语句

  • ROW:基于行的复制,日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改记录下每一行数据修改的细节,可以解决函数、存储过程等在slave机器的复制问题,但这种方式日志量较大,性能不如Statement。举个例子,假设update语句更新10行数据,Statement方式就记录这条update语句,Row方式会记录被修改的10行数据。这个是直接记录行数据

  • MIXED:混合模式复制,实际就是前两种模式的结合,在Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种,如果sql里有函数或一些在执行时才知道结果的情况,会选择Row,其它情况选择Statement,推荐使用这一种。两种混合,mysql来区分使用哪一种

binlog写入磁盘机制

binlog写入磁盘机制主要通过 sync_binlog 参数控制,默认值是 0。

  • 为0的时候,表示每次提交事务都只 write 到page cache系统级别的缓存,由系统自行判断什么时候执行 fsync 写入磁盘。虽然性能得到提升,但是机器宕机,page cache里面的 binlog 会丢失。
  • 也可以设置为1,表示每次提交事务都会执行 fsync 写入磁盘,这种方式最安全。
  • 还有一种折中方式,可以设置为N(N>1),表示每次提交事务都write 到page cache,但累积N个事务后才 fsync 写入磁盘,这种如果机器宕机会丢失N个事务的binlog。

发生以下任何事件时, binlog日志文件会重新生成:

  • 服务器启动或重新启动
  • 服务器刷新日志,执行命令flush logs
  • 日志文件大小达到 max_binlog_size 值,默认值为 1GB

mysqlbinlog日志开启:

打开 MySQL 的配置文件 my.cnf

[mysqld]
log-bin = /var/log/mysql/mysql-bin.log  # 设置二进制日志文件路径
server-id = 1  # 设置服务器 ID,通常是 1,但如果是主从架构,需要保证不同服务器的 server-id 不同
binlog-format = ROW  # 设置 binlog 格式为 ROW,其他选项有 STATEMENT 和 MIXED
expire-logs-days = 7  # 设置二进制日志的过期时间,单位为天,7天后会自动删除过期的日志文件

配置完成之后,重启mysql,使用命令查询binlog日志相关信息

注意mysql需要有文件的读写权限,否则会出问题

image-20241218150753315

删除binlog的日志

这个一般用的很少,一般是设置一个自动删除的时间,等MySQL自己删除

删除当前的binlog文件
reset master;
# 删除指定日志文件之前的所有日志文件,下面这个是删除6之前的所有日志文件,当前这个文件不删除
purge master logs to 'mysql-binlog.000006';
# 删除指定日期前的日志索引中binlog日志文件
purge master logs before '2023-01-21 14:00:00';

查看binlog 日志文件

发现docker中的MySQL没有自带mysqlbinlog命令,所以先从网上下载mysqlbinlog,复制进入docker容器

docker cp /mysqlbinlog bdfefc2333e0:/usr/bin/
docker exec -it bdfefc2333e0 /bin/bash
cd /usr/bin/
ls|grep mysql

image-20241219144059612

然后查看MySQL binlog

chmod 777 mysqlbinlog
bash-4.2# mysqlbinlog --no-defaults -v --base64-output=decode-rows /var/log/mysql/mysql-bin.000001;

image-20241219144600345

如何利用binlog恢复指定时间点或者指定position的数据

image-20241219145455274

暂时有的日志如上

# 先执行刷新日志的命令生成一个新的binlog文件mysql-binlog.000003,后面我们的修改操作日志都会记录在最新的这个文件里
flush logs;
# 找一个测试的表,新增两条数据# 假设现在误操作执行了一条删除语句把刚新增的两条数据删掉了

插入后:

image-20241219145700205

删除后:

image-20241219145813897

查看binlog:

mysqlbinlog --no-defaults -v --base64-output=decode-rows /var/log/mysql/mysql-bin.000003;
# at 219
#241219  6:59:18 server id 1  end_log_pos 294 CRC32 0xdc84e9a2 	Query	thread_id=2	exec_time=0	error_code=0
SET TIMESTAMP=1734591558/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=45,@@session.collation_connection=45,@@session.collation_server=192/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 294
#241219  6:59:18 server id 1  end_log_pos 351 CRC32 0xec76e56e 	Table_map: `testsql`.`account` mapped to number 110
# at 351
#241219  6:59:18 server id 1  end_log_pos 402 CRC32 0x930676a6 	Write_rows: table id 110 flags: STMT_END_F
### INSERT INTO `testsql`.`account`
### SET
###   @1=4
###   @2='test1'
###   @3=666
# at 402
#241219  6:59:18 server id 1  end_log_pos 433 CRC32 0xf7d3725a 	Xid = 18
COMMIT/*!*/;
# at 433
#241219  6:59:36 server id 1  end_log_pos 498 CRC32 0x6357212e 	Anonymous_GTID	last_committed=1	sequence_number=2
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 498
#241219  6:59:36 server id 1  end_log_pos 573 CRC32 0x7e44e1ea 	Query	thread_id=2	exec_time=0	error_code=0
SET TIMESTAMP=1734591576/*!*/;
BEGIN
/*!*/;
# at 573
#241219  6:59:36 server id 1  end_log_pos 630 CRC32 0xc5afdfc9 	Table_map: `testsql`.`account` mapped to number 110
# at 630
#241219  6:59:36 server id 1  end_log_pos 681 CRC32 0xc7a910e1 	Write_rows: table id 110 flags: STMT_END_F
### INSERT INTO `testsql`.`account`
### SET
###   @1=5
###   @2='test2'
###   @3=888
# at 681
#241219  6:59:36 server id 1  end_log_pos 712 CRC32 0x244a7b90 	Xid = 21
COMMIT/*!*/;
# at 712
#241219  7:00:05 server id 1  end_log_pos 777 CRC32 0x97391901 	Anonymous_GTID	last_committed=2	sequence_number=3
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 777
#241219  7:00:05 server id 1  end_log_pos 852 CRC32 0xdadcc029 	Query	thread_id=2	exec_time=0	error_code=0
SET TIMESTAMP=1734591605/*!*/;
BEGIN
/*!*/;
# at 852
#241219  7:00:05 server id 1  end_log_pos 909 CRC32 0x7730273d 	Table_map: `testsql`.`account` mapped to number 110
# at 909
#241219  7:00:05 server id 1  end_log_pos 960 CRC32 0xe52369c8 	Delete_rows: table id 110 flags: STMT_END_F
### DELETE FROM `testsql`.`account`
### WHERE
###   @1=4
###   @2='test1'
###   @3=666
# at 960
#241219  7:00:05 server id 1  end_log_pos 991 CRC32 0x1000d14c 	Xid = 24
COMMIT/*!*/;
# at 991
#241219  7:00:05 server id 1  end_log_pos 1056 CRC32 0x263cb90a 	Anonymous_GTID	last_committed=3	sequence_number=4
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 1056
#241219  7:00:05 server id 1  end_log_pos 1131 CRC32 0x1cfc942c 	Query	thread_id=2	exec_time=0	error_code=0
SET TIMESTAMP=1734591605/*!*/;
BEGIN
/*!*/;
# at 1131
#241219  7:00:05 server id 1  end_log_pos 1188 CRC32 0xa2760126 	Table_map: `testsql`.`account` mapped to number 110
# at 1188
#241219  7:00:05 server id 1  end_log_pos 1239 CRC32 0x3c28778c 	Delete_rows: table id 110 flags: STMT_END_F
### DELETE FROM `testsql`.`account`
### WHERE
###   @1=5
###   @2='test2'
###   @3=888
# at 1239
#241219  7:00:05 server id 1  end_log_pos 1270 CRC32 0xc2eb5012 	Xid = 25
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

找到两条插入数据的sql,每条sql的上下都有BEGIN和COMMIT,我们找到第一条sql BEGIN前面的文件位置标识 at 294(这是文件的位置标识),再找到第二条sql COMMIT后面的文件位置标识 at 852

我们可以根据文件位置标识来恢复数据,执行如下sql:

mysqlbinlog  --no-defaults --start-position=294 --stop-position=852 --database=testsql /var/log/mysql/mysql-bin.000003 | mysql -uroot -p密码 -v testsql

image-20241219150555774

image-20241219150610736

数据恢复成功

另外binlog也可以根据时间戳去进行数据的恢复:

# 补充一个根据时间来恢复数据的命令,我们找到第一条sql BEGIN前面的时间戳标记 SET TIMESTAMP=1674833544,再找到第二条sql COMMIT后面的时间戳标记 SET TIMESTAMP=1674833663,转成datetime格式
mysqlbinlog  --no-defaults --start-datetime="2023-1-27 23:32:24" --stop-datetime="2023-1-27 23:34:23" --database=test D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000009 | mysql -uroot -p密码 -v 数据库名称

注意:如果要恢复大量数据,比如程序员经常说的删库跑路的话题,假设我们把数据库所有数据都删除了要怎么恢复了,如果数据库之前没有备份,所有的binlog日志都在的话,就从binlog第一个文件开始逐个恢复每个binlog文件里的数据,这种一般不太可能,因为binlog日志比较大,早期的binlog文件会定期删除的,所以一般不可能用binlog文件恢复整个数据库的。

一般我们推荐的是每天(在凌晨后)需要做一次全量数据库备份,那么恢复数据库可以用最近的一次全量备份再加上备份时间点之后的binlog来恢复数据。

备份数据库一般可以用mysqldump 命令工具

mysqldump -u root 数据库名>备份文件名;   #备份整个数据库
mysqldump -u root 数据库名 表名字>备份文件名;  #备份整个表
mysql -u root test < 备份文件名 #恢复整个数据库,test为数据库名称,需要自己先建一个数据库test

为什么会有redo log和binlog两份日志呢?

因为最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以InnoDB 使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力。

有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。

redolog主要用于崩溃恢复;属于引擎层

binlog主要用于主从同步,指定时间点(位置)的恢复;属于server层

undolog

是什么?数据行历史数据的记录,主要是历史的行数据+事务id+回滚指针

用来做什么?

  1. 事务的回滚
  2. undo日志版本链+一致性视图readView去实现MVCC,决定当前查询可见哪些数据,不可见哪些数据

InnoDB对undo log文件的管理采用段的方式,也就是回滚段(rollback segment) 。每个回滚段记录了 1024 个 undo log segment ,每个事务只会使用一个undo log segment。

在MySQL5.5的时候,只有一个回滚段,那么最大同时支持的事务数量为1024个。在MySQL 5.6开始,InnoDB支持最大128个回滚段,故其支持同时在线的事务限制提高到了 128*1024 。

innodb_undo_directory:设置undo log文件所在的路径。该参数的默认值为"./",即innodb数据文件存储位置,目录下ibdata1文件就是undo log存储的位置。
innodb_undo_logs: 设置undo log文件内部回滚段的个数,默认值为128。
innodb_undo_tablespaces: 设置undo log文件的数量,这样回滚段可以较为平均地分布在多个文件中。设置该参数后,会在路径innodb_undo_directory看到undo为前缀的文件。

undolog什么时候删除?

新增类型的,在事务提交之后就可以清除掉了。

修改类型的,事务提交之后不能立即清除掉,这些日志会用于mvcc。只有当没有事务用到该版本信息时才可以清除。

为什么Mysql不能直接更新磁盘上的数据而设置这么一套复杂的机制来执行SQL了?

因为来一个请求就直接对磁盘文件进行随机读写,然后更新磁盘文件里的数据性能可能相当差。

因为磁盘随机读写的性能是非常差的,所以直接更新磁盘文件是不能让数据库抗住很高并发的。

Mysql这套机制看起来复杂,但它可以保证每个更新请求都是更新内存BufferPool,然后顺序写日志文件,同时还能保证各种异常情况下的数据一致性。

更新内存的性能是极高的,然后顺序写磁盘上的日志文件的性能也是非常高的,要远高于随机读写磁盘文件。

正是通过这套机制,才能让我们的MySQL数据库在较高配置的机器上每秒可以抗下几干甚至上万的读写请求。

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

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

相关文章

mysql的内部组件结构

大体来分,MySQL分为引擎层和server层 server层 连接器、查询缓存、分析器(解释器)、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。 连接…

工作中这样用MQ,很香!

前言 消息队列(MQ)是分布式系统中不可或缺的技术之一。 对很多小伙伴来说,刚接触MQ时,可能觉得它只是个“传话工具”,但用着用着,你会发现它简直是系统的“润滑剂”。 无论是解耦、削峰,还是异步任务处理,都离不开MQ的身影。 下面我结合实际场景,从简单到复杂,逐一拆…

点阵LED数显屏驱动芯片/数码管驱动控制器-VK1668 SOP24

产品品牌:永嘉微电/VINKA 产品型号:VK1668 封装形式:SOP24 概述 VK1668是一种带键盘扫描接口的数码管或点阵LED驱动控制专用芯片,内部集成有3线 串行接口、数据锁存器、LED 驱动、键盘扫描等电路。SEG脚接LED阳极,GRID脚接LED阴 极,可支持13SEGx4GRID、12SEGx5GRID、11SE…

Qt鼠标悬浮Hover消息不触发,只有鼠标单击才会触发消息?

1.Qt鼠标悬浮Hover消息不触发,只有鼠标单击才会触发消息? 下面的工具配置,想要鼠标悬浮在工具菜单上时,显示删除的图标;但是发现怎么都触发不了bool CBaseToolListWidget::eventFilter(QObject* ptr_object, QEvent* ptr_event){if (this == ptr_object){QEvent::Type eve…

vue-进行分组----将轮播图数据进行分组

效果展示第一步将数据进行分组处理 例如:数据是这样的处理方法一:进行两次for循环处理方法二:进行一次for循环

20222402 2024-2025-2 《网络与系统攻防技术》实验八实验报告

1.实验内容 1.1本周学习内容 Web 前端:负责开发用户所看到的内容。 (1)HTML (2)JavaScript(Js) (3)CSS (4)Web 前端框架 Web 后端:主要使用各种库,API,Web 服务等技术搭建后端应用体系,确保各种 Web服务接口之间的正确通信。比如处理前端用户发起的请求,各种业务逻辑的操作…

Shor’s Algorithm

本文延续RSA与ECC-ElGamal。 Shor算法(Shor’s Algorithm)几乎是最为出名的量子算法,原因就在于其可以在多项式的时间复杂度内完成大数的质因分解问题。也由此,基于质因分解难题的RSA算法受到了严重的量子威胁,而RSA算法正是在日常生活之中最为常用(如HTTPS协议、SSH协议…

翻页代码

using System.Collections;using System.Collections.Generic;using UnityEngine; public class NewBehaviourScript : MonoBehaviour{ //成员变量 //SerializeField凡是显示在Inspector(检查器) 中的属性都同时具有Serialize功能(序列化的意思是说再次读取Unity时序列化的变…

5款Win电脑好用的备忘录app推荐盘点

对于大多数的打工人来说,在使用Win电脑办公时,是需要随手记录一些琐事的,特别是工作上的事情,如果不随手记下来,很有可能会忘记。今天给大家介绍5款亲测好用的备忘录app,可以在电脑上使用,也可以实时同步到手机端,非常方便。 1、钉钉便签 作为一款办公软件,它不仅可以…

珠海盈致:智能制造赋能企业,解锁全新价值维度

智能制造是信息技术与制造技术的深度融合,经历了从数字化制造到“互联网+制造”,再到新一代智能制造的三个阶段。它是一个大系统,贯穿于产品、制造、服务的全生命周期,由智能产品、智能生产、智能服务三大功能系统,以及工业智联网和智能制造云两大支撑系统组成。 智能制造…

【路由交换】华为ENSP配置网口桥接

ENSP桥接物理网口,需要创建Cloud云对象,并在云对象中完成接口绑定配置绑定物理网口绑定UDP端口配置端口映射模拟器和cloud对象连接网络连接测试

基于QT+MQTT的实时视频监控

MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模式的轻量级通信协议,广泛应用于物联网领域。它允许设备通过极少的代码和有限的带宽实现实时可靠的消息服务。MQTT协议的核心在于其三部分组成的控制报文:固定报头、可变报头和有效载荷。mqtt中的一些名词解…