当前位置: 首页 > 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算法源码...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...