一、分片策略详情

        在Mycat 基础_moneywenxue的博客-CSDN博客 这篇文章中我们已经实践过一部分分片测试,这一节我们在它的基础上作补充。

1.1 连续分片

1.1.1 范围分片(已演示)

1.1.2 按自然月分片

三个节点 imall 库创建 sharding_by_month 表(上节课的单库分表也是)

CREATE TABLE `sharding_by_month` (
`create_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 逻辑表——schema.xml:

<table name="sharding_by_month" dataNode="122-imall,123-imall,124-imall" rule="qs-sharding-by-month"/>

分片规则——rule.xml:

<tableRule name="qs-sharding-by-month"><rule><columns>create_time</columns><algorithm>qs-partbymonth</algorithm></rule>
</tableRule>

分片算法——rule.xml:

<function name="qs-partbymonth" class="io.mycat.route.function.PartitionByMonth"><property name="dateFormat">yyyy-MM-dd</property><property name="sBeginDate">2025-10-01</property><property name="sEndDate">2025-12-31</property>
</function>
  • columns 标识将要分片的表字段, 字符串类型, 与 dateFormat 格式一致。
  • algorithm 为分片函数。
  • dateFormat 为日期字符串格式。
  • sBeginDate 为开始日期。
  • sEndDate 为结束日期

注意: 节点个数要大于月份的个数

测试语句:

truncate table sharding_by_month;
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2024-10-16', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2025-10-27', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2026-11-04', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2027-11-11', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2029-12-25', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2030-12-31', database());

执行完情况:

10月份在imall_1节点;11月份在imall_2节点;12月份的在imall_3节点。

注意:以上跟年度没有关系,只跟月度有关。

问题:不在 10 月和 12 月之间的数据,路由到哪个节点?结果不一定。可以在本地调试一下。

另外还有按天分片(可以指定多少天一个分片)、按小时分片。

1.2 离散分片

1.2.1 十进制取模分片(已演示)

略。

1.2.2 枚举分片

        将所有可能出现的值列举出来,指定分片。例如:全国 34 个省,要将不同的省的数
据存放在不同的节点,可用枚举的方式。

1.2.3 一致性哈希

一致性 hash 有效解决了分布式数据的扩容问题。

建表语句:

CREATE TABLE `sharding_by_murmur` (
`id` int(10) DEFAULT NULL,
`db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

逻辑表——schema.xml:

<table name="sharding_by_murmur" primaryKey="id" dataNode="122-imall,123-imall,124-imall" rule="sharding-by-murmur" />

分片规则——rule.xml:

<tableRule name="qs-sharding-by-murmur"><rule><columns>id</columns><algorithm>qs-murmur</algorithm></rule>
</tableRule>

分片算法——rule.xml:

<function name="qs-murmur" class="io.mycat.route.function.PartitionByMurmurHash"><property name="seed">0</property><property name="count">3</property><property name="virtualBucketTimes">160</property>
</function>

测试语句(mycat库-imall):

truncate table sharding_by_murmur;
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (1, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (2, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (3, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (4, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (5, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (6, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (7, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (8, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (9, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (10, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (11, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (12, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (13, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (14, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (15, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (16, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (17, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (18, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (19, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (20, database());

测试结果: 

逻辑表:

 物理表节点:

 

特点:可以一定程度减少数据的迁移。

1.2.4 固定分片哈希

        这是先求模得到逻辑分片号,再根据逻辑分片号直接映射到物理分片的一种散列算法。

建表语句:

CREATE TABLE `sharding_by_long` (
`id` int(10) DEFAULT NULL,
`db_nm` varchar(20) DEFAULT NULL
) ;

逻辑表——schema.xml:

<table name="sharding_by_long" dataNode="122-imall,123-imall,124-imall" rule="qs-sharding-by-long" />

分片规则——rule.xml:

<tableRule name="qs-sharding-by-long"><rule><columns>id</columns><algorithm>qs-sharding-by-long</algorithm></rule>
</tableRule>

平均分成 8 片(%1024 的余数,1024=128*8):

<function name="qs-sharding-by-long" class="io.mycat.route.function.PartitionByLong"><property name="partitionCount">8</property><property name="partitionLength">128</property>
</function>
  • partitionCount 为指定分片个数列表。
  • partitionLength 为分片范围列表。

第二个例子(实践中是这个例子):
两个数组,分成不均匀的 3 个节点(%1024 的余数,1024=2*256+1*512):

<function name="qs-sharding-by-long" class="io.mycat.route.function.PartitionByLong"><property name="partitionCount">2,1</property><property name="partitionLength">256,512</property>
</function>

3 个节点,对 1024 取模余数的分布:

 测试语句:

truncate table sharding_by_long;
INSERT INTO `sharding_by_long` (id,db_nm) VALUES (222, database());
INSERT INTO `sharding_by_long` (id,db_nm) VALUES (333, database());
INSERT INTO `sharding_by_long` (id,db_nm) VALUES (666, database());

测试结果:

 mycat表:

物理表节点:

 

特点:在一定范围内 id 是连续分布的。

 1.2.5 取模范围分片(改完配置后,启动报错)

逻辑表-schema.xml:

<table name="sharding_by_pattern" primaryKey="id" dataNode="122-imall,123-imall,124-imall" rule="sharding-by-pattern" />

建表语句:

CREATE TABLE `sharding_by_pattern` (
`id` varchar(20) DEFAULT NULL,
`db_nm` varchar(20) DEFAULT NULL
) ;

分片规则——rule.xml:

<tableRule name="sharding-by-pattern"><rule><columns>id</columns><algorithm>sharding-by-pattern</algorithm></rule>
</tableRule>

分片算法——rule.xml:

<function name="sharding-by-pattern" class=" io.mycat.route.function.PartitionByPattern"><property name="patternValue">100</property><property name="defaultNode">0</property><property name="mapFile">partition-pattern.txt</property>
</function>

patternValue 取模基数,这里设置成 100
partition-pattern.txt,一共 3 个节点:

  1. id=19%100=19,在 dn1;
  2. id=222%100=22,dn2;
  3. id=371%100=71,dn3

 partitin-pattern.txt:

# id partition range start-end ,data node index
###### first host configuration
1-20=0
21-70=1
71-100=2
 

测试语句:

INSERT INTO `sharding_by_pattern` (id,db_nm) VALUES (19, database());
INSERT INTO `sharding_by_pattern` (id,db_nm) VALUES (222, database());
INSERT INTO `sharding_by_pattern` (id,db_nm) VALUES (371, database());

特点:可以调整节点的数据分布。

1.2.6 范围取模分片

建表语句:

CREATE TABLE `sharding_by_rang_mod` (
`id` bigint(20) DEFAULT NULL,
`db_nm` varchar(20) DEFAULT NULL
);

逻辑表——schema.xml:

<table name="sharding_by_rang_mod" dataNode="122-imall,123-imall,124-imall" rule="qs-sharding-by-rang-mod" />

分片规则——rule.xml:

<tableRule name="qs-sharding-by-rang-mod"><rule><columns>id</columns><algorithm>qs-rang-mod</algorithm></rule>
</tableRule>

分片算法——rule.xml:

<function name="qs-rang-mod" class="io.mycat.route.function.PartitionByRangeMod"><property name="mapFile">partition-range-mod.txt</property>
</function>

partition-range-mod.txt:

# range start-end ,data node group size
0-20000=1
20001-40000=2

        解读:先范围后取模。Id 在 20000 以内的,全部分布到 dn1。Id 在 20001-40000的,%2 分布到 dn2,dn3。

插入数据:

INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (666, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (6667, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (16666, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (21111, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (22222, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (23333, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (24444, database());

特点:扩容的时候旧数据无需迁移。

1.3 其他分片规则

  • 应用指定分片 PartitionDirectBySubString
  • 日期范围哈希 PartitionByRangeDateHash
  • 冷热数据分片 PartitionByHotDate
  • 也 可 以 自 定 义 分 片 规 则 : extends AbstractPartitionAlgorithm implements RuleAlgorithm

1.3.1 连续分片和离散分片的特点

连续分片优点:

  1. 范围条件查询消耗资源少(不需要汇总数据)
  2. 扩容无需迁移数据(分片固定)

连续分片缺点:

  1. 存在数据热点的可能性
  2. 并发访问能力受限于单一或少量 DataNode(访问集中)

离散分片优点:

  1. 并发访问能力增强(负载到不同的节点)
  2. 范围条件查询性能提升(并行计算)

离散分片缺点:

  1. 数据扩容比较困难,涉及到数据迁移问题
  2. 数据库连接消耗比较多

1.4 切分规则的选择

步骤:

  1. 找到需要切分的大表,和关联的表
  2. 确定分片字段(尽量使用主键),一般用最频繁使用的查询条件
  3. 考虑单个分片的存储容量和请求、数据增长(业务特性)、扩容和数据迁移问题。

例如:按照什么递增?序号还是日期?主键是否有业务意义?
一般来说,分片数要比当前规划的节点数要大。
总结:根据业务场景,合理地选择分片规则。

举例:
老师:3.7 亿的数据怎么分表?我是不是分成 3 台服务器?
1、一年内到达多少?两年内到达多少?(数据的增长速度)?
答:一台设备每秒钟往 3 张表各写入一条数据,一共 4 台设备。每张表一天
86400*4=345600 条。每张表一个月 10368000 条。
分析:增长速度均匀,可以用日期切分,每个月分一张表。

2、什么业务?所有的数据都会访问,还是访问新数据为主?
答:访问新数据为主,但是所有的数据都可能会访问到

3、表结构和表数据是什么样的?一个月消耗多少空间
 答:字段不多,算过了,三年数据量有 3.7 亿,30G。
分析:30G 没必要分库,浪费磁盘空间。

4、访问量怎么样?并发压力大么?
答:并发有一点吧
分析:如果并发量不大,不用分库,只需要在单库分表。不用引入 Mycat 中间件
了。如果要自动路由的话可以用 Sharding-JDBC,否则就是自己拼装表名。

5、3 张表有没有关联查询之类的操作?
答:没有。
分析:还是拼装表名简单一点。
如果从单库变成分库分表,或者节点数的增加和减少,都会涉及到数据迁移的问
题。数据迁移有两种,一种是在线不停机的迁移,还有一种是停机的。

二、Mycat 扩缩容

2.1 在线扩缩容思路

在线扩容的流程:

  1. 把历史数据,通过中间件迁移到新库
  2. 新的写请求,发送到消息队列,不消费
  3. 数据迁移完毕,迁移程序下线
  4. 消费消息,将增量数据写入新库
  5. 数据一致性验证
  6. 旧数据库下线,切换到新库,重启应用

         如果数据已经超过了单个节点的存储上线,或者需要下线节点的时候,就需要对数
据重新分片。

2.2 mysqldump 方式

系统第一次上线,把单张表迁移到 Mycat,可以用 mysqldump。

MySQL 导出:

mysqldump -uroot -p123456 -h127.0.0.1 -P3306 -c -t --skip-extended-insert imall > mysql-1107.sql
  • -c 代表带列名
  • -t 代表只要数据,不要建表语句
  • --skip-extended-insert 代表生成多行 insert(mycat childtable 不支持多行插入ChildTable multi insert not provided)

Mycat 导入:

mysql -uroot -p123456 -h127.0.0.1 -P8066 imall < mysql-1107.sql

 2.3 Mycat 自带的离线扩缩容工具

如果是已有分片表,可以用 mycat 自带的工具,实际上是对 mysqldump 进行了包
装。

笔者也按照步骤做了一遍,但是报错了,也不知道是因为我是window版本的mycat,还是哪些配置没配对,报错了,报错内容如下:

虽然没操作成功,但是我步骤也贴上来:Mycat生产实践---数据迁移与扩容实践_蓑衣客的博客-CSDN博客

 2.3.1 准备工作

  1. mycat 所在环境安装 mysql 客户端程序。
  2.  mycat 的 lib 目 录 下 添 加 mysql 的 jdbc 驱 动 包 ( 例 如mysql-connector-java-5.1.27.jar)。
  3. 对扩容缩容的表所有节点数据进行备份,以便迁移失败后的数据恢复。

2.3.2 步骤

以取模分片表 sharding-by-mod 缩容为例。

  1. 复制 schema.xml、rule.xml 并重命名为 newSchema.xml、newRule.xml 放于 conf 目录下。
  2. 修改 newSchema.xml 和 newRule.xml 配置文件为扩容缩容后的 mycat 配置参数(表的节点数、数据源、路由规则)。

注意:
只有节点变化的表才会进行迁移。仅分片配置变化不会迁移。

newSchema.xml:

<table name="sharding_by_mod" dataNode="122-imall,123-imall,124-imall" rule="qs-sharding-by-mod" />

改成(减少了一个节点):

<table name="sharding_by_mod" dataNode="122-imall,123-imall" rule="qs-sharding-by-mod" />

newRule.xml 修改 count 个数:

<function name="qs-sharding-by-mod-long" class="io.mycat.route.function.PartitionByMod">
<property name="count">2</property>
</function>

3、修改 conf 目录下的 migrateTables.properties 配置文件,告诉工具哪些表需
要进行扩容或缩容,没有出现在此配置文件的 schema 表不会进行数据迁移,格式:

注意,

1)不迁移的表,不要修改 dn 个数,否则会报错。
2)ER 表,因为只有主表有分片规则,子表不会迁移

imall=sharding-by-mod

 4、dataMigrate.sh 中这个必须要配置

通 过 命 令 "find / -name mysqldump" 查 找 mysqldump 路 径 为
"/usr/bin/mysqldump",指定#mysql bin 路径为"/usr/bin/"

#mysql bin 路径
RUN_CMD="$RUN_CMD -mysqlBin= /usr/bin/"

5、停止 mycat 服务

6、执行执行 bin/dataMigrate.sh 脚本
注意:必须要配置 Java 环境变量,不能用 openjdk

7、脚本执行完成,如果最后的数据迁移验证通过,就可以将之前的 newSchema.xml
和 newRule.xml 替换之前的 schema.xml 和 rule.xml 文件,并重启 mycat 即可。

 

注意事项:

  1. 保证分片表迁移数据前后路由规则一致(取模——取模)。
  2. 保证分片表迁移数据前后分片字段一致。
  3. 全局表将被忽略。
  4. 不要将非分片表配置到 migrateTables.properties 文件中。
  5. 暂时只支持分片表使用 MySQL 作为数据源的扩容缩容。migrate 限制比较多,还可以使用 mysqldump。

总结:离线或者在线,主要看数据量,和对于业务的影响程度决定。

三、MySQL 主从复制

        上一节课我们已经用 mycat 实现了 MySQL 数据的分片存储,第一个可以实现负载
均衡,不同的读写发生在不同的节点上。第二可以实现横向扩展,如果数据持续增加,
加机器就 OK 了。
        当然,一个分片只有一台机器还不够。为了防止节点宕机或者节点损坏,都要用副
本机制来实现。MySQL 数据库同样可以集群部署,有了多个节点之后,节点之间数据又
是个大问题。
        这里我们来学习一下 MySQL 是怎么实现节点数据同步的。

MySQL 主从复制配置:

https://gper.club/articles/7e7e7f7ff3g5bgc3g6c

3.1 主从复制的含义

        在 MySQL 多服务器的架构中,主节点,也就是产生数据的节点叫 master 节点。其
他的副本,向主节点同步数据的节点,叫做 slave(默认是异步的,客户端的数据在 master
刷盘就返回)。一个集群里面至少要有一个 master。slave 可以有多个。

3.2 主从复制的用途

  1. 数据备份:把数据复制到不同的机器上,以免单台服务器发生故障时数据丢失。
  2. 负载均衡:结合负载的机制,均摊所有的应用访问请求,降低单机 IO。
  3. 高可用 HA:当节点故障时,自动转移到其他节点,提高可用性。

主从复制的架构可以有多种。

3.3 主从复制的形式

一主一从/一主多从:

双主复制(互为主从):

级联复制:

        不过在,MySQL 自身并没有自动选举和故障转移的功能,需要依赖其他的中间件或
者架构实现,比如 MMM,MHA,percona,mycat。
        主从复制是怎么实现的呢?

3.4 binlog

        客户端对 MySQL 数据库进行操作的时候,包括 DDL 和 DML 语句,服务端会在日志文件中用事件的形式记录所有的操作记录,这个文件就是 binlog 文件(属于逻辑日志,、跟 Redis 的 AOF 文件类似)。Binary log,二进制日志。

基于 binlog,我们可以实现主从复制和数据恢复。

binlog 默认是不开启的,需要在服务端手动配置。注意有一定的性能损耗。

3.4.1 binlog 配置

编辑 /etc/my.cnf:

log-bin=/var/lib/mysql/mysql-bin
server-id=1

重启 MySQL 服务:

service mysqld stop
service mysqld start
## 如果出错查看日志
vi /var/log/mysqld.log
cd /var/lib/my

是否开启 binlog

show variables like 'log_bin%'; 

3.4.2 binlog 格式

  • STATEMENT:记录每一条修改数据的 SQL 语句(减少日志量,节约 IO)。
  • ROW:记录哪条数据被修改了,修改成什么样子了(5.7 以后默认)。
  • MIXED:结合两种方式,一般的语句用 STATEMENT,函数之类的用 ROW。

查看 binlog 格式:

show global variables like '%binlog_format%';

Binlog 文件超过一定大小就会产生一个新的,查看 binlog 列表:

show binary logs;

大小:

show variables like 'max_binlog_size';

查看 binlog 内容:

show binlog events in 'mysql-bin.000001'; 

用 mysqlbinlog 工具,基于时间查看 binlog
(注意这个是 Linux 命令, 不是 SQL)

/usr/bin/mysqlbinlog --start-datetime='2025-08-22 13:30:00' --stop-datetime='2025-08-22 14:01:01' -d gupao
/var/lib/mysql/mysql-bin.000001

 3.5 主从复制原理

3.5.1 主从复制配置

1、主库开启 binlog,设置 server-id

这一步查看:3.4.1 binlog 配置

2、在主库创建具有复制权限的用户,允许从库连接

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'192.168.44.128' IDENTIFIED
BY '123456';
FLUSH PRIVILEGES;

3、从库/etc/my.cnf 配置,重启数据库

server-id=2
log-bin=mysql-bin
relay-log=mysql-relay-bin
read-only=1
log-slave-updates=1

        开启 log-slave-updates 参数后,从库从主库复制的数据会写入 log-bin 日志文件里,这样可以实现互为主备或者级联复制(它自己也可以作为一个 master 节点)。

4、在从库执行

stop slave;
change master to
master_host='192.168.44.121',master_user='repl',master_password='123456',master_log_file='mysql-bin.00000
1', master_log_pos=4;
start slave;

5、查看同步状态

SHOW SLAVE STATUS;

Slave_IO_Running 和 Slave SQL Running 都为 yes 为正常。

3.5.2 主从复制原理

这里面涉及到几个线程:

  1.  slave服务器执行start slave,开启主从复制开关,slave 服务器的 IO 线程请求从 master 服务器读取 binlog(如果该线程追赶上了主库,会进入睡眠状态)
  2. master服务器创建Log Dump线程,把binlog发送给slave服务器。slave 服务器把读取到的 binlog 日志内容写入中继日志 relay log(会记录位置信息,以便下次继续读取)。
  3. slave 服务器的 SQL 线程会实时检测 relay log 中新增的日志内容,把 relay log解析成 SQL 语句,并执行。

为什么需要 relay log?为什么不把接收到的 binlog 数据直接写入从库?

——Relay log 相当于一个中转站,也记录了 master 和 slave 的同步信息。

3.5.3 mycat 读写分离的实现

添加

<dataHost name="host122" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="hostM1" url="192.168.44.122:3306" user="root"password="123456"><readHost host="hostS1" url="192.168.44.129:3306" user="root" password="123456" /></writeHost>
</dataHost>

balance:负载的配置,决定 select 语句的负载

作用
0不开启读写分离机制, 所有读操作都发送到当前可用的 writeHost 上。
1所有读操作都随机发送到当前的 writeHost 对应的 readHost 和备用的 writeHost
2所有的读操作都随机发送到所有的 writeHost,readHost 上
3所有的读操作都只发送到 writeHost 的 readHost 上

writeType:读写分离的配置,决定 update、delete、insert 语句的负载

作用
0所有写操作都发送到可用的 writeHost 上(默认第一个, 第一个挂了以后发到第二个)
1所有写操作都随机的发送到 writeHost

switchType:主从切换配置

作用
-1表示不自动切换
1默认值, 表示自动切换
2基于 MySQL 主从同步的状态决定是否切换,心跳语句为 show slave status
3基于 MySQL galera cluster 的切换机制(适合集群) (1.4.1), 心跳语句为 show status like 'wsrep%'。

四、Mycat 注解

4.1 注解的作用

当关联的数据不在同一个节点的时候,Mycat 是无法实现跨库 join 的。

举例:
如果直接在 122-imall 插入主表数据,123-imall 插入明细表数据(本来应该在 122),此时关联查询无法查询出来。

模拟mycat ER分片不在同一节点不能链表查询的情况:

-- 122 节点插入
INSERT INTO `order_info` (`order_id`, `uid`, `nums`, `state`, `create_time`, `update_time`) VALUES (9,
1000003, 3, 1, '2019-9-25 11:35:49', '2019-9-25 11:35:49');
​
-- 123 节点插入
INSERT INTO `order_detail` (`order_id`, `id`, `goods_id`, `price`, `is_pay`, `is_ship`, `status`) VALUES (9,
20250001, 85114752, 19.99, 1, 1, 1);

在 mycat 数据库查询,直接查询没有结果:

select a.order_id,b.goods_id from order_info a, order_detail b where a.order_id = b.order_id;

        Mycat 作为一个中间件,有很多自身不支持的 SQL 语句,比如存储过程,但是这些
语句在实际的数据库节点上是可以执行的。有没有办法让 Mycat 做一层透明的代理转发,
直接找到目标数据节点去执行这些 SQL 语句呢?
        那我们必须要有一种方式告诉 Mycat 应该在哪个节点上执行。这个就是 Mycat 的注
解。我们在需要执行的 SQL 语句前面加上一段代码,帮助 Mycat 找到我们的目标节点。

4.2 注解的用法

注解的形式是 :

/*!mycat: sql=注解 SQL 语句*/

注解的使用方式是 :

/*!mycat: sql=注解 SQL 语句*/ 真正执行的 SQL

使用时将 = 号后的 "注解 SQL 语句" 替换为需要的 SQL 语句即可。

注解中的语句有一些限制,或者注意的地方:

原始 SQL注解 SQL
select如果需要确定分片, 则使用能确定分片的注解, 比如/*!mycat: sql=select * from users where
user_id=1*/
如果要在所有分片上执行则可以不加能确定分片的条件
insert使用 insert 的表作为注解 SQL, 必须能确定到某个分片
原始 SQL 插入的字段必须包括分片字段
非分片表(只在某个节点上) : 必须能确定到某个分片
delete使用 delete 的表作为注解 SQL
update使用 update 的表作为注解 SQL

        使用注解并不额外增加 MyCat 的执行时间;从解析复杂度以及性能考虑,注解SQL 应尽量简单,因为它只是用来做路由的。

        注解可以帮我们解决什么问题呢?

4.3 注解使用示例

4.3.1 多表 ShareJoin

注意(表里面必须有三个节点的数据)

https://gper.club/articles/7e7e7f7ff7g59gc1g68

注意, 跨库关联查询使用是有限制的。

/*!mycat:catlet=io.mycat.catlets.ShareJoin */
select a.order_id,b.goods_id from order_info a, order_detail b where a.order_id = b.order_id;

4.3.2 DDL 或存储过程

customer.id=1 全部路由到 122

-- 表
/*!mycat: sql=select * from customer where id =1 */ CREATE TABLE test2(id INT);
​
-- 存储过程
/*!mycat: sql=select * from customer where id =1 */ CREATE PROCEDURE test_proc() BEGIN END ;

4.3.3 特殊语句自定义分片

Mycat 本身不支持 insert select,通过注解支持。

122-imall 创建测试表:

CREATE TABLE `test2` (
`id` int(11) NOT NULL,
PRIMARY KEY (`id`)
);

【先确认 order_detail 表有数据】

INSERT INTO `order_info` (`order_id`, `uid`, `nums`, `state`, `create_time`, `update_time`) VALUES (1,
1000001, 1, 2, '2025-9-23 14:35:37', '2025-9-23 14:35:37');
INSERT INTO `order_info` (`order_id`, `uid`, `nums`, `state`, `create_time`, `update_time`) VALUES (2,
1000002, 1, 2, '2025-9-24 14:35:37', '2025-9-24 14:35:37');
INSERT INTO `order_info` (`order_id`, `uid`, `nums`, `state`, `create_time`, `update_time`) VALUES (3,
1000003, 3, 1, '2025-9-25 11:35:49', '2025-9-25 11:35:49');
INSERT INTO `order_detail` (`order_id`, `id`, `goods_id`, `price`, `is_pay`, `is_ship`, `status`) VALUES (3,
20180001, 85114752, 19.99, 1, 1, 1);
INSERT INTO `order_detail` (`order_id`, `id`, `goods_id`, `price`, `is_pay`, `is_ship`, `status`) VALUES (1,
20180002, 25411251, 1280.00, 1, 1, 0);
INSERT INTO `order_detail` (`order_id`, `id`, `goods_id`, `price`, `is_pay`, `is_ship`, `status`) VALUES (1,
20180003, 62145412, 288.00, 1, 1, 2);
INSERT INTO `order_detail` (`order_id`, `id`, `goods_id`, `price`, `is_pay`, `is_ship`, `status`) VALUES (2,
20180004, 21456985, 399.00, 1, 1, 2);
INSERT INTO `order_detail` (`order_id`, `id`, `goods_id`, `price`, `is_pay`, `is_ship`, `status`) VALUES (2,
20180005, 21457452, 1680.00, 1, 1, 2);
INSERT INTO `order_detail` (`order_id`, `id`, `goods_id`, `price`, `is_pay`, `is_ship`, `status`) VALUES (2,
20180006, 65214789, 9999.00, 1, 1, 3);
/*!mycat: sql=select * from customer where id =1 */ INSERT INTO test2(id) SELECT id FROM order_detail;

4.3.4 读写分离

        读写分离 : 配置 Mycat 读写分离后,默认查询都会从读节点获取数据,但是有些场
景需要获取实时数据,如果从读节点获取数据可能因延时而无法实现实时,Mycat 支持
通过注解 /*balance*/ 来强制从写节点(write host)查询数据。

/*balance*/ select a.* from customer a where a.id=6666;

4.3.5 读写分离数据库选择( 1.6 版本之后)

/*!mycat: db_type=master */ select * from customer;
/*!mycat: db_type=slave */ select * from customer;
/*#mycat: db_type=master */ select * from customer;
/*#mycat: db_type=slave */ select * from customer;

注解支持的'! '不被 mysql 单库兼容
注解支持的'#'不被 MyBatis 兼容
随着 Mycat 的开发,更多的新功能正在加入。

4.4 注解原理

        Mycat 在执行 SQL 之前会先解析 SQL 语句,在获得分片信息后再到对应的物理节
点上执行。如果 SQL 语句无法解析,则不能被执行。如果语句中有注解,则会先解析注
解的内容获得分片信息,再把真正需要执行的 SQL 语句发送到对应的物理节点上。
所以我们在使用注解的时候,应该清楚地知道目标 SQL 应该在哪个节点上执行,注
解的 SQL 也指向这个分片,这样才能使用。如果注解没有使用正确的条件,会导致原始
SQL 被发送到所有的节点上执行,造成数据错误。

五、XA 分布式事务

        作为一个服务端的软件,或者说一个伪装成 MySQL 数据库的代理层,怎么实现
对分布式事务的支持呢?

        我们看到 Mycat 的官方介绍,从 1.6.5 版本开始支持 XA 分布式事务。XA 是一
种两阶段提交的实现
,我们先看看什么是两阶段提交。

5.1 二阶段提交

所谓的二阶段提交分为两个阶段:

  1. 准备prepare阶段
  2. 提交commit阶段

第一阶段分为两个步骤: 

  1. 事务管理器通知参与该事务的各个资源管理器,通知他们准备事务。
  2. 资源管理器接收到消息后开始准备阶段,写好事务日志(redo undo)并执行日志,但不提交。然后将是否就绪的消息返回给事务管理器(此时已经将事务的大部分事情做完,以后的操作耗时极小)。

第二阶段也分为两个步骤:

  1. 事务管理器在接受各个消息后,开始分析,如果有任意数据库失败,则发送回滚命令,否则发送提交命令。
  2. 各个资源管理器接收到命令后,执行(耗时很少),并将提交消息返回给事务管理器。

事务管理器接受消息后,事务结束,应用程序继续执行。

        为什么要分两步执行?
        
一是因为分两步,就有了事务管理器统一管理的机会;二尽可能晚地提交事务,让事务在提交前尽可能地完成所有能完成的工作,这样,最后的提交阶段将是耗时极短,耗时极短意味着操作失败的可能性也就降低。

5.2 XA 规范

        在 XA 的分布式事务处理模型里面涉及到三个角色 AP(应用程序)、RM(数据
库)、TM(事务管理器)

  • AP 定义事务的开始和结束,访问事务内的资源。
  • RM 除了数据库之外,还可以是其他的系统资源,比如文件系统,打印机服务器。
  • TM 负责管理全局事务,分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚、失败恢复等,是一个协调者的角色,可能是程序或者中间件。

        XA 协议主要规定了了 TM 与 RM 之间的交互。

        注意:通过实现 XA 的接口,只是提供了对 XA 分布式事务的支持,并不是说数
据库本身有分布式事务的能力。

5.3 MySQL 对 XA 的支持

        XA 是一种两阶段提交的实现。数据库本身必须要提供被协调的接口,比如事务
开启,准备,事务结束,事务提交,事务回滚。

https://dev.mysql.com/doc/refman/5.7/en/xa.html

MySQL 单节点运行 XA 事务演示:

use gupao;
​
-- 开启 XA 事务
xa start 'xid';
​
-- 插入数据
insert into teacher(tid,tname,tcid) values(100,'qingshan',1);
​
-- 结束一个 XA 事务
xa end 'xid';
-- 准备提交
xa prepare 'xid';
​
-- 列出所有处于 PREPARE 阶段的 XA 事务
xa recover
-- 提交
xacommit'xid';

工程:ssm-mycat,代码:com.qingshan.xa.XaTest:

package com.qingshan.xa;import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlXid;
import javax.sql.XAConnection;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.sql.Connection;
import java.sql.Statement;public class XaTest {public static MysqlXADataSource getDataSource(String connStr, String user, String pwd) {try {MysqlXADataSource ds = new MysqlXADataSource();ds.setUrl(connStr);ds.setUser(user);ds.setPassword(pwd);return ds;} catch (Exception e) {e.printStackTrace();}return null;}public static void main(String[] arg) {String connStr1 = "jdbc:mysql://localhost:3306/imall_1";String connStr2 = "jdbc:mysql://localhost:3306/imall_2";try {//从不同数据库获取数据库数据源MysqlXADataSource ds1 = getDataSource(connStr1, "root", "123456");MysqlXADataSource ds2 = getDataSource(connStr2, "root", "123456");//数据库1获取连接XAConnection xaConnection1 = ds1.getXAConnection();XAResource xaResource1 = xaConnection1.getXAResource();Connection connection1 = xaConnection1.getConnection();Statement statement1 = connection1.createStatement();//数据库2获取连接XAConnection xaConnection2 = ds2.getXAConnection();XAResource xaResource2 = xaConnection2.getXAResource();Connection connection2 = xaConnection2.getConnection();Statement statement2 = connection2.createStatement();//创建事务分支的xidXid xid1 = new MysqlXid(new byte[] { 0x01 }, new byte[] { 0x02 }, 100);Xid xid2 = new MysqlXid(new byte[] { 0x011 }, new byte[] { 0x012 }, 100);try {//事务分支1关联分支事务sql语句xaResource1.start(xid1, XAResource.TMNOFLAGS);int update1Result = statement1.executeUpdate("update order_info set nums=2674 where order_id=3");xaResource1.end(xid1, XAResource.TMSUCCESS);//事务分支2关联分支事务sql语句xaResource2.start(xid2, XAResource.TMNOFLAGS);int update2Result = statement2.executeUpdate("update order_info set nums=2674 where order_id=1");xaResource2.end(xid2, XAResource.TMSUCCESS);// 两阶段提交协议第一阶段int ret1 = xaResource1.prepare(xid1);int ret2 = xaResource2.prepare(xid2);// 两阶段提交协议第二阶段if (XAResource.XA_OK == ret1 && XAResource.XA_OK == ret2) {xaResource1.commit(xid1, false);xaResource2.commit(xid2, false);System.out.println("reslut1:" + update1Result + ", result2:" + update2Result);}} catch (Exception e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}}}

记住流程,帮助我们理解xa二段提交,实际开发不会用这个。

5.4 MyCAT 代码实现(重要)

package com.qingshan.xa;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;/*** @author Qian* @Since JDK1.8* @Date 2021/10/27 22:31*/
public class MyCATXAClientDemo {public static void main(String[] args) throws ClassNotFoundException, SQLException {// 1. 获得数据库连接Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:8066/imall", "root", "root");conn.setAutoCommit(false);// 2. 开启 MyCAT XA 事务conn.prepareStatement("set xa=on").execute();// 3. 插入 SQL// 3.1 SQL1 A库String sql1 = String.format("update order_info set nums=%d where order_id=%d", 2675, 3);conn.prepareStatement(sql1).execute();// 3.2 SQL2 B库String sql2 = String.format("update order_info set nums=%d where order_id=%d", 2675, 1);conn.prepareStatement(sql2).execute();// 4. 提交 XA 事务conn.commit();}
}
  • set xa=on MyCAT 开启 XA 事务。
  • conn.commit 提交 XA 事务。

MyCAT XA分布式事务_weixin_34253539的博客-CSDN博客

 下面是springboot支持分布式事务的链接,不涉及mycat,也不是xa:

SpringBoot+Mybatis+atomikos实现动态切换数据源+分布式事务_有趣的灵魂_不世俗的心的博客-CSDN博客

5.5 Mycat 中分布式事务的实现

分布式事务实战--一个完整的xa例子 - dongfuye - 博客园

Mycat 在 1.6.5 版本以后已经完全支持 XA 分布式强事务类型了。

对前端是资源管理器,对后端是事务管理器。

Mycat 中 XA 的用法:

用户应用侧(AP)的使用流程如下:

  1. set autocommit=0 --在应用层需要设置事务不能自动提交;注意 XA 事务和本地事务是冲突的。
  2. set xa=on --在 SQL 中设置 XA 为开启状态;
  3. 执行 SQL
  4. commit 或者 rollback,对事务进行提交(提交成功或者回滚异常)。
     

第三步如下: 

INSERT INTO`customer`(`id`,`name`)VALUES(6667,'赵先生');
INSERT INTO`customer`(`id`,`name`)VALUES(7778,'钱先生');
INSERT INTO`customer`(`id`,`name`)VALUES(16667,'孙先生');

 流程图如下:

 在这里 mycat 起到了事务协调者的角色。

不过 XA 两阶段提交存在一些问题:

  1. 同步阻塞问题。资源是锁定的。
  2. 事务管理器不能挂。
  3. 数据一致性问题:如果部分参与者没有收到 commit,事务不会提交。

其他的分布式实现方案,参考微服务架构-Spring Cloud Alibaba-分布式事务,后续再研究。

最后我们来看一下 Mycat 的原理。它是怎么帮我们实现分库分表和解决相关的问题的。

六、核心流程总结

 官网的架构图:

 6.1 启动

  1. MycatServer 启动,解析配置文件,包括服务器、分片规则等
  2. 创建工作线程,建立前端连接和后端连接

6.2 执行 SQL

  1. 前端连接接收 MySQL 命令
  2. 解析 MySQL,Mycat 用的是 Druid 的 DruidParser
  3. 获取路由
  4. 改写 MySQL,例如两个条件在两个节点上,则变成两条单独的 SQL。

    例如 select * from travelrecord where id in(5000001, 10000001);

    改写成:
    select * from travelrecord where id = 5000001;(dn2 执行)
    select * from travelrecord where id = 10000001;(dn3 执行)
    又比如多表关联查询,先到各个分片上去获取结果,然后在内存中计算
  5. 与后端数据库建立连接
  6. 发送 SQL 语句到 MySQL 执行
  7. 获取返回结果
  8. 处理返回结果,例如排序、计算等等
  9. 返回给客户端

6.3 源码下载与调试环境搭建(了解)

6.3.1 下载源代码, 导入工程

git clone https://github.com/MyCATApache/Mycat-Server

6.3.2 配置

schema.xml 放在:src\main\resources

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/"><schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100"><table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /><table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /><table name="hotnews" primaryKey="ID" autoIncrement="true"dataNode="dn1,dn2,dn3" rule="mod-long" /></schema>
​<dataNode name="dn1" dataHost="localhost1" database="db1" /><dataNode name="dn2" dataHost="localhost1" database="db2" /><dataNode name="dn3" dataHost="localhost1" database="db3" /><dataHost name="localhost1" maxCon="20" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="hostM1" url="127.0.0.1:3306" user="root"password="123456"></writeHost></dataHost>
</mycat:schema>

6.3.3 表结构

本地数据库创建 db1、db2、db3 数据库:

create database db1;
create database db2;
create database db3;

全部执行建表脚本:

CREATE TABLE `company` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(64) DEFAULT '',
`market_value` bigint(20) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
​
CREATE TABLE `hotnews` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(64) DEFAULT '',
`content` varchar(512) DEFAULT '0',
`time` varchar(8) DEFAULT '',
`cat_name` varchar(10) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
​
CREATE TABLE `travelrecord` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`city` varchar(32) DEFAULT '',
`time` varchar(8) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

6.3.4 逻辑表配置

travelrecord 表,根据 id 范围分片:

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />

travelrecord 表分片规则:

<tableRule name="auto-sharding-long"><rule><columns>id</columns><algorithm>rang-long</algorithm></rule>
</tableRule>

travelrecord 表分片算法:

<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong"><property name="mapFile">autopartition-long.txt</property>
</function>

autopartition-long.txt:

1-10000=0
10000-20000=1
20000-30000=2

hotnews 表,根据 id 取模分片,模以 3:

<table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"         rule="mod-long"/>
<tableRule name="mod-long"><rule><columns>id</columns><algorithm>mod-long</algorithm></rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes --><property name="count">3</property>
</function>

company 表,全局表,没有分片规则:

<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />

6.3.5 debug 方式启动

debug 方式启动 main 方法
\src\main\java\io\mycat\MycatStartup.java

6.3.6 连接本机 Mycat 服务测试

测试语句:

-- 范围分片
insert into travelrecord(`id`, `city`, `time`) values(1, '长沙', '20251020');
​
-- 取模分片
insert into hotnews(`id`, `title`, `content`) values(1,'咕泡', '盆鱼宴');
​
-- 全局表
insert into company(`name`, `market_value`) values('spring', 100);

6.3.7 调试入口

连接入口:
io.mycat.net.NIOAcceptor#accept
SQL 入口:
io.mycat.server.ServerQueryHandler#query

调试 DDL:

truncate table travelrecord;

普通 Select,这三条语句的路由都不一样:

select * from hotnews where id =1;
select * from hotnews where id =2;
select * from hotnews where id =3;

insert:

insert into travelrecord(`id`, `city`, `time`) values(10000, '长沙', '20251020');
insert into travelrecord(`id`, `city`, `time`) values(20000, '长沙', '20251020');
insert into travelrecord(`id`, `city`, `time`) values(30000, '长沙', '20251020');

Step Out(Shift+F8)可以看到上一层的调用。

七、Mycat 高可用

目前 Mycat 没有实现对多 Mycat 集群的支持。集群之前最麻烦的是数据同步和选举。
可以暂时使用 HAProxy+Keepalived 实现。
参考:https://gper.club/articles/7e7e7f7ff3g5bgc5g6c
HAProxy+Keepalived 搭建 RabbitMQ 高可用集群。

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

相关文章

  1. Django学习笔记第三篇:Django之视图层笔记

    1.视图函数 一个视图函数&#xff0c;简称视图&#xff0c;是一个简单的Python 函数&#xff0c;它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容&#xff0c;一个重定向&#xff0c;一个404错误&#xff0c;一个XML文档&#xff0c;或者一张图片. . . 是任何东西…...

    2024/4/20 13:44:30
  2. 在谈回溯全排列思想

    这里采用&#xff0c;方格填数法&#xff0c;与数学排列组合方法相同。需要借助O(N)的空间标记已经选择过的数&#xff0c;但最容易理解。 class Solution { private:vector<int> vis;vector<vector<int>> res; public:vector<vector<int>> per…...

    2024/5/1 11:40:07
  3. Android为什么要用xml描述界面

    XML可以使程序的内容和结构完全分离,可以实现内容管理和流程管理的彻底分离,降低开发耦合度,更便于项目的管理。 而且XML具有统一的标准语法,任何系统和产品所支持的XML文档,都具有统一的格式和语法,有利于跨平台移植,可扩展性强。 用Swing这样的模式, 耦合度高,相比X…...

    2024/5/1 9:09:23
  4. 数据埋点流程、设计以及案例

    作为数据分析师的你&#xff0c;是否和我一样经常会被业务方拿着两个不同数据平台的报表数据进行灵魂拷问。下面的场景你应该在熟悉不过了。 情景1 一场拉新促活的活动之后&#xff0c;运营拿着两个不同团队维护的报表数据来问我&#xff0c;为什么两份报表统计出来的日活跃用…...

    2024/4/21 17:51:41
  5. 【算法笔记题解】第四章排序的题解

    文章目录 前言 题目描述 1083 List Grades (25 分)https://pintia.cn/problem-sets/994805342720868352/problems/994805383929905152 输入描述 输出描述 输入示例 输出示例 解题思路 题目理解 代码实现 结果分析与总结 前言 昨天刷的那个被牛客网坑了一把&#xff…...

    2024/4/21 17:51:41
  6. IOC(概念和原理)

    1.什么是IOC &#xff08;1&#xff09;控制反转&#xff0c;把对象的创建和对象之间的调用过程&#xff0c;交给Spring管理 &#xff08;2&#xff09;使用IOC的目的&#xff1a;降低耦合度 &#xff08;3&#xff09;做入门案例就是IOC实现 2.IOC底层原理 &#xff08;1&a…...

    2024/4/21 17:51:39
  7. KW_VMware安装及虚拟网络模式详解

    https://pan.baidu.com/s/1Z_v9z6P3bZT2RZ1u1vF0PA p1qa v8...

    2024/4/28 9:13:26
  8. 【Leetcode刷题】121. 买卖股票的最-佳时机

    题目 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大…...

    2024/4/21 17:51:37
  9. letcode-Z字变形

    题目 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1a; 之后&#xff0c;你的输出需要从左往右逐行读取&#xff0c;产生出一个新的字符串&…...

    2024/4/21 17:51:36
  10. React-Class-Component-lifecycle

    react 类组件生命周期 &#xff1a; 阶段&#xff1a; 挂载、更新、卸载 不同阶段 需要做不同的事情&#xff08;状态初始化、this 批量绑定、网络数据请求、DOM操作...&#xff09; 在不同阶段 不同的钩子函数里面去做 constructor UNSAFE_componentWillMount() 第一次组…...

    2024/4/21 17:51:35
  11. 多智能体强化学习之QMIX

    论文&#xff1a;QMIX: Monotonic Value Function Factorisation for Deep Multi-Agent Reinforcement Learning 参考博客&#xff1a;多智能体强化学习入门&#xff08;五&#xff09;——QMIX算法分析、多智能体强化学习入门QMIX 参考书籍&#xff1a;《深度强化学习学术前沿…...

    2024/4/21 17:51:34
  12. git命令代码及作用

    查看自己的用户名和邮箱地址&#xff1a; $ git config user.name $ git config user.email 修改自己的用户名和邮箱地址&#xff1a; $ git config --global user.name “xxx” $ git config --global user.email “xxx” 下载git及小乌龟 新的改变 我们对Markdown编辑…...

    2024/4/21 17:51:34
  13. Postman这样用更香

    Postman是一个功能强大的接口测试工具&#xff0c;不仅可以调用http接口也可以发送https请求&#xff0c;满足日常测试工作的需求。 一、下载 官网&#xff1a;https://www.postman.com 1.选择需要下载的版本号 2.双击下载的安装包&#xff0c;进入到用户登录和注册的页面 若…...

    2024/4/21 17:51:33
  14. Redis学习笔记(主要命令)

    Redis&#xff1a; 概念&#xff1a; redis是一款高性能的NOSQL系列的非关系型数据库 是键值(Key-Value)存储数据库&#xff0c;数据模型&#xff1a; 一系列键值对。 Redis支持的键值数据类型如下&#xff1a; 字符串类型 string 存储&#xff1a;set key value 获取&#x…...

    2024/4/20 13:44:45
  15. 数据库 ER图、关系模式相互转换

    ER图->关系模式...

    2024/4/20 13:44:43
  16. laravel的mysql的分表及分表联查解决方案

    0X00 问题初现 php的laravel如何实现水平分表&#xff1f;最近手里有个项目&#xff0c;框架使用php的laravel7框架&#xff0c;由于数据量激增&#xff0c;当时为了快速迭代开发的详情表现在一晚上就干出30万行的数据量&#xff0c;主表已经一千两百万的数据。因为这只是用来…...

    2024/4/20 13:44:42
  17. 5-Spring IoC自动装载

    IoC 自动装载&#xff08;Autowire&#xff09; IoC 负责创建对象&#xff0c;DI 负责完成对象的依赖注入&#xff0c;通过配置 property 标签的 ref 属性来完成&#xff0c; 同时 Spring提供了另外一种更加简便的依赖注入方式&#xff1a;自动装载&#xff0c;不需要手动配置…...

    2024/4/20 13:44:41
  18. Java面试题-day14 JSP相关知识合集

    jsp&#xff1a;服务器 1) Tomcat&#xff0c;Apache&#xff0c;JBoss的区别&#xff1f; Apache解析静态的html文件&#xff1b;Tomcat可解析jsp动态页面、也可充当servlet容器。Apache是Http服务器&#xff0c;Tomcat是web服务器,只支持jspservletJBoss是应用服务器&#x…...

    2024/4/20 13:44:41
  19. MATLAB车牌识别计时计费系统

    一、课题介绍 随着汽车数量的增加&#xff0c;城市交通状况日益受到人们的重视&#xff0c;如何进行有效的交通管理更是成为了人们关注的焦点。智能交通系统通过车辆检测装置对过往的车辆实施检测&#xff0c;提取有关交通数据&#xff0c;达到监控、管理和指挥交通的目的。因此…...

    2024/4/20 13:44:39
  20. Python 测试题

    1.变量如何定义&#xff1f;(5分) 定义int, float, complex, tuple, list, dict类型变量 输出变量的值&#xff0c;以及类型 int1 float1.1 complex{1,2,3,4} tuple(1,2,3,4) list[1,2] dict{1:2,3:4} print(int,type(int)) print(float,type(float)) print(complex,type(comp…...

    2024/4/20 13:44:39

最新文章

  1. 算法效率的判断及一些典型例题的讲解

    一.算法效率 1.用处&#xff1a;判断算法的好坏&#xff0c;好的算法应该是高效的 2算法效率取决于时间复杂度和空间复杂度 <1>时间复杂度 1.1概念&#xff1a;算法中基本操作的执行次数就是算法的时间复杂度 1.2表示&#xff1a;大O的渐进表示法&#xff0c;例如O(N)…...

    2024/5/1 19:32:33
  2. 梯度消失和梯度爆炸的一些处理方法

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

    2024/3/20 10:50:27
  3. WPS二次开发专题:如何获取应用签名SHA256值

    作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 在申请WPS SDK授权版时候需要开发者提供应用包名和签…...

    2024/5/1 13:07:33
  4. 开启 Keep-Alive 可能会导致http 请求偶发失败

    大家好&#xff0c;我是蓝胖子&#xff0c;说起提高http的传输效率&#xff0c;很多人会开启http的Keep-Alive选项&#xff0c;这会http请求能够复用tcp连接&#xff0c;节省了握手的开销。但开启Keep-Alive真的没有问题吗&#xff1f;我们来细细分析下。 最大空闲时间造成请求…...

    2024/5/1 13:02:34
  5. 【外汇早评】美通胀数据走低,美元调整

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

    2024/5/1 17:30:59
  6. 【原油贵金属周评】原油多头拥挤,价格调整

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

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

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

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

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

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

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

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

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

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

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

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

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

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

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

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

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

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

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

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

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

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

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

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

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

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

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

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

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

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

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

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

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

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

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

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

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

    2024/4/30 9:42:49
  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