当前位置: 首页 > news >正文

InnoDB 死锁和问题排查

文章目录

    • 死锁(dead lock)
      • 示例 1
    • 问题排查
      • 查看连接的线程
      • 查看相关的表
      • 查看最近一次的死锁信息
      • 查看服务器的锁信息
      • 查看正在使用的表
    • 如何尽可能地避免死锁

死锁(dead lock)

两个及以上的事务各自持有对方需要的锁,导致双方都无法继续执行,只能互相等待(循环等待)。因为双方都在等待对方释放锁,而各自又无法释放锁,从而导致了死循环。这就是死锁(dead lock)。

当两个事务锁定了多张表的多条记录(如 UPDATE 或者 SELECT … FOR UPDATE),且它们各自锁定的顺序相反时,就会出现死锁。当 sql 语句锁定了多行记录和间隙时,也容易出现死锁。

关于 InnoDB 锁的类型和兼容性,可参考 https://blog.csdn.net/lamp_yang_3533/article/details/129291575

产生死锁的四个条件:

  • 互斥条件:一个资源每次只能被一个进程(线程)使用。
  • 请求与保持条件:一个进程(线程)因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺条件:进程(线程)已获得的资源,在末使用完之前,不能被剥夺。
  • 循环等待条件:多个进程(线程)之间形成一种头尾相接的循环等待的资源争用关系。

死锁检测功能 innodb_deadlock_detect 默认是开启的。当出现死锁时,InnoDB 就会检测到状态,并及时回滚导致死锁的多个事务中的一个。

mysql> show variables like 'innodb_deadlock_detect';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_deadlock_detect | ON    |
+------------------------+-------+
1 row in set, 1 warning (0.00 sec)

如果关闭了死锁检测功能,InnoDB 就依赖锁等待超时时间 innodb_lock_wait_timeout,当锁等待超时(默认 50 秒)后,对事务进行回滚。

mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50    |
+--------------------------+-------+
1 row in set, 1 warning (0.00 sec)

说明: 以下示例基于 MySQL 8.0,如果是之前的版本会有所不同。

示例 1

CREATE TABLE `t` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',`name` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户名称',`department_id` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '用户所属的部门id',`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户的状态: 1启用, 2禁用',`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),KEY `department_id_index` (`department_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';# 插入部分测试数据
INSERT t (`id`, `name`, `department_id`, `status`) VALUES 
('1', 'test', '8', '1'),
('2', 'test', '1', '1'),
('3', 'test', '8', '1'),
('7', 'test', '2', '1'),
('8', 'test', '2', '1'),
('9', 'test', '8', '1');

首先,在第一个连接中,开启事务 A。

# 事务 A
BEGIN;
UPDATE t SET department_id=3 WHERE id BETWEEN 3 AND 7;

由于在 MySQL 8.0 中,只要持有锁(不管是否出现锁争用),locks 表中就会记录数据。

故可以先简单看一下事务中锁的信息。

SELECT trx_mysql_thread_id AS sql_thread_id,trx_id, OBJECT_NAME as `table`, INDEX_NAME as `index`, LOCK_DATA as data, LOCK_MODE as mode, LOCK_STATUS as status, LOCK_TYPE as type 
FROM performance_schema.data_locks as lk
LEFT JOIN information_schema.innodb_trx as trx ON trx.trx_id=lk.ENGINE_TRANSACTION_ID;
+---------------+--------+-------+---------+------+------+---------+--------+
| sql_thread_id | trx_id | table | index   | data | mode | status  | type   |
+---------------+--------+-------+---------+------+------+---------+--------+
|            30 | 28220  | t     | NULL    | NULL | IX   | GRANTED | TABLE  |
|            30 | 28220  | t     | PRIMARY | 3    | X    | GRANTED | RECORD |
|            30 | 28220  | t     | PRIMARY | 7    | X    | GRANTED | RECORD |
|            30 | 28220  | t     | PRIMARY | 8    | X    | GRANTED | RECORD |
+---------------+--------+-------+---------+------+------+---------+--------+
4 rows in set (0.00 sec)

然后,在第二个连接中,开启事务 B。

# 事务 B
BEGIN;
UPDATE t SET status=2 WHERE id=9;

继续看一下事务中锁的信息。

+---------------+--------+-------+---------+------+------+---------+--------+
| sql_thread_id | trx_id | table | index   | data | mode | status  | type   |
+---------------+--------+-------+---------+------+------+---------+--------+
|            33 | 28226  | t     | NULL    | NULL | IX   | GRANTED | TABLE  |
|            33 | 28226  | t     | PRIMARY | 9    | X    | GRANTED | RECORD |
|            30 | 28220  | t     | NULL    | NULL | IX   | GRANTED | TABLE  |
|            30 | 28220  | t     | PRIMARY | 3    | X    | GRANTED | RECORD |
|            30 | 28220  | t     | PRIMARY | 7    | X    | GRANTED | RECORD |
|            30 | 28220  | t     | PRIMARY | 8    | X    | GRANTED | RECORD |
+---------------+--------+-------+---------+------+------+---------+--------+
6 rows in set (0.00 sec)

还未出现锁争用的情况。

然后,在事务 B 中,继续执行下面的 SQL。

UPDATE t SET status=2 WHERE id=3;

查看事务中的锁信息,如下:

+---------------+--------+-------+---------+------+------+---------+--------+
| sql_thread_id | trx_id | table | index   | data | mode | status  | type   |
+---------------+--------+-------+---------+------+------+---------+--------+
|            33 | 28234  | t     | NULL    | NULL | IX   | GRANTED | TABLE  |
|            33 | 28234  | t     | PRIMARY | 9    | X    | GRANTED | RECORD |
|            33 | 28234  | t     | PRIMARY | 3    | X    | WAITING | RECORD |
|            30 | 28229  | t     | NULL    | NULL | IX   | GRANTED | TABLE  |
|            30 | 28229  | t     | PRIMARY | 3    | X    | GRANTED | RECORD |
|            30 | 28229  | t     | PRIMARY | 7    | X    | GRANTED | RECORD |
|            30 | 28229  | t     | PRIMARY | 8    | X    | GRANTED | RECORD |
+---------------+--------+-------+---------+------+------+---------+--------+
7 rows in set (0.00 sec)

可发现,目前已经出现资源竞争,事务 B 处于锁等待(wait)状态。

最后,在事务 A 中,继续执行下面的 SQL。

UPDATE t SET status=2 WHERE id=9;

出现双方循环等待,立即产生死锁,事务报错。

事务 B 报错信息如下:

[Err] 1213 - Deadlock found when trying to get lock; try restarting transaction

再来看看事务中锁的信息。

+---------------+--------+-------+---------+------+------+---------+--------+
| sql_thread_id | trx_id | table | index   | data | mode | status  | type   |
+---------------+--------+-------+---------+------+------+---------+--------+
|            30 | 28229  | t     | NULL    | NULL | IX   | GRANTED | TABLE  |
|            30 | 28229  | t     | PRIMARY | 3    | X    | GRANTED | RECORD |
|            30 | 28229  | t     | PRIMARY | 7    | X    | GRANTED | RECORD |
|            30 | 28229  | t     | PRIMARY | 8    | X    | GRANTED | RECORD |
|            30 | 28229  | t     | PRIMARY | 9    | X    | GRANTED | RECORD |
+---------------+--------+-------+---------+------+------+---------+--------+
5 rows in set (0.00 sec)

由于死锁,事务 B 被 InnoDB 回滚了。故现在只剩下事务 A 的锁,它可以正常提交事务了。

这里,我们利用下面语句查看最新监测到的死锁信息。

SHOW ENGINE INNODB STATUS\G;
------------------------
LATEST DETECTED DEADLOCK
------------------------
2023-02-28 17:25:14 0x45c
*** (1) TRANSACTION:
TRANSACTION 28234, ACTIVE 50 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 33, OS thread handle 11904, query id 557 localhost 127.0.0.1 root updating
UPDATE t SET status=2 WHERE id=3
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6 page no 4 n bits 80 index PRIMARY of table `mytest`.`t` trx id 28234 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 8; compact format; info bits 00: len 4; hex 00000003; asc     ;;1: len 6; hex 000000006e45; asc     nE;;2: len 7; hex 01000001260281; asc     &  ;;3: len 10; hex 74657374202020202020; asc test      ;;4: len 1; hex 03; asc  ;;5: len 1; hex 81; asc  ;;6: len 5; hex 99af790294; asc   y  ;;7: len 5; hex 99af791609; asc   y  ;;*** (2) TRANSACTION:
TRANSACTION 28229, ACTIVE 65 sec starting index read
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 2
MySQL thread id 30, OS thread handle 1116, query id 574 localhost 127.0.0.1 root updating
UPDATE t SET status=2 WHERE id=9
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 6 page no 4 n bits 80 index PRIMARY of table `mytest`.`t` trx id 28229 lock_mode X locks rec but not gap
Record lock, heap no 4 PHYSICAL RECORD: n_fields 8; compact format; info bits 00: len 4; hex 00000003; asc     ;;1: len 6; hex 000000006e45; asc     nE;;2: len 7; hex 01000001260281; asc     &  ;;3: len 10; hex 74657374202020202020; asc test      ;;4: len 1; hex 03; asc  ;;5: len 1; hex 81; asc  ;;6: len 5; hex 99af790294; asc   y  ;;7: len 5; hex 99af791609; asc   y  ;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 6 page no 4 n bits 80 index PRIMARY of table `mytest`.`t` trx id 28229 lock_mode X locks rec but not gap waiting
Record lock, heap no 7 PHYSICAL RECORD: n_fields 8; compact format; info bits 00: len 4; hex 00000009; asc     ;;1: len 6; hex 000000006e4a; asc     nJ;;2: len 7; hex 02000001160280; asc        ;;3: len 10; hex 74657374202020202020; asc test      ;;4: len 1; hex 08; asc  ;;5: len 1; hex 82; asc  ;;6: len 5; hex 99af790294; asc   y  ;;7: len 5; hex 99af791618; asc   y  ;;*** WE ROLL BACK TRANSACTION (1)

问题排查

死锁出现的前提条件是锁等待,或者说是锁资源的争用。

不仅需要对死锁问题进行排查处理,还需要对长时间的锁等待问题,进行排查和分析。

锁等待会阻塞当前的线程,甚至对其他的线程造成影响,降低了系统的并发性能,线程资源和其持有的锁迟迟不能释放,不仅造成了资源的浪费,还有可能导致服务器崩溃。

下面是一些常常会用到的分析手段。

查看连接的线程

show processlist;可以显示哪些线程正在运行。如果当前用户有 SUPER 权限,就可以看到所有线程。

如果有线程正在 UPDATE 或者 INSERT 某张表,那么进程的 state 为 Updating 或者 Sending data。

show processlist; 只会列出前 100 条数据,如果想列出所有结果,可以使用 show full processlist;

  • Id 表示线程 id(客户端连接的 id)。可使用 select connection_id(); 获取。
  • User 表示客户端连接用的是哪个用户。
  • Host 表示客户端连接到了哪个 host 主机。
  • db 表示客户端连接的是哪个数据库。可使用 select database(); 获取。
  • Command 表示客户端连接当前操作的命令类型。
  • Time 表示客户端连接当前操作的命令持续了多长时间,单位秒。
  • info 表示客户端连接当前操作的具体是什么命令。
  • state 表示当前操作命令的状态。

关于 state 的常见状态值如下:

  • Sending data 表示正在处理 select 查询,同时正在把查询结果发送给客户端。
  • Updating 表示正在搜索匹配的行,并修改它们。
  • Locked 表示被其他的 sql 操作锁住了。
  • User lock 表示正在等待 get_lock()。
  • Upgrading lock 表示正在升级锁。
  • Searching rows for update 表示正在搜索符合条件的行以备更新。
  • Removing duplicates 表示正在执行 select distinct,对查询结果去重。
  • Sorting for order 表示正在进行 order by 排序。
  • Creating tmp table 表示正在创建临时表,来存放子查询的临时结果集。
  • Copying tmp table on disk 表示临时结果集大于 tmp_table_size,正在将临时表从内存存储转换为磁盘存储,以节省内存。
mysql> show full processlist;
+----+-----------------+-----------------+--------+---------+-------+------------------------+----------------------------------+
| Id | User            | Host            | db     | Command | Time  | State                  | Info                             |
+----+-----------------+-----------------+--------+---------+-------+------------------------+----------------------------------+
|  4 | event_scheduler | localhost       | NULL   | Daemon  | 11355 | Waiting on empty queue | NULL                             |
|  8 | root            | localhost:63023 | NULL   | Sleep   | 11271 |                        | NULL                             |
| 13 | root            | localhost:63066 | mytest | Sleep   | 10490 |                        | NULL                             |
| 20 | root            | localhost:63458 | mytest | Sleep   |   143 |                        | NULL                             |
| 23 | root            | localhost:63470 | mytest | Sleep   |  9971 |                        | NULL                             |
| 24 | root            | localhost:63480 | mytest | Sleep   |  8050 |                        | NULL                             |
| 25 | root            | localhost:63485 | mytest | Sleep   |  9583 |                        | NULL                             |
| 27 | root            | localhost:63504 | mytest | Sleep   |    30 |                        | NULL                             |
| 30 | root            | localhost:63601 | mytest | Sleep   |    63 |                        | NULL                             |
| 32 | root            | localhost:63891 | mytest | Query   |     0 | starting               | show full processlist            |
| 33 | root            | localhost:63965 | mytest | Query   |    34 | updating               | UPDATE t SET status=2 WHERE id=9 |
+----+-----------------+-----------------+--------+---------+-------+------------------------+----------------------------------+
11 rows in set (0.00 sec)

当然,也可直接用下面的 SQL 语句查表。

select * from information_schema.processlist;

查看相关的表

注意:从 MySQL 8.0 开始,data_locks 取代了 innodb_locks,data_lock_waits 取代了 innodb_lock_waits,并移到了数据库 performance_schema

information_shcema.innodb_trx 表存储了当前的事务(进行中的)信息。

SELECT * FROM information_schema.innodb_trx;

performance_schema.data_locks 存储了当前的锁信息。

SELECT * FROM performance_schema.data_locks;

performance_schema.data_lock_waits 存储了当前的锁等待信息。

SELECT * FROM performance_schema.data_lock_waits;

information_schema.processlist 存储了当前的连接信息。

select * from information_schema.processlist;

除了单独查看上面几张表的详细信息外,还可以联表查询需要的字段,这样会更直观

# 查看线程和锁的信息
SELECT trx_mysql_thread_id AS sql_thread_id,trx_id, BLOCKING_ENGINE_TRANSACTION_ID AS blocked_by_trx_id,OBJECT_NAME as `table`, INDEX_NAME as `index`, LOCK_DATA as data, LOCK_MODE as mode, LOCK_STATUS as status, LOCK_TYPE as type,trx_state,trx_started,trx_wait_started,trx_query
FROM performance_schema.data_locks as lk
LEFT JOIN information_schema.innodb_trx as trx ON trx.trx_id=lk.ENGINE_TRANSACTION_ID
LEFT JOIN performance_schema.data_lock_waits as lkw ON lkw.REQUESTING_ENGINE_TRANSACTION_ID=trx.trx_id;
+---------------+--------+-------------------+-------+---------+------+------+---------+--------+-----------+---------------------+---------------------+----------------------------------+
| sql_thread_id | trx_id | blocked_by_trx_id | table | index   | data | mode | status  | type   | trx_state | trx_started         | trx_wait_started    | trx_query                        |
+---------------+--------+-------------------+-------+---------+------+------+---------+--------+-----------+---------------------+---------------------+----------------------------------+
|            33 | 28248  |             28239 | t     | NULL    | NULL | IX   | GRANTED | TABLE  | LOCK WAIT | 2023-02-28 20:01:15 | 2023-02-28 20:01:15 | UPDATE t SET status=2 WHERE id=9 |
|            33 | 28248  |              NULL | t     | PRIMARY | 9    | X    | WAITING | RECORD | LOCK WAIT | 2023-02-28 20:01:15 | 2023-02-28 20:01:15 | UPDATE t SET status=2 WHERE id=9 |
|            30 | 28239  |              NULL | t     | NULL    | NULL | IX   | GRANTED | TABLE  | RUNNING   | 2023-02-28 19:04:41 | NULL                | NULL                             |
|            30 | 28239  |              NULL | t     | PRIMARY | 9    | X    | GRANTED | RECORD | RUNNING   | 2023-02-28 19:04:41 | NULL                | NULL                             |
+---------------+--------+-------------------+-------+---------+------+------+---------+--------+-----------+---------------------+---------------------+----------------------------------+
4 rows in set (0.00 sec)

查看最近一次的死锁信息

show engine innodb status 查看最近一次检测到的死锁信息(LATEST DETECTED DEADLOCK)。

show engine innodb status\G;

如果死锁问题很频繁,想要查看更多的死锁信息。可以开启 innodb_print_all_deadlocks 选项,将所有的死锁信息记录到 MySQL 服务器的错误日志。

查看服务器的锁信息

show status like '%lock%';
mysql> show status like '%lock%';
+------------------------------------------+--------+
| Variable_name                            | Value  |
+------------------------------------------+--------+
| Com_lock_instance                        | 0      |
| Com_lock_tables                          | 0      |
| Com_unlock_instance                      | 0      |
| Com_unlock_tables                        | 0      |
| Handler_external_lock                    | 26     |
| Innodb_row_lock_current_waits            | 1      |
| Innodb_row_lock_time                     | 596291 |
| Innodb_row_lock_time_avg                 | 37268  |
| Innodb_row_lock_time_max                 | 51895  |
| Innodb_row_lock_waits                    | 16     |
| Key_blocks_not_flushed                   | 0      |
| Key_blocks_unused                        | 6698   |
| Key_blocks_used                          | 0      |
| Locked_connects                          | 0      |
| Performance_schema_locker_lost           | 0      |
| Performance_schema_metadata_lock_lost    | 0      |
| Performance_schema_rwlock_classes_lost   | 0      |
| Performance_schema_rwlock_instances_lost | 0      |
| Performance_schema_table_lock_stat_lost  | 0      |
| Table_locks_immediate                    | 409    |
| Table_locks_waited                       | 0      |
+------------------------------------------+--------+
21 rows in set (0.00 sec)

可重点关注下面几个参数:

  • Innodb_row_lock_current_waits 当前正处于锁等待状态的数量;
  • Innodb_row_lock_time 服务器从启动到现在,锁等待的总时长,单位毫秒
  • Innodb_row_lock_time_avg 服务器从启动到现在,锁等待的平均时长,单位毫秒
  • Innodb_row_lock_time_max 服务器从启动到现在,锁等待最久的一次时长,单位毫秒
  • Innodb_row_lock_waits:服务器从启动到现在,锁等待的总次数。

如果锁等待的总次数和锁等待的平均时长比较大,可以考虑排查优化。

查看正在使用的表

查看哪些表是打开的,正在被线程使用。

in_use 表示有多少线程正在使用某张表,可以用来过滤。

show open tables where in_use>0;show open tables from db_name where in_use>0;

一般只用于查看哪些表被很多线程打开使用。

如何尽可能地避免死锁

  • 合理设计和使用索引,采用复合索引时,将区分度高的放在最前面,避免全表扫描。
  • 避免大事务,尽量将大事务拆分为多个小事务来处理,尽可能快地提交事务。
  • 更新多张表或多条记录时,确保每次操作的顺序一致
  • 减少更新或插入语句的数据量(行数),这样就可减少锁定的行数和间隙,也可减少事务执行的时长。
  • 尽量使用唯一索引(如主键)去查询和更新索引。
  • 高并发的系统中,尽量不要手动(显式)加锁。如少用显式的排他锁(X)select ... for update 和 共享锁(S)select ... lock in share mode
  • 在服务器高峰期,不要执行耗时的复杂脚本,不要修改表结构,不要进行批量数据修复。

相关文章:

InnoDB 死锁和问题排查

文章目录死锁(dead lock)示例 1问题排查查看连接的线程查看相关的表查看最近一次的死锁信息查看服务器的锁信息查看正在使用的表如何尽可能地避免死锁死锁(dead lock) 两个及以上的事务各自持有对方需要的锁,导致双方…...

tensorflow07——使用tf.keras搭建神经网络(Sequential顺序神经网络)——六步法——鸢尾花数据集分类

使用tf.keras搭建顺序神经网络 六步法——鸢尾花数据集分类 01 导入相关包 02 导入数据集,打乱顺序 03 建立Sequential模型 04 编译——确定优化器,损失函数,评测指标(用哪一种准确率) 05 训练模型——把各项参入填入…...

关于Java连接Hive,Spark等服务的Kerberos工具类封装

关于Java连接Hive,Spark等服务的Kerberos工具类封装 idea连接服务器的hive等相关服务的kerberos认证注意事项 idea 本地配置,连接服务器;进行kerberos认证,连接hive、HDFS、Spark等服务注意事项: 本地idea连接Hadoo…...

大数据框架之Hadoop:MapReduce(五)Yarn资源调度器

Apache YARN (Yet Another Resource Negotiator) 是 hadoop 2.0 引入的集群资源管理系统。用户可以将各种服务框架部署在 YARN 上,由 YARN 进行统一地管理和资源分配。 简言之,Yarn是一个资源调度平台,负责为运算程序提供服务器运算资源&…...

uniapp实现地图点聚合功能

前言 在工作中接到的一个任务,在app端实现如下功能: 地图点聚合地图页面支持tab切换(设备、劳务、人员)支持人员搜索显示分布 但是uniapp原有的map标签不支持点聚合功能(最新的版本支持了点聚合功能)&am…...

经典分类模型回顾2—GoogleNet实现图像分类(matlab版)

GoogleNet是深度学习领域的一种经典的卷积神经网络,其在ImageNet图像分类任务上的表现十分优秀。下面是使用Matlab实现GoogleNet的图像分类示例。 1. 数据准备 在开始之前,需要准备一些图像数据用来训练和测试模型,可以从ImageNet等数据集中…...

Java经典面试题——谈谈 final、finally、finalize 有什么不同?

典型回答 final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展, final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。 finally 则是 Java 保…...

C#的Version类型值与SQL Server中二进制binary类型转换

使用C#语言编写的应用程序可以通过.NET Framework框架提供的Version类来控制每次发布的版本号,以便更好控制每次版本更新迭代。 版本号由两到四个组件组成:主要、次要、内部版本和修订。 版本号的格式如下所示, 可选组件显示在方括号 ([ 和…...

软测入门(五)接口测试Postman

Postman 一款Http接口收工测试工具。如果做自动化测试会使用jemter做。 安装 去官网下载即可。 https://www.postman.com/downloads/?utm_sourcepostman-home 功能介绍 页面上的单词基本上都能了解,不多介绍。 转代码&注释 可将接口的访问转为其他语言的…...

UWB通道选择、信号阻挡和反射对UWB定位范围和定位精度的影响

(一)介绍检查NLOS操作时需要考虑三个方面:(1)由于整体信号衰减,通信范围减小。(2)由于直接路径信号的衰减,导致直接路径检测范围的减小。(3)由于阻…...

linux基本功之列之wget命令实战

文章目录前言一. wget命令介绍二. 语法格式及常用选项三. 参考案例3.1 下载单个文件3.2 使用wget -o 下载文件并改名3.3 -c 参数,下载断开链接时,可以恢复下载3.4 wget后台下载3.5 使用wget下载整个网站四. 补充与汇总常见用法总结前言 大家好&#xff…...

学习ROS时针对gazebo相关的问题(重装与卸载是永远的神)

ResourceNotFound:gazebo_ros 错误解决 参考:https://blog.csdn.net/weixin_42591529/article/details/123869969 当将机器人加载到gazebo时,运行launch文件出现如下错误 这是由于缺少gazebo包所导致的。 解决办法:...

几个C语言容易忽略的问题

1 取模符号自增问题 我们不妨尝试写这样的程序 #include<stdio.h> int main(){int n,t5;printf("%d\n",7%(-3));//1printf("%d\n",(-7)%3);//-1while(--t)printf("%d\n",t);t5;while(t--)printf("%d\n",t);return 0; } 运行…...

CentOS 7.9安装Zabbix 4.4《保姆级教程》

CentOS 7.9安装Zabbix 4.4一、配置一览二、环境准备设置Selinux和firewalld设置软件源1.配置ustc CentOS-Base源2.安装zabbix 4.4官方源3.安装并更换epel源4.清除并生成缓存三、安装并配置Zabbix Server安装zabbix组件安装php安装mariadb并创建数据库修改zabbix_server.conf设置…...

路由器与交换机的区别(基础知识)

文章目录交换机路由器路由器和交换机的区别&#xff08;1&#xff09;工作层次不同&#xff08;2&#xff09;数据转发所依据的对象不同&#xff08;3&#xff09;传统的交换机只能分割冲突域&#xff0c;不能分割广播域&#xff1b;而路由器可以分割广播域&#xff08;4&#…...

Python基础学习9——函数

基本概念 函数是一种能够完成某项任务的封装工具。在数学中&#xff0c;函数是自变量到因变量的一种映射&#xff0c;通过某种方式能够使自变量的值变成因变量的值。其实本质上也是实现了某种值的转换的任务。 函数的定义 在python中&#xff0c;函数是利用def来进行定义&am…...

项目中的MD5、盐值加密

首先介绍一下MD5&#xff0c;而项目中用的是MD5和盐值来确保密码的安全性&#xff1b; 1. md5简介 md5的全称是md5信息摘要算法&#xff08;英文&#xff1a;MD5 Message-Digest Algorithm &#xff09;&#xff0c;一种被广泛使用的密码散列函数&#xff0c;可以产生一个128位…...

电商项目后端框架SpringBoot、MybatisPlus

后端框架基础 1.代码自动生成工具 mybatis-plus &#xff08;1&#xff09;首先需要添加依赖文件 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.2</version></dependency><de…...

2023年03月IDE流行度最新排名

点击查看最新IDE流行度最新排名&#xff08;每月更新&#xff09; 2023年03月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多&#xff0c;这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&am…...

华为校招机试 - 数组取最小值(Java JS Python)

目录 题目描述 输入描述 输出描述 用例 题目解析 JavaScript算法源码 Java算法源码...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...