MySQL 8.0 新特性汇总
文章目录
-
- 前言
- 1. 运维管理
-
- 1.1 可持久化变量
- 1.2 管理员端口
- 1.3 资源组
- 1.4 数据库粒度只读
- 1.5 show processlist 实现方式
- 1.6 加速索引创建速度
- 1.7 控制连接的内存使用量
- 1.8 克隆插件
- 1.9 mysqldump 新增参数
- 1.10 慢日志增强
- 1.11 快速加列
- 1.12 InnoDB 隐藏主键
- 1.13 Redo 配置
- 1.14 undo 配置
- 1.15 事务调度 CATS
- 1.16 自增主键持久化
- 1.17 在线回收临时表空间
- 1.18 自适应参数
- 2. 开发相关
-
- 2.1 默认字符集
- 2.2 GROUP BY ASC/DESC 语法
- 2.3 公用表达式
- 2.4 窗口函数
- 2.5 check 约束
- 2.6 隐藏列
- 2.7 不可见索引
- 2.8 降序索引
- 2.9 函数索引
- 2.10 VALUES 语法
- 2.11 NOWAIT 和 SKIP LOCKED
- 2.12 分区表支持
- 3. 复制相关
-
- 3.1 Binlog 中包含元数据
- 3.2 Binlog 记录事务提交时间戳
- 3.3 Binlog 过期时间
- 3.4 ReplicaSet 复制方案
- 4. 安全相关
-
- 4.1 角色管理
- 4.2 caching_sha2_password
- 4.3 print_identified_with_as_hex
- 4.4 更细粒度的权限控制
- 4.5 生成随机密码
- 4.6 双重密码支持
- 4.7 密码错误锁定用户
- 4.8 账号备注信息
- 5. 优化器相关
-
- 5.1 hash join
- 5.2 直方图
- 6. 推荐升级流程
- 总结
前言
MySQL 5.7 在 2023 年 10 月 31 日起,已经终止软件生命周期了,意味着 MySQL 官方将不再提供对 MySQL 5.7 版本的技术支持和更新。8.0 版本成为官方长期支持版本,提供了很多新特性,本文将详细解读 MySQL 8.0 版本的新特性,为 MySQL 版本升级作参考和指导。
1. 运维管理
1.1 可持久化变量
MySQL 5.7 版本,使用 SET 命令修改参数后,需要再将参数写入到配置文件中,否则重启后又恢复默认配置。MySQL 8.0 提供SET PERSIST 语法可以将参数持久化到配置文件中,用户无需再对配置文件进行编辑,是一个对云厂商比较友好的特性。
# 持久化变量,同时修改变量内存值
SET PERSIST max_connections = 1000;# 只持久化修改,不修改内存中变量值,适用于修改只读参数
SET PERSIST_ONLY back_log = 100;# 清空 mysqld-auto.cnf 中的变量,持久化修改参数的原理是 MySQL 维护了一个配置文件,即 mysqld-auto.cnf
RESET PERSIST;# 删除 mysqld-auto.cnf 中的特定变量,如果变量不存在会报错
RESET PERSIST system_var_name;# 删除 mysqld-auto.cnf 中的特定变量,不存在则不会报错。
RESET PERSIST IF EXISTS system_var_name;
当使用 SET PERSIST 命令时,变量更改将更新到数据目录中的 mysqld-auto.cnf 选项文件。mysqld-auto.cnf 是仅在第一次执行 PERSIST 或 PERSIST_ONLY 语句时创建的 JSON 格式文件。内容如下:
需要的授权:
GRANT SYSTEM_VARIABLES_ADMIN, PERSIST_RO_VARIABLES_ADMIN, SHUTDOWN on *.* to 'admin'@'localhost';
参考资料:Persisted System Variables
1.2 管理员端口
MySQL 8.0 提供了管理员的连接地址和端口,默认的管理员端口是 33062,相当于是为管理员连接提供了专用通道,且没有连接数限制,这样即使 MySQL 连接数满了,也可以连接上去修改 max_connections 的大小。
[(none)]>show variables like '%admin%';
+---------------------------------+-----------------+
| Variable_name | Value |
+---------------------------------+-----------------+
| admin_address | |
| admin_port | 33062 |
+---------------------------------+-----------------+
使用管理员端口的用户需要拥有 SERVICE_CONNECTION_ADMIN 权限的用户连接。
参考资料:Administrative Connection Management
1.3 资源组
MySQL 是单进程多线程的程序,在 8.0 之前所有的线程优先级都是相同的,并且所有的线程资源都是共享的。8.0 之后推出 RESOURCE GROUP 特性,DBA 可以通过资源组的方式修改线程优先级以及所使用的资源,目前仅支持 CPU 资源。
业务上经常会有一些跑批操作,这些跑批 SQL 往往较复杂且涉及数据量大,执行起来非常消耗资源,往往是业务低峰夜间执行,避免影响其它线程运行避免 CPU 跑满,堵塞其它线程,导致请求进不去。有了 RESOURCE GROUP 特性,我们可以创建一个资源组,让跑批任务限制在固定的一个或多个 CPU 核上,避免影响其它线程。
由于文章篇幅,如果想使用或者详细了解该特性的朋友请参考下方文档。
详细解读:8.0 新特性 - RESOURCE GROUP
1.4 数据库粒度只读
MySQL 8.0 可设置数据库粒度的只读模式,禁止所有更新操作,适用于数据迁移场景。
# 开启只读模式
ALTER DATABASE db_name READ ONLY = 1;
# 关闭只读模式
ALTER DATABASE db_name READ ONLY = 0;
1.5 show processlist 实现方式
show processlist 默认是从全局的线程管理器中获取线程信息,这种实现方式会持有全局互斥锁,对数据库的性能有一定的影响,官方推荐使用 performance_schema.processlist 的方式查询,这种方式不会持有全局锁。
MySQL 8.0.22 中,引入 performance_schema_show_processlist 参数,设置为 ON 则表示使用 performance_schema.processlist 的方式实现 show processlist 默认为 OFF。
参考资料:The processlist Table
1.6 加速索引创建速度
MySQL 8.0.27 中,引入 innodb_ddl_threads 参数。该参数用于 MySQL 创建二级索引时,在排序和构建阶段,使用线程的个数,一定程度上可以加快索引的创建速度,默认为 4 个。
大表创建索引时,可以给流量较低的备库开启该参数,从而减小主备延迟。
详细解读:8.0 新特性 - innodb_ddl_threads
1.7 控制连接的内存使用量
MySQL 8.0.28 开始,引入 connection_memory_limit 变量,可以限制单个连接内存的使用量,如果超过最大值连接会被断开。
1.8 克隆插件
克隆插件(Clone Plugin)是 MySQL 8.0.17 引入的一个重大特性,可以从本地或者远程克隆数据。
如果在 8.0.17 之前想要给 MySQL 复制拓扑中添加一个新节点,只支持 Binlog 一种恢复方式,如果新节点所需要的 Binlog 在集群中不存在,就只能先借助备份工具进行全量备份恢复,再配置增量同步。这种方式虽然能达到添加新节点的目的,但总归是需要借助外部工具,相对来说是有一定的使用门槛和工作量。
Clone 插件支持本地克隆和远程克隆,可以很方便的帮助我们添加一个新的节点,也可以作为 Innodb 引擎的物理备份工具。
克隆插件之前有文章详细介绍过,感兴趣的可以阅读。
推荐阅读:MySQL 8.0 Clone Plugin 详解
1.9 mysqldump 新增参数
在 MySQL 8.0.30 中,mysqldump 新增了 mysqld-long-query-time 选项,允许自定义 long_query_time 的会话值。这样可以避免将逻辑备份相关的语句记录在慢日志中。
参考资料:mysqldump_mysqld-long-query-time
1.10 慢日志增强
在 MySQL 8.0.14 中,引入 log_slow_extra 参数,开启后在慢日志中会记录更加详细的信息,例如语句异常终止的信号、语句返回数据的字节大小、排序的行数等等。
该参数默认是关闭的,开启后记录的信息更多,意味着慢日志将膨胀的更快,额外的字段信息可参考下方资料。
参考资料:log_slow_extra
1.11 快速加列
从 MySQL 8.0.12 开始,OnlineDDL 开始支持 INSTANT 算法,可以使用该算法进行加字段操作,只需修改表的元数据信息,操作瞬间就可以完成。不过在 8.0.29 之前,列只能加在表的最后的位置。从 8.0.29 开始移除了该限制,快速加列支持加到表的任何位置,并且删除列也支持 INSTANT 算法。
通过只修改数据字典的方法来实现大表快速加列,避免之前加列操作必须做的数据拷贝,从而大幅缩小大表加列所需的时间,减少对系统的影响。
推荐阅读:8.0 新特性 - Instant Add Column
1.12 InnoDB 隐藏主键
MySQL Innodb 引擎采用的是 IOT(索引组织表)存储方式,主键的重要性就不言而喻。在早期版本用户如果没有显式指定主键,会自动生成隐藏主键 row_id 来组织 B+ 树,隐藏主键 row_id 只会作用于 MVCC、Redo 和 Undo 等内部机制,无法在复制模块中使用。一些大数据组件生成的表结构,往往都没有主键设计,会出现全表扫描回放问题,带来非常大的主备延迟。
而且 MySQL 一些周边软件 gh-ost、DTS 服务等,都有依赖主键设计,没有主键会降低数据库的可维护性。
MySQL 8.0.30 引入 sql_generate_invisible_primary_key 参数,可为没有显式设置主键的表创建一个隐式的主键。该特性之前的文章中有详细解读。
推荐阅读:8.0 新特性 - Generated Invisible Primary Key
1.13 Redo 配置
在 MySQL 8.0.30(也包含 5.7 版本) 版本 Redo 的配置相关的参数主要有下面两个:
-
innodb_log_files_in_group:Redo 文件的个数,默认为 2。
-
innodb_log_file_size:Redo 在磁盘上,单个文件的大小。
du -sh ib_logfile*
128M ib_logfile0
128M ib_logfile1cat /etc/my.cnf | grep innodb_log_file_size
innodb_log_file_size = 128M
这两个参数不支持在线修改,必须重启生效。
MySQL 8.0.30 版本发布后提供新参数 innodb_redo_log_capacity 代替之前两个参数,不过原来两个参数并没有取消,会自动计算转换为 innodb_redo_log_capacity 抛出警告:
[Warning] [MY-013907] [InnoDB] Deprecated configuration parameters innodb_log_file_size and/or innodb_log_files_in_group have been used to compute innodb_redo_log_capacity=1073741824. Please use innodb_redo_log_capacity instead.
支持在线修改:
set global innodb_redo_log_capacity=1073741824;
推荐阅读:8.0 新特性 - innodb_redo_log_capacity
1.14 undo 配置
MySQL 8.0 版本默认开启 innodb_undo_tablespaces 参数,将 undo 日志从系统表空间 ibdata 文件中独立出来,这样就可以动态调整 undo 大小,便于收缩 undo 空间,否则必须重新初始化实例。
除了默认会独立出 undo 空间外,还提供了 SQL 语句可用于管理 undo 表空间。
参考资料:Undo Tablespaces
1.15 事务调度 CATS
MySQL 8.0 中的 InnoDB 引擎使用了 Contention-Aware Transaction Scheduling (CATS) 竞争感知事务调度算法,可以提升高并发场景下数据库的吞吐,提升数据库整体性能。
当多个事务同时获取一把锁,那么哪个事务先获得这把锁?在 MySQL 8.0 版本之前,使用的是 FIFO 先进先出算法,该算法会将锁优先分配给最先进入等待队列中的事务。在 MySQL 8.0 中,则会计算每个事务堵塞的事务数,最后将锁分配给堵塞事务最多的事务。
推荐阅读:Transaction Scheduling
1.16 自增主键持久化
MySQL 5.7 版本 auto_increment
是存储在内存中的,这就导致每次重启 MySQL 都会重新计算该值,计算逻辑是取该字段的 MAX VALUE
请看下方 case:
-- 创建一张测试表,id 为自增主键
create table t1(id bigint auto_increment primary key,c1 varchar(10) not null,c2 varchar(10) not null
);
插入 8 行记录:
insert into t1(c1, c2) value ('a', 'b'),('a', 'b'),('a', 'b'),('a', 'b'),('a', 'b'),('a', 'b'),('a', 'b'),('a', 'b');
此时 AUTO_INCREMENT
的值为 9,下一条写入会被分配自增 ID 为 9:
select TABLE_NAME, AUTO_INCREMENT from information_schema.TABLES where TABLE_NAME = 't1';
TABLE_NAME
AUTO_INCREMENT
t1
9
然后删除后 4 条记录:
delete from t1 where id > 4;
重启数据库:
>$ service mysqld restart
Shutting down MySQL.... SUCCESS!
Starting MySQL... SUCCESS!
查询 t1 表的自增 ID:
select TABLE_NAME, AUTO_INCREMENT from information_schema.TABLES where TABLE_NAME = 't1';
TABLE_NAME
AUTO_INCREMENT
t1
5
可以看到 MySQL 在重启之后自增列的值被重置了。这个现象被称之为 BUG 主要是在现在的互联网业务中,支撑业务数据的不仅仅只有 MySQL,还可能会有 Redis,RabbitMQ 等缓存和消息队列或者是单独的 MySQL 日志归档库,自增列可能会被用来作为关联各个存储之间的“逻辑外键”,当 MySQL 重启之后,新写入的数据可能会用到已经被删除的值,导致数据库中的数据和外部系统之间的数据出现错误的关联。另外一种问题场景就是 MySQL 自身各个表之间有外键关系,但是没有建立外键约束,也会遇到类似的问题。
该 BUG 已在 MySQL 8.0 版本修复,推荐阅读。
Auto-Increment Counter Persistence in MySQL 8: Comparing the Evolution From MySQL 5.7
1.17 在线回收临时表空间
在 MySQL 5.7 版本中,用户创建的临时表和磁盘临时表会存储在全局的临时表空间 ibtmp1 中,会话结束后并不会释放临时空间,只会打上删除的标记可复用,如果要释放临时表空间需要重启实例。
MySQL 8.0 新增 innodb_temp_tablespaces_dir 参数,默认在数据目录中 #innodb_tmp 命名的一个临时表空间池,一个会话最多会分配两个临时表空间,分别用来存储用户创建的临时表和优化器内部创建的临时表。当会话连接断开时,会截断这两个临时表空间。
参考资料: Temporary Tablespaces
1.18 自适应参数
MySQL 8.0.14 推出了 innodb_dedicated_server 参数,开启该参数后 MySQL 会根据服务器的配置自适应一些关键参数。比如 buffer pool 的大小和 redo log 的大小,是一个对云厂商比较友好的特性。如果你的 MySQL 是部署在一个专属的数据库服务器中,可以开启该参数。
参考资料:innodb_dedicated_server
2. 开发相关
2.1 默认字符集
MySQL 8.0 默认字符由 latin1 调整为 utf8mb4,值得注意的是,在 MySQL 8.0 中,utf8mb4 的默认排序规则是 utf8mb4_0900_ai_ci,在 MySQL 5.7 中则是 utf8mb4_general_ci,也就是如下两个参数的默认值。
[mysqld]
character_set_server=utf8mb4
collation_server=utf8mb4_0900_ai_ci
从 MySQL 5.7 升级到 8.0 的话,可以将参数设置为 5.7 相同的值,数据迁移完成后可以改回,或者一直沿用 5.7 的参数。
参考资料:MySQL 8.0 Configuration Changes
2.2 GROUP BY ASC/DESC 语法
MySQL 8.0 版本,不支持 GROUP BY ASC/DESC 语法,如果需要对分组的列进行排序,需要显式指定排序列。
-- MySQL 5.7
select `name`,count(*) from table_name GROUP BY `name` desc;-- MySQL 8.0
select `name`,count(*) from table_name GROUP BY `name` ORDER BY `name` desc;
推荐阅读:MySQL 8.0 SQL Change
2.3 公用表达式
公用表达式 简称:WITH (Common Table Expressions),是 MySQL 8.0 新增的语法,可以定义一个临时的结果集合,全局可用。某些特殊场景下使用公用表达式可以让 SQL 更加简洁,同时也提升了 SQL 的可读性。
WITH cte (col1, col2) AS
(SELECT 1, 2UNION ALLSELECT 3, 4
)
SELECT col1, col2 FROM cte;-- 输出:
+------+------+
| col1 | col2 |
+------+------+
| 1 | 2 |
| 3 | 4 |
+------+------+
参考资料:Common Table Expressions
2.4 窗口函数
窗口函数(Window Function)是一个提升 MySQL 数分能力的特性,可针对一组进行计算,并为每行返回一个结果,这一点和聚合函数不同。聚合函数只能为每个分组返回一个结果,窗口函数中的 over 子句定义了要计算行的行窗口。
sales 为销售表,有每个城市和商品的利润:
mysql> SELECT * FROM sales ORDER BY country, year, product;
+------+---------+------------+--------+
| year | country | product | profit |
+------+---------+------------+--------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2001 | Finland | Phone | 10 |
| 2000 | India | Calculator | 75 |
| 2000 | India | Calculator | 75 |
| 2000 | India | Computer | 1200 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 1500 |
| 2001 | USA | Computer | 1200 |
| 2001 | USA | TV | 150 |
| 2001 | USA | TV | 100 |
+------+---------+------------+--------+
如果想计算总利润,可以使用 sum 函数,如果想要知道每个国家的利润,可以使用 group by 分组再使用 sum 函数。
mysql> SELECT SUM(profit) AS total_profitFROM sales;
+--------------+
| total_profit |
+--------------+
| 7535 |
+--------------+
mysql> SELECT country, SUM(profit) AS country_profitFROM salesGROUP BY countryORDER BY country;
+---------+----------------+
| country | country_profit |
+---------+----------------+
| Finland | 1610 |
| India | 1350 |
| USA | 4575 |
+---------+----------------+
聚合函数则可以使用聚会函数为每一行返回一个结果,如下面的 case 可以把总利润和国家利润计算出来放在每条记录的后面,便于对比。
mysql> SELECTyear, country, product, profit,SUM(profit) OVER() AS total_profit,SUM(profit) OVER(PARTITION BY country) AS country_profitFROM salesORDER BY country, year, product, profit;
+------+---------+------------+--------+--------------+----------------+
| year | country | product | profit | total_profit | country_profit |
+------+---------+------------+--------+--------------+----------------+
| 2000 | Finland | Computer | 1500 | 7535 | 1610 |
| 2000 | Finland | Phone | 100 | 7535 | 1610 |
| 2001 | Finland | Phone | 10 | 7535 | 1610 |
| 2000 | India | Calculator | 75 | 7535 | 1350 |
| 2000 | India | Calculator | 75 | 7535 | 1350 |
| 2000 | India | Computer | 1200 | 7535 | 1350 |
| 2000 | USA | Calculator | 75 | 7535 | 4575 |
| 2000 | USA | Computer | 1500 | 7535 | 4575 |
| 2001 | USA | Calculator | 50 | 7535 | 4575 |
| 2001 | USA | Computer | 1200 | 7535 | 4575 |
| 2001 | USA | Computer | 1500 | 7535 | 4575 |
| 2001 | USA | TV | 100 | 7535 | 4575 |
| 2001 | USA | TV | 150 | 7535 | 4575 |
+------+---------+------------+--------+--------------+----------------+
参考资料:Window Function Concepts and Syntax
2.5 check 约束
MySQL 8.0 支持 check 约束,请看下方示例,在 age 字段可以创建一个约束,年龄必须小于 150 岁。
CREATE TABLE user_test(id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '主键',name VARCHAR(10) not null COMMENT '姓名',age int UNSIGNED CHECK(age<150) COMMENT '年龄'
);
插入 200 岁的张三会返回异常。
insert into user_test values (1, '张三', 200);
-- 异常
ERROR 3819 (HY000): Check constraint 'user_test_chk_1' is violated.
参考资料:CHECK Constraints
2.6 隐藏列
隐藏列是 MySQL 8.0.23 引入的新特性,可以设置列的可见性,除非显式指定隐藏属性的字段,否则 select * from 不会显示。
CREATE TABLE t1 (i INT,j DATE default '2024-01-01' INVISIBLE
) ENGINE = InnoDB;
写入三条数据:
insert into t1 values (1),(2),(3);>select * from t1;
+------+
| i |
+------+
| 1 |
| 2 |
| 3 |
+------+>select i, j from t1;
+------+------------+
| i | j |
+------+------------+
| 1 | 2024-01-01 |
| 2 | 2024-01-01 |
| 3 | 2024-01-01 |
+------+------------+
参考资料:Invisible Columns
2.7 不可见索引
可以修改索引的可见性,如果调整索引不可见,那么优化器会默认忽略该索引。该特性在索引维护中非常有用,大表中维护一个索引的代价还是比较大的。
讲一个笔者亲身经历过的故障吧,研发人员要删除一张 20G 大表中的一个索引,执行完后数据库 CPU 立马飙升,原来还有 SQL 依赖刚才删除的索引,那索引被删掉后这业务的 SQL 就全部全表扫描了,数据库 CPU、IO 立马打满了。此时加索引也很难加上,必须得停掉相关业务的 SQL 重新添加索引,影响范围很大。
如果有不可见索引,那么删除一个索引的流程就会安全很多,可以先调整索引的可见性,观测一段时间,期间如果有任何问题则打开索引即可,毕竟大表加一个索引也需要时间,修改索引可见性几乎瞬间完成。
-- 查询元数据,哪些索引不可见
select table_schema, table_name, index_name, column_name, is_visible
from information_schema.statistics
where is_visible = 'no';-- 修改索引可见
alter table xx alter index idx_xx visible;
-- 修改索引不可见
alter table xx alter index idx_xx invisible;
-- 创建一个不可见索引
alter table xx add index idx_xx(column_name) invisible;
推荐阅读:Invisible Indexes
2.8 降序索引
MySQL 8.0 之前的索引排序规则之前只允许 ASC 存储,创建时指定 DESC 也会被忽略,现在创建索引时可以指定索引的排序方向,便于应对一些排序场景,避免文件排序。
推荐阅读:Descending Indexes
2.9 函数索引
MySQL 8.0 提供了函数索引,可应对使用函数导致索引失效的场景,详细可参考下方案例。
推荐阅读:MySQL 函数导致索引失效应对策略
2.10 VALUES 语法
values 是 MySQL 8.0.19 引入的一个 DML 语法,属于一个种表值构造语法。
mysql> VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8) ORDER BY column_1;
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
| 1 | -2 | 3 |
| 4 | 6 | 8 |
| 5 | 7 | 9 |
+----------+----------+----------+
3 rows in set (0.00 sec)
推荐阅读:VALUES Statement
2.11 NOWAIT 和 SKIP LOCKED
MySQL 8.0 版本在 SELECT…FOR SHARE 和 SELECT…FOR UPDATE 语句中引入了 NOWAIT 和 SKIP LOCKED 选项,用来解决电商场景中的热点行问题。
CREATE TABLE `test_semi` (`a` int NOT NULL,`b` int DEFAULT NULL,`c` int DEFAULT NULL,PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;insert into test_semi values(10, 1, 0),(11, 2, 0),(12,1,0),(13,2,0),(14,1,0);
使用 Session 1 开启一个事务:
begin;
select * from test_semi where b = 1 for update;
+----+------+------+
| a | b | c |
+----+------+------+
| 10 | 1 | 0 |
| 12 | 1 | 0 |
| 14 | 1 | 0 |
+----+------+------+
Session 2 尝试查询全表:
-- 堵塞:
select * from test_semi for update;-- 跳过了锁定的行
select * from test_semi for update SKIP LOCKED;
+----+------+------+
| a | b | c |
+----+------+------+
| 11 | 2 | 0 |
| 13 | 2 | 0 |
+----+------+------+-- 需要加的锁,被其他事务持有,则直接返回异常,不会等待锁超时
select * from test_semi for update NOWAIT;
ERROR 3572 (HY000): Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set.
推荐阅读:Locking Reads
2.12 分区表支持
通用的分区接口已从代码中移除,在 MySQL 8.0 中,如果要使用分区表,只能使用 InnoDB 存储引擎。
3. 复制相关
3.1 Binlog 中包含元数据
MySQL 5.7 中 Binlog 是不记录元数据的,使用 mysqlbinlog 解析出来的 binlog 文本字段是用 @1、@2 按照顺序排列的,没有字段名称。MysQL 8.0.1 版本提供了 binlog_row_metadata 参数,设置为 full 的时候会在 Binlog Table_map event 中记录字段信息。
使用 mysqlbinlog 解析时需要指定 --print-table-metadat 选项。
mysqlbinlog -vv --base64-output=decode-rows --print-table-metadata mysql-bin.000003 #240729 11:12:54 server id 553306 end_log_pos 431 CRC32 0x5478e143 Table_map: `test`.`test_semi` mapped to number 146
# has_generated_invisible_primary_key=0
# Columns(`a` INT NOT NULL,
# `b` INT,
# `c` INT)
# Primary Key(a)
# at 431
#240729 11:12:54 server id 553306 end_log_pos 597 CRC32 0x05b1fd6a Update_rows: table id 146 flags: STMT_END_F
### UPDATE `test`.`test_semi`
### WHERE
### @1=10 /* INT meta=0 nullable=0 is_null=0 */
### @2=1 /* INT meta=0 nullable=1 is_null=0 */
### @3=0 /* INT meta=0 nullable=1 is_null=0 */
3.2 Binlog 记录事务提交时间戳
如果想从 Binlog 查一些问题,比如业务 bug 造成的数据错乱,需要秒级以内的粒度来分析问题,MySQL 8.0 的 Binlog 中会记录事务提交的时间戳。
-- 源库事务提交的时间戳
# original_commit_timestamp=1722222774134690 (2024-07-29 11:12:54.134690 CST)
-- 当前节点事务提交的时间戳
# immediate_commit_timestamp=1722222774134690 (2024-07-29 11:12:54.134690 CST)
还可以提升 MySQL 复制关系的可观测性,详细参考下文。
推荐阅读:MySQL 8 and Replication Observability
3.3 Binlog 过期时间
在 MySQL 8.0 之前,Binlog 过期时间由 exprice_logs_days 参数控制,单位是天。在 MySQL 8.0 中,引入 binlog_expire_logs_seconds 参数,可设置秒级别的过期时间,默认是 2592000 秒,既 30 天。
如果 expire_logs_days 和 binlog_expire_logs_seconds 参数都设置了非 0 的值,那么 binlog_expire_logs_seconds 的优先级更高。
另外,MySQL 8.0.29 新增 binlog_expire_logs_auto_purge 参数,用来禁用 Binlog 自动清理。在此之前只能通过将 binlog_expire_logs_seconds 和 exprice_logs_days 设置为 0 来实现。
参考资料:binlog_expire_logs_seconds
3.4 ReplicaSet 复制方案
MySQL Innodb ReplicaSet 是 MySQL 团队在 8.0 版本上添加的功能,用来帮助用户快速部署和管理主从复制,在数据库层仍然使用的是主从复制技术。
- ReplicaSet 主要包含三个组件:MySQL Router、MySQL Server 以及 MySQL Shell 高级客户端。
- MySQL Shell 负责管理 ReplicaSet 包括部署、切换、节点加入等,都可以通过内置 AdminAPI 自动化完成。
- MySQL Router 是一款轻量级中间件,可在应用程序和 ReplicaSet 之间提供透明路由和读写分离功能。
推荐阅读:MySQL Innodb ReplicaSet
4. 安全相关
4.1 角色管理
MySQL Role 就是 8.0 新增加关于权限的功能 Role 角色 可以理解为是一个权限的集合,比如在 SQLserver 中也有相关 Role 的功能,下图是 SQLserver 的角色管理界面 与 SQLserver 不同的是 MySQL 目前没有系统默认系统的角色,需要我们自行创建。
如何使用 role 本文就不展开介绍了,如果一个实例账号比较多的情况下,可通过 role 简化 DBA 的日常管理操作。另外一个账号可以属于多个角色,并且支持在 session 中切换,我觉得这是一个非常好的特性,有什么用呢?比如 DBA 日常排查问题的时候只需要只读权限即可,在变更的时候才需要高权限,那么 DBA 可以在两个角色中切换,可以有效避免误操作。
推荐阅读:Using Roles
4.2 caching_sha2_password
MySQL 8.0 版本默认的密码插件由 mysql_native_password 更改为 caching_sha2_password 插件。这项改动有什么影响?遇到问题如何修改呢?可参考下方文档。
推荐阅读:Caching SHA-2 Pluggable Authentication
4.3 print_identified_with_as_hex
该特性是与 caching_sha2_password 配套的特性,用于账号迁移场景。
set session print_identified_with_as_hex = on;show create user t1@'%';
CREATE USER `t1`@`%` IDENTIFIED WITH 'caching_sha2_password' AS 0x2441243030352416564A3E2B11497D1D225702020B6A635920160378523571616436544E5A594B7273357142392E434D79796D424162485A365536317A63425349372E446A42 REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT PASSWORD REQUIRE CURRENT DEFAULT;
参考资料:SHOW CREATE USER Statement
4.4 更细粒度的权限控制
MySQL 8.0 拥有更细粒度的权限控制,如果授予 super 权限会提示 warning。
通过 show privileges 命令查询权限选项 5.7 有 31 个,而 8.0 有 69 个权限选项,另外授权相关的表引擎调整为了 InnoDB 引擎。
show privileges;
参考资料:Privileges Provided by MySQL
4.5 生成随机密码
MySQL 8.0 不能通过 grant 语法创建用户,必须先 create user 然后再授权。在创建用户过程中,可以让 MySQL 生成随机密码。
create user user1@'%' identified by random password;-- 输出:
+-------+------+----------------------+-------------+
| user | host | generated password | auth_factor |
+-------+------+----------------------+-------------+
| user1 | % | K[BnRT0qxSWd8zG]J7A0 | 1 |
+-------+------+----------------------+-------------+
修改密码的时候也可以指定随机密码:
alter user user1@'%' identified by random password;-- 输出:
+-------+------+----------------------+-------------+
| user | host | generated password | auth_factor |
+-------+------+----------------------+-------------+
| user1 | % | TCiEI%8<}cN8&_eOY.m( | 1 |
+-------+------+----------------------+-------------+set password for user1@'%' to random;-- 输出:
+-------+------+----------------------+-------------+
| user | host | generated password | auth_factor |
+-------+------+----------------------+-------------+
| user1 | % | YpS/oLgUY_@G>jO5/lE, | 1 |
+-------+------+----------------------+-------------+
随机密码的长度由参数 generated_random_password_length 来决定,默认为 20 个字符。
参考资料:Random Password Generation
4.6 双重密码支持
MySQL 8.0 支持一个用户同时设置两个密码,新密码和旧密码都可以用于登陆数据库。
-- 给 user1 添加一个新的随机密码
alter user user1@'%' identified by random password retain current password;-- 输出:
+-------+------+----------------------+-------------+
| user | host | generated password | auth_factor |
+-------+------+----------------------+-------------+
| user1 | % | E8wLo{>0]so],XImeeEH | 1 |
+-------+------+----------------------+-------------+-- 删除旧密码
alter user user1@'%' discard old password;
可用于业务连接账号密码修改过渡阶段。
参考资料:Dual Password Support
4.7 密码错误锁定用户
MySQL 8.0.19 开始,可设置用户密码错误次数,失败后锁定用户。
-- FAILED_LOGIN_ATTEMPTS:密码失败次数
-- PASSWORD_LOCK_TIME:锁定时间,单位是天 设置为 UNBOUNDED 表示永久锁定alter user user1@'%' FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME 3;
密码输入失败 4 次,锁定 3 天,抛出如下异常。
ERROR 3955 (HY000): Access denied for user 'user1'@'localhost'. Account is blocked for 3 day(s) (3 day(s) remaining) due to 4 consecutive failed logins.
对于锁定的账号,在以下情况下会解锁:
- 数据库重启。
- 执行 FLUSH PRIVILEGES。
- 锁定时间结束。
- 通过 alter user 重置 FAILED_LOGIN_ATTEMPTS 或 PASSWORD_LOCK_TIME。
- 通过 alter user user1@‘%’ account unlock; 解锁。
参考资料:Failed-Login Tracking and Temporary Account Locking
4.8 账号备注信息
创建用户时,可以通过 COMMENT/ATTRIBUTE 子句对账号添加备注信息。设置的备注信息可以使用下面的方式查看。
-- 添加备注信息
alter user 'user1'@'%' ATTRIBUTE '{"username":"张三", "empno":"10001", "job":"DBA"}';-- 查询
select * from user_attributes where user = 'user1';-- 输出:
+-------+------+-----------------------------------------------------------------------------------+
| USER | HOST | ATTRIBUTE |
+-------+------+-----------------------------------------------------------------------------------+
| user1 | % | {"job": "DBA", "empno": "10001", "comment": "测试用户", "username": "张三"} |
+-------+------+-----------------------------------------------------------------------------------+
5. 优化器相关
5.1 hash join
MySQL 8.0 引入了 Hash join,对于 BNL Join,会基于驱动表的数据在 join buffer 中构建一个Hashmap。如果驱动表的数据可以一次性全部加载到 join buffer 中,则只需要对被驱动表进行一次全表扫描,就能完成 join。如果驱动表的数据无法一次性全部加载到 join buffer 中,MySQL 会根据关联条件对驱动表和被驱动表进行分片,一次 join 一对分片,这种情况下,一般只需要扫描两次数据,就能完成 join 操作。
MySQL 8.0.20 之前 hash join 只适用于等值连接和笛卡尔积。
select * from a join b on a.id = b.id;
select * from a join b;
MySQL 8.0.20 开始,hash join 支持非等值连接、半连接、反连接、左外连接、右外连接。
-- 非等值连接
select * from a join b where a.a1 > b.b1;
-- 半连接
select * from a where a.a1 in (select b1 from b);
-- 反连接
select * from a where not exists (select * from b where a.a1 = b.b1)
-- 左外连接
select * from a left join b on a.id = b.id;
-- 右外连接
select * from a right join b on a.id = b.id;
推荐阅读:MySQL优化器特性(四)表关联之BNL(Block Nested Loop)和Hash Join
5.2 直方图
直方图(Histogram)是数据库提供的一种(索引之外的)基础统计信息,用于描述列上的数据分布情况。它最典型的场景是估算查询谓词的选择性,以便选择合适的执行计划。
例如下方的 SQL 需要先通过 where 条件过滤数据后选择结果集小的表作为驱动表,这时,优化器需要知道两表的总行数,也需要知道每个表符合条件的行数,也就是谓词的选取率。如果该字段没有二级索引和直方图的话,MySQL 很难准确的选到小表,因为无法知道表中的数据分布,在多表关联的场景执行计划表关联的顺序对 SQL 执行效率影响很大。
select *
from customer join orders on customer.cust_id = orders.customer_id
where customer.balance < 1000 and orders.total > 10000
如果为两张表创建直方图,表中的数据会被排序分为 100 个 bucket,并记录每个桶中数据的最大值、最小值、出现频次占比等信息。这样的话就可以影响优化器,在关联过程中,选择合适的小表作为驱动表。
该特性适合多表关联由于数据分布不均匀选错索引的场景,可以创建直方图引导优化器选择高效的访问路径。毕竟索引的维护是有代价的,直方图只在创建和更新时才会有开销。
参考资料:Optimizer Statistics
6. 推荐升级流程
- 基于当前业务的数据备份恢复一台实例,将这台实例升级为 8.0。
- 在新实例上进行充分的测试(回归测试/性能测试)通过业务测试识别出潜在问题。
- 将测试发现的问题进行改造。
- MySQL 5.7 和 MySQL 8.0 配置双向同步(用 read_only 保持只有一边写入)便于割接后遇到问题回滚。
- 割接切换到 MySQL 8.0。
- 观测 7 天,无异常后释放双向同步和 5.7 数据库资源。
总结
MySQL 8.0 相比 5.7 版本更新很多新特性,很多改变没有直接删除,便于用户过渡,兼容性还是比较高的。不过到 8.1、8.2 的创新版本,老的 5.7 的参数和语法就已经删除。
由于 5.7 已经结束软件生命周期,意味着 Oracle 官方将不再为该版本提供更新和漏洞修复,虽然数据库厂商保证原则性上 MySQL 是安全的,保不齐有时会发现极其罕见的重大安全漏洞。如果用户坚持使用 5.7 版本将会面临安全风险增大、生态系统衰退、运维成本增高等问题。建议还在使用 5.7 的用户开始筹备规划未来的升级计划,从而为业务提供持续可靠的数据库服务。
相关文章:
MySQL 8.0 新特性汇总
文章目录 前言1. 运维管理 1.1 可持久化变量1.2 管理员端口1.3 资源组1.4 数据库粒度只读1.5 show processlist 实现方式1.6 加速索引创建速度1.7 控制连接的内存使用量1.8 克隆插件1.9 mysqldump 新增参数1.10 慢日志增强1.11 快速加列1.12 InnoDB 隐藏主键1.13 Redo 配置1.14…...
Resnet C ++ 部署 tensort 部署(四)
Resnet C 部署 pytorch功能测试(一) Resnet C 部署 模型训练(二) Resnet C 部署 模型测试&转 onnx(三) Resnet C 部署 tensort 部署(四) 之后,开始onnx 转trt 部…...
《Java核心技术I》对并发散列映射的批操作
对并发散列映射的批操作 Java API提供了批处理,计时其他线程处理映射,这些操作也能安全的执行。 3种不同操作: search(搜索),为每个键或值应用一个函数,直到函数生成一个非null的结果,然后搜索终止&…...
记录一次使用git无权限的问题排查
正常的配置了公私钥之后,在gitlab中也存储了配对的公钥,但当使用git clone 时,总是报无权限 由于在这台机器中添加了多个公私钥,有点复杂,我们可以使用命令 ssh -vvvT 调试一下 ssh -vvvT yourGitlabAddr...
appium学习之二:adb命令
1、查看设备 adb devices 2、连接 adb connect IP:端口 3、安装 adb install xxx.apk 4、卸载 adb uninstall 【包名】 5、把对应目录下的1.txt文件传到手机sdcard下 adb push 1.txt /sdcard 6、进入对应的设备里 adb shell 7、切入sdcard目录 cd /sdcard 8、ls 查…...
Linux Vi/Vim使用 ⑥
掌握 CentOS 7 下的 Vi/Vim 编辑器:从安装到精通 在 CentOS 7 系统的日常运维、编程开发以及各类文本处理场景中,Vi/Vim 编辑器都是不可或缺的得力工具。它以轻量、高效、功能强大著称,虽然初次上手有一定学习门槛,但掌握之后便能…...
JCR一区牛顿-拉夫逊优化算法+分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测
JCR一区牛顿-拉夫逊优化算法分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测 目录 JCR一区牛顿-拉夫逊优化算法分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.中科院…...
easyExcel实现表头批注
背景: 网上大部分都不能直接使用,为此总结一个方便入手且可用的工具,用自定义注解实现 依赖包: <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>…...
Pytest测试用例使用小结
基础使用 Pytest 测试用例实现代码 import pytest from server.service import Servicepytest.fixture def service():return Service(logger)class TestService:classmethoddef setup_class(cls):"""初始化设置一次:return:"""logger.info(&q…...
LeetCode题练习与总结:132 模式--456
一、题目描述 给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。 如果 nums 中存在 132 模式的子序列 &a…...
IdentityServer4框架、ASP.NET core Identity
OAuth2.0 IdentityServer4 官网 中文官网 ASP.NET Core Identity提供了一个用来管理和存储用户账户的框架. IdentityServer4是基于ASP.NET Core实现的认证和授权框架,是对OpenID Connect和OAuth 2.0协议的实现。 IdentityServer是一个中间件,它可以添加符合OpenID…...
【分子材料发现】——GAP:催化过程中吸附构型的多模态语言和图学习(数据集处理详解)(二)
Multimodal Language and Graph Learning of Adsorption Configuration in Catalysis https://arxiv.org/abs/2401.07408Paper Data: https://doi.org/10.6084/m9.figshare.27208356.v2 1 Dataset CatBERTa训练的文本字符串输入来源于Open Catalyst 2020 (OC20…...
SpringBoot开发过程中经常遇到问题解决方案分享
目录 1. Spring Boot应用启动缓慢 2. 数据库连接池配置问题 3. Spring Boot应用无法连接外部服务 4. 配置文件读取不生效 5. Spring Boot应用的日志输出不完整 6. Spring Boot中的Transactional事务管理问题 1. Spring Boot应用启动缓慢 问题原因: Spring Boo…...
AR眼镜_消费级工业AR智能眼镜主板硬件解决方案
AR眼镜的研发是一项复杂的软硬件集成工程,它需要在摄影、音频、交互和连接等多个方面提供卓越的基础体验,因此产品的每个细节都显得尤为重要。 在设计AR眼镜时,重量、体积和散热性能都是必须认真考量的关键因素。在芯片平台的选择上ÿ…...
Springboot 核心注解
Spring Boot 是一个基于 Spring 框架的扩展,旨在简化新 Spring 应用的初始搭建以及开发过程。它通过自动配置和约定优于配置的原则,减少了开发者的工作量。Spring Boot 提供了一组核心注解和 Starter 依赖管理工具来帮助开发者快速启动项目。 1. Spring…...
Nacos集群搭建【Oracle作外部数据源】
一、知识点分析 1.Nocas是什么? Nacos是一个动态服务发现、配置管理和服务管理平台。 1.1定义与背景: Nacos,全称为Dynamic Naming and Configuration Service,是由阿里巴巴开源的云原生应用配套工具。它旨在简化微服务架…...
云轴科技ZStack出席中国电信国际EMCP平台香港发布会,持续推动海外合作
近日,以“云聚未来 翼起新篇”为主题的中国电信国际多云服务一站式平台(E-surfing Managed Cloud Platform,简称EMCP平台)新闻发布会在香港成功举办,标志着中国电信国际在云计算服务领域取得了又一重大进展。云轴科技…...
爬虫自动化之drissionpage+SwitchyOmega实现随时切换代理ip
本文介绍了如何使用DrizzlePage进行爬虫自动化,并重点讲解了首次启动时设置代理IP以及通过SwitchyOmega插件实现随时切换代理IP的方法。 安装一次,后面调用就不会再去安装了 下载地址:https://github.com/FelisCatus/SwitchyOmega/releases 这两个文件随便那个都可以,下载…...
docker安装kettle(PDI)并实现web访问
我是MAC电脑M1版本,希望把软件交给docker进行管理,最近公司同事都通过kettle来实现外部数据对接,所以我本地也有安装kettle需求,在网上找到了这个解决方案操作很简单,但出现了无法访问的情况。我的排查方式是ÿ…...
[软件工程]十.可靠性工程(reliable engineering)
1.什么是可靠性工程 我们希望软件在给定的时间内,运行的时候不会崩溃或者发生失效,同时能保护我们的数据和个人信息。我们要能够信任我们所使用的软件,这意味着软件必须是可靠的。可靠性(reliability):系统…...
【Makefile】编译日志之输出重定向符号 >
用法1 make all >& compilelog.txt make all > compilelog.txt这两个编译命令在功能上有一些细微的区别,主要在于标准输出和标准错误的处理方式。 make all >& compilelog.txt 这个命令会将标准输出(stdout)和标准错误&a…...
linux之less
less命令是Linux系统中一个功能强大的文件查看工具,它允许用户分页查看文件内容,并提供了多种快捷键和选项来增强用户体验。以下是less命令的一些常用操作: 基本使用 查看文件使用less命令的基本语法是less [选项] [文件名]。例如࿰…...
算法-字符串-165.比较版本号
一、题目 二、思路解析 1.思路: 比较的是两个版本号它们以“.”作为分割的部分的有效值(即数值)是否一致 2.常用方法: 1.s.split("\\规则"),将字符串按参数规则进行分割并存储在字符串数组中 String[] str …...
List与Set、数组与ArrayList、ArrayList与LinkedList的区别
List 与 Set 的区别: 项ListSet重复允许重复的对象(多个null也可以)不允许重复的对象(null也只能有一个)有序性有序的。 保持了每个元素的插入顺序。即输出顺序就是输入顺序。 有序和无序都有。 HashSet:无…...
如何在 Odoo18 视图中添加关联数据看板按钮 | 免费开源ERP实施诀窍
文 / 开源智造 Odoo亚太金牌服务 引言 关联数据看板按钮乃是 Odoo 当中的一项强效功能,它容许用户顺遂地访问相关记录,或者直接从模型的表单视图施行特定操作。它们为用户给予了对重要信息的疾速访问途径,并简化了工作流程,由此…...
Linux下mysql环境的搭建
1.mysql的下载 去MySQL官网下载mysql的linux压缩包 MySQL :: Download MySQL Community Server 如果下载慢请到网盘中自行下载 通过网盘分享的文件:mysql-8.0.40-1.el7.x86_64.rpm-bundle.tar 链接: https://pan.baidu.com/s/1vUJ-VuTwer1nLPT-haQCqw?pwd6342 提…...
视觉语言模型 Qwen2-VL
视觉语言模型 Qwen2-VL flyfish from PIL import Image import requests import torch from torchvision import io from typing import Dict from transformers import Qwen2VLForConditionalGeneration, AutoTokenizer, AutoProcessor from modelscope import snapshot_dow…...
浅谈新能源汽车感应钥匙一键启动的步骤和特点
随着汽车智能化技术的发展,无钥匙启动系统还可以与其他智能系统进行集成,如智能车载系统、远程控制系统等。这使得车主可以通过智能手机等智能设备远程控制车辆的启动、解锁、上锁等操作,进一步提升了使用的便捷性和智能化水平。新能源汽车…...
鸿蒙ArkTS语言基础语法详解
文章目录 鸿蒙ArkTS语言基础语法详解一、引言二、ArkTS语言概述1. ArkTS语言特点2. TypeScript基础语法2.1 类型注解2.2 接口2.3 泛型2.4 类的继承2.5 类的访问修饰符 三、ArkTS的基本组成3.1 装饰器3.2 UI描述3.3 自定义组件3.4 系统组件3.5 属性方法和事件方法 四、自定义组件…...
H5游戏出海如何获得更多增长机会?
海外H5小游戏的崛起给了国内众多中小厂商出海发展的机会,开发者如何在海外市场获得更多的增长机会?#APP出海# H5游戏如何在海外获得核心用户? HTML5游戏的开发与运营者们首先可以利用量多质高的HTML5游戏,维持海外用户粘性&…...
网站右侧二维码/外贸独立站怎么建站
P3909 异或之积 题目描述 对于A_1,A_2,A_3,\cdots,A_NA1,A2,A3,⋯,AN,求 (6\times \sum_{i1}^N\sum_{ji1}^N\sum_{kj1}^N A_i\times A_j\times A_k)\ mod\ (10^97)(6∑i1N∑ji1N∑kj1NAiAjAk) mod (1097) 的值。 输入输出格式 输入格式…...
网站seo站外优化/网页设计可以自学吗
大家都知道网站对一个企业的网络营销和推广来说非常重要,现在越来越多的企业选择自助建站,最大优点的节约费用,没有建站经验也能做出一个功能强大,甚至比专业网站建设公司更专业的网站,自助建站分为自助建站系统和在线…...
wordpress多导航栏/广东近期新闻
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过。但在实际的生产环境中,由单台Mysql作为独立的数据库是完全不能满足实际需求的,无论是在安全…...
郑州网站推广地址/优化网站排名软件
过完五一,感觉整个人跟废了一样,虽然五一期间也没做什么,就是感觉累,感觉困。但无奈今天还有一堆事情等我去做。 早上来先发了一版v5.0.1,开启项目新版的第一次!但是毫无疑问,出了很多问题&…...
绿色系的网站/电商网页制作教程
在asp.net编程开发中,有时需要动态变换CSS,比如有的时候做个性化页面,可以这样做 1.<head> 2. <link id"MyStyleSheet" rel"stylesheet" type"text/css" runat"server" /> 3.<…...
wordpress设置可写/seopc流量排行榜企业
计算机网络 练习(一百四十二) 某网络拓扑图如下所示,若采用 RIP 协议,在路由器 Router2 上需要进行 RIP 声明的网络是() A. 仅网络 1 B. 网络 1、202.117.112.0/30 和 202.117.113.0/30 C. 网络 1、网络…...