【MySQL】MySQL索引与事务

news2025/4/26 12:58:16

目录

前言

1. 索引 (index)

1.1 概念

1.2 作用

1.3 使用场景

1.4 索引的相关操作

查看索引

创建索引

删除索引

2. 索引背后的数据结构

2.1 B+树

2.2 B+树的特点

2.3 B+树的优势

3. 事务

3.1 为什么使用事务

3.2 事务的概念

3.3 使用事务

3.4 事务四大关键特性

4. 事务隔离性解决并发问题

4.1 脏读问题

4.2 不可重复读

4.3 幻读

4.4 隔离级别


前言

数据库使用 select 查询的时候:

  1. 先遍历表
  2. 把当前的行给带入到条件中,看条件是否成立
  3. 条件成立,这样的行就保留。不成立就跳过。
  • 如果表非常的小,正常使用没问题。如果表非常大,这样的遍历成本就比较高了。
  • 站在时间复杂度角度,每次从内存中读取一条一条记录,进行比较至少是O(N)。时间复杂度和空间复杂度的计算都是针对内存中数据进行的操作。读取内存的访问速度非常快,计算时间复杂度不包含读取内存的时间,依据是基于操作的执行(比较)次数。
  • 数据库是把数据存储在硬盘上,每次需要先读取硬盘拿到一个数据,再进行比较。
  • 读取硬盘这个操作,开销本身就是很大的。读写1次硬盘开销远远大于读写1次内存。读1次硬盘相当于读1万次内存。如果是N个数据,频繁进行读取更是慢上加慢。

所以就引出了索引,增加遍历查询速度,减少硬盘的访问次数。针对查询操作引入的优化手段。

1. 索引 (index)

索引英文是 index这里的 index 指的是索引,并不是数组下标。

1.1 概念

索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。(具体细节在后续的数据库原理课程讲解)

1.2 作用

  • 索引属于是针对查询操作引入的优化手段。可以通过索引来加快查询的速度,减少硬盘的访问次数,避免针对表进行遍历。
  • 数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。
  • 索引所起的作用类似书籍目录,可用于快速定位、检索数据。

引入索引的代价:

  • 索引会占用额外的磁盘空间,付出额外空间代价来保存索引数据。生成索引,是需要一系列的数据结构,以及一系列的额外的数据,来存储到硬盘空间中的。
  • 索引加快了查询速度,但可能会拖慢新增,删除,修改的速度。因为新增、删除、修改数据还需要同步新增、删除、修改索引,产生额外的开销。例如,修改论文的标题,需要同步修改目录。
整体来说,还是认为索引是利大于弊。实际开发中,查询(读)场景一般要比增删改(写)频率高很多。

1.3 使用场景

要考虑对数据库表的某列或某几列创建索引,需要考虑以下几点:

  • 数据量较大,且经常对这些列进行条件查询。
  • 该数据库表的插入操作,及对这些列的修改操作频率较低。
  • 不太在意,索引占用额外的磁盘空间。

满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。

反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。

1.4 索引的相关操作

创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引。

为什么创建这三个约束,会自动创建对应列的索引:

  • primary key 和 uniqe 都是要求对应列的记录不能重复,每次插入/修改被约束列的数据,需要查询判断是否重复。涉及频繁的查询操作。优化查询速度,自动引入索引,查询跟着索引走就不需要一条条记录去遍历了,大大加快了插入/修改的速度。
  • foreign key 约束的时候,子表中对应的记录要在父表中存在。往子表中插入/修改对应约束列的数据时,就需要每次查询父表中是否存在。反之,从父表中修改/删除数据时,也需要查询该数据在子表中是否被引用。涉及频繁的查询操作。优化查询速度,自动引入索引。

  • 查看索引

primary key 主键自动生成的索引
  • 可以理解为:student表中内容,根据id列生成了一份目录;这里自动创建的索引名为primary
  • 索引表中的列大概认识一下,不需要全部了解。
  • 一个索引是针对一个列来指定的。
  • 只有针对这一列进行条件查询的时候,查询速度才能够被索引优化。

例如:

  • 此处针对 id 创建索引。使用id进行条件查询,速度是很快。
  • select * from student where id = 100; ——  使用索引,不需要一条条记录遍历。
  • select * from student where name = '张三';  —— 仍然需要遍历表。

unique  自动生成的索引

foreign key 外键自动生成的索引

  • 一本书可以有多个目录一个表也可以有多个索引,每个索引针对不同列。
  • 例如:一个字典,目录有多种。拼音目录、笔画目录、部首目录、难检字目录。

  • 创建索引

对于非主键、非唯一约束、非外键的字段,可以创建普通索引。

  • 创建索引操作,也是一个危险操作;创建索引的时候,需要针对现有的数据,进行大规模的重新整理。如果当前表是一个空表或者数据不多,创建索引都没有问题。但如果这个表很大,创建索引开销会很大,很容易就把数据库服务器给卡住。

例如:有一本很厚的书,现在给这个书手动的写一份目录出来。好的做法,是创建表之初就把索引设定好。

  • 一般来说,创建索引,在创建表时已经规划好了。如果表使用了很久,有很多数据,再想创建索引,就要慎重了。

如果表很大,坚持要创建索引,使用“移花接木”的技巧方式,尤其是生产环境(线上)的数据库。做法:在另外一台机器部署mysql服务器,创建同样的表,并且把表上的索引创建好,再把之前的机器上的数据给导入到新的mysql服务器上。控制导入数据过程的节奏,多花点时间导数据,不要影响到原来服务器正常的运转。当所有数据都导入完毕,就可以使用新的数据库,替换旧的数据库了。

  • 删除索引

  • 手动创建的索引,可以手动删除。自动创建的索引(主键/外键,unique),不可以删除。

和创建索引类似,删除索引也是一个危险操作。理由同上。

2. 索引背后的数据结构

索引是通过一定的数据结构来实现的。B+树(N叉搜索树),为数据库量身定做的数据结构。

哪些数据结构能加快查询的速度,mysql的索引的数据结构为什么不能是顺序表,链表,栈,队列,二叉搜索树,哈希表呢?

  • 1. 顺序表   查询元素时间复杂度O(N)

在顺序表中间插入或删除元素需要移动大量数据,效率较低。

当容量不足时,需要重新分配更大的存储空间,并拷贝所有数据。

在大规模数据中进行随机查询效率低,尤其是当数据需要排序时。

  • 2. 链表  查询元素时间复杂度是 O(N)

链表不支持随机访问,必须从头开始遍历,查询时间复杂度是 O(N)。

每个节点需要额外的指针存储,内存开销较高。链表不能快速进行范围查询。

链表广义上插入/删除的时间复杂度为O(1),但java中具体实现LinkeList插入/删除的时间复杂度为O(N),需要遍历找到要插入/删除元素的位置。

  • 3. 栈、队列、堆   查询元素时间复杂度是 O(N)

栈和队列只适合用于简单的顺序操作,不支持高效的随机查询、范围查询或复杂操作。

栈和队列不支持快速的插入、删除或排序操作。

  • 4. 二叉搜索树   查询元素时间复杂度是 O(N)/O(logN)

一个普通的二叉搜索树,查询时间复杂度是O(N),因为会存在不平衡的极端情况(单枝树),如果引入平衡机制(AVL树,红黑树)可以达到O(logN)。

实际开发中用红黑树比较多一些,因为AVL树要保持左右子节点的高度差不会超过1,要求太严格,触发调整的频率就比较高,有一定额外开销。红黑树虽然近似平衡二叉树,但左右子节点的高度差保持在一定范围内即可,没有AVL要求的那么严格,综合能力更好些。(数据结构进阶篇会介绍)

  • 5. 哈希表 查询时间复杂度是 O(1)

通过计算哈希函数映射到数组的下标。

从前面所学习的数据结构中,可知道红黑树(二叉搜索树)和哈希表都能提高查询速度,但是并不适合数据库的查询场景。

mysql数据库中查询操作经常会用到:精准查询、范围查询、模糊匹配等查询操作。

所以实现索引的数据结构至少能够满足以上的查询操作。 索引针对的列的模糊匹配只是一部分的实现。也就是并非所有的查询操作都能用到索引。

知道第一个字符,就可以通过第一个字符大小关系,来缩小查询范围,这个操作可以一定程度上使用索引。不知道第一个字符,每个字符都有可能,仍然需要遍历。

  • 哈希表,哈希表只能进行“精准匹配”,无法做到范围查询和模糊查询。 
  • 红黑树(平衡二叉搜索树),可以处理精准匹配、范围查询(元素是有序的找到开头,找到结尾就可以找到)、能一定程度的模糊匹配,但最大的问题是树的高度。

最大的问题:红黑树是二叉树(平衡),每个节点最多两个子树,树的分叉少(结点的度少),表示同样数量的结果集合,树的高度就会更高。

一旦树的高度更高了,查询操作的时候硬盘IO访问次数就会更多。考虑每个节点都要触发IO,如果是一个二叉树,在查询叶子节点元素就要从树根一路往下找,找到叶子节点,每往下走一层就是IO一次,高度有多少,IO次数就有几次,所以这样的操作是比较低效的。 因此数据库引入的索引是一个改进的树形结构,B+树(N叉搜索树)。

2.1 了解B树

要了解B+树需要先了解下B树,B树有的时候会写作B - 树,不是B减树仍是B树的意思。 '-' 是连接符的意思,不是数学中的减符号。

B树的核心思路和"二叉搜索树"差不多。B树本质上是一个N叉搜索树

由于是N叉搜索树,有N个分叉,每个分叉代表一个区间,此时意味着当前节点里面就可以存储多个key。

  • 每个节点的度都是不确定的。当节点的子树多了以及节点上保存的key多了,意味着在同样key 的个数的前提下,B树的高度就要比二叉搜索树低很多,树的高度越低,进行查询的时候访问磁盘的次数就越少,速度就大大提升。
  • B树的查询基本思路与二叉搜索树的查询思路是相似的,只不过B树是分了N叉,每个节点中有多个key,需要进行多次比较,确定走哪个区间,从而走哪个子树。
  • 一个节点上保存N个key就划分出N+1个区间。每个区间都可以衍生出一系列的子树了。树的高度就大幅度的降低了。
  • 由于每个节点是在一个硬盘的区域中,一次读硬盘就读取出了整个节点(多个key )再进行几次比较。(读一次硬盘的开销远远大于内存中比较的开销,读一次硬盘相当于内存中1w次比较。这里的比较操作一般都不会到几万,都是几个或十几个元素,这里的比较操作并不会特别耗时,相对于读取硬盘来说是非常轻量的,没有太大影响)
  • 一个节点中,虽然是可以保存N个key,也不是无限制的,达到一定的规模,就会触发节点的分裂。当删除元素达到一定的数目,也会触发节点的合并(简化树形结构)。
  • 具体什么时候进行拆分,怎么拆分;具体什么时候合并,怎么合并。实际的实现中,不同的场景下可以使用不同的策略。

2.2 B+树

B+树,在B树的基础上又做出改进(也是N叉搜索树),针对数据库量身定做的。

  • 整个树的所有数据都是包含在叶子节点中的(所有非叶子节点中的key最终都会出现在叶子节点中)
  • 上述这个结构,是默认id是表的主键,如果这个表里有多个索引呢?
  • 针对id是主键创建索引,表的数据还是按照 id为主键,构建出B+树通过叶子节点组织所有的数据行。
  • 其次,针对 name这一列,则会构建另外一个B+树,但是这个B+树的叶子节点就不再存储这一行的完整数据,而是存主键id是啥,此时,如果你根据name来查询,查到叶子节点得到的只是主键id,还需要再通过主键id去主键的B+树里再查一次(查两次B+树),上述过程称为“回表",这个过程,都是mysql自动完成的,用户感知不到。
  • 上面的这个树形结构,是"索引",如果这一列不能比较,就没法建立索引;幸运的是, mysql里的各种类型都能比较,数字、字符串、时间日期。 故mysql中不支持自定义类型

2.3 B+树的特点

  1. 一个节点,可以存储N 个key,N个key划分出了N个区间(而不是B树中的N+1个区间)
  2. 每个节点中的key的值,都会在子节点中也存在(同时该key是子节点的最大值,也可以是最小值)
  3. B+树的叶子节点,是首尾相连,类似于一个链表
  4. 由于叶子节点是完整的数据集合,所以只在叶子节点这里存储数据表中的每一行的数据,而非叶子节点,只存key值本身即可。

2.4 B+树的优势

1、当前一个节点保存更多的 key,最终树的高度是相对更矮的,查询的时候减少了IO访问次数(和B树是一样的)这里IO特指硬盘的访问

2、所有的查询最终都会落到叶子节点上(查询任何一个数据,经过的IO访问次数,是一样的)

这个相同次数很关键,稳定的能够让程序猿对于程序的执行效率有一个更准确的评估。

3、B+树的所有的叶子节点,构成链表,此时比较方便进行范围查询。

例如:查询学号>5并且<11的同学。只需要先找到5所在的位置,在找到11所在位置从5沿着链表遍历到11,中间结果即为所求,非常方便非常高效。

4、由于数据都在叶子节点上,非叶子节点只存储key,导致非叶子节点占用空间是比较小的,这些非叶子节点就可能在内存中缓存(或者是缓存一部分),又进一步减少了IO的次数。 常量池本质上就是缓存。

例如:假设一个整数按照4个字节算,10亿个这样的整数,占据多大内存空间?(估算即可,不用精确)10亿个这样的 key才不到4G,4G对于计算机内存来说还是非常容易的。

带有索引的数据, mysql 组织数据就是B+树的方式;当你看到一张"表”的时候,实际上这个表不一定就是按照"表格"这样的数据结构在硬盘上组织的,也有可能是按照这种树形结构组织。具体是哪种结构,取决于你的表里有没有索引,以及数据库使用了哪种存储引擎。

3. 事务

3.1 为什么使用事务

开发中经常会涉及到一些场景,需要“一气呵成”的完成一些操作。

【案例】

  • 准备测试表:

drop table if exists accout;
create table accout(id int primary key auto_increment, name varchar(20) comment '账户名称', money decimal(11,2) comment '金额');
insert into accout(name, money) values('阿里巴巴', 5000),('四十大盗', 1000);

  • 比如说,四十大盗把从阿里巴巴的账户上偷盗了2000元

-- 阿里巴巴账户减少2000
update accout set money = money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money = money+2000 where name = '四十大盗';

  • 假如在执行以上第一句SQL时,出现网络错误,或是数据库挂掉了,阿里巴巴的账户会减少2000,但是四十大盗的账户上就没有了增加的金额。这是比较严重的错误。此时,数据就会出现“不上不下”的中间状态,非常明显的bug!!!

引入事务就是为了避免上述的问题。

解决方案:使用事务来控制,保证以上两句SQL要么全部执行成功,要么全部执行失败。

事务的本质就是把多个sql语句给打包成一个整体,要么全部执行成功,要么全部执行失败。而不会出现"执行一半"这样的中间状态。

3.2 事务的概念

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。

在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。

  • 把多个sql语句给打包成一个整体:称为原子性(atom)过去的人们认为原子是事物能够分割的最小单位。现在并非原子是最小分割单位。
  • 全部执行失败:不是真的没执行,而是"看起来好像没执行一样",其实是执行了,执行一半出错了,出错之后选择了恢复现场,把数据还原成未执行之前的状态了。
  • 这个恢复数据的操作,称为“回滚" (rollback)

【案例】

  • 单独执行的每个sql都是自成一个体系,此时这些sql之间是没有原子性的。
  • 如果把这俩操作作为一个事务,当第一个 sql执行完之后,数据库崩溃。当下次数据库重新启动完成之后,就会自动的把上次修改一半的数据给进行还原(把1号用户-500再加回来就行了)。

3.3 使用事务

  1. 开启事务:start transaction; 
  2. 执行多条SQL语句。这个过程中某个环节出现问题,例如程序崩溃/数据库崩溃/机器断电了,就会自动触发回滚机制。
  3. 提交或主动触发回滚:commit/rollback;
  • commit;  提交事物,意思是下面没有sql语句了,该事务结束了。事务结束的标记。
  • rollback 是主动触发回滚。出错有很多情况,崩溃/断电只是其中一种(会自发触发回滚),有时候需要主动通过代码方式判断当前是否需要回滚。所以rollback一般是要搭配一些条件判断逻辑来使用的。sql里也能支持条件,循环,变量,函数...,但是日常开发一般不会这么写,更多的是搭配其他的编程语言。例如使用java操作数据库,在java中主动判定某个结果是否符合要求,如果不符合要求进行主动回滚。
  • 说明:rollback即是全部失败,commit即是全部成功。

    回滚是怎么做到,把数据还原成未执行的状态?

    • 依据日志中的记录,进行回滚操作 。 例如日志里记录的操作是插入,回滚根据记录就删除。记录的操作是删除,回滚根据记录就插入。如果记录的操作是修改,回滚根据记录就改回去。

    • 数据库里专门有个用来记录事务关键操作的日志(正因为如此,使用事务的时候,执行sql的开销是更大的,效率是更低)。日志:是打印出来的内容,存放在文件里。
    • 日志是存放在文件中的,所以即使是主机掉电,也不影响(回滚用的日志已经在文件中了)。后续一旦重新启动主机,mysql也重新启动,就会发现回滚日志中有一些需要进行回滚的操作。于是就可以完成这里的回滚了。

    3.4 事务四大关键特性

    数据库的事务,有四个关键的特性:

    1. 原子性:把多个sql语句给打包成一个整体,要么全部执行成功,要么全部执行失败 ——最核心的特性
    2. 一致性:事务执行前后,数据要合理。(很多时候是要靠数据库的约束以及一系列的检查机制来完成的)

           3. 持久性:事务修改的内容是写到硬盘上持久保存的。重启服务器,数据仍然是存在的。

           4. 隔离性:是为了解决"并发"执行多个事务,引起的问题。

    并发:

    • 一个餐馆(服务器),同一时刻能给多个顾客(客户端)提供服务,这些顾客可能是一个接一个来的,也可能是一起来了一波顾客。
    • 此时,服务器同时处理多个客户端的请求,就称为"并发"(齐头并进的感觉)。
    • 同时能处理客户端请求越多,并发程度越高,整体的效率就越高。
    • 数据库也是服务器,一定会存在多个客户端给服务器提交事务的情况。为了提高效率,就会提高并发程度,但在数据库中提高并发程度之后,可能存在一些问题,会导致数据出现一些“错误”的情况。
    • 隔离级别,就是在"数据正确"和"效率"之间做权衡。往往提升了效率,就会牺牲正确性;提升了正确性,就会牺牲效率。
    • 事务的隔离性,存在的意义就是为了在数据库并发处理事务的时候不会有问题,即使有问题,问题也不会太大。

    4. 事务隔离性解决并发问题

    下面介绍,数据库中并发执行事务可能产生的问题,以及数据库的隔离性是怎样解决的。

    4.1 脏读问题

    问题描述:

    • 在我写代码的过程中,同学在我身后经过, 他瞄了一眼我的屏幕,看到了我的代码中写了一些内容,比如他看到了,我的代码里有一个class Student,有一些属性,id, name,gender... 然后他就走了,很可能他走了之后,我的代码又改了。
    • 即一个事务A正在对数据进行修改的过程中,还没提交之前;另外一个事务B,对同一个数据进行了读取,此时B的读操作就称为“脏读",读到的数据也称为"脏数据"。
    • 脏的意思,是"无效",而不是埋汰。为啥说无效?很可能,A回头又把数据给修改了。即另一个事务读取到的数据不一定是最终的结果,可能是无效数据。

    解决方法:写的时候不能读,写操作加锁。

    • 为了解决脏读问题,mysql 引入"写操作加锁"这样的机制。
    • 即我和同学们商量好,我写代码的过程中你别来看 ,等我改完提交到码云上,你再通过我的码云来看,写的时候不能看(给写操作加锁),写完了才能看。
    • 当我写的时候同学没法读,意味着我的“写操作"和同学的"读操作"不能并发了(不同同时执行了)
    • 这个给写加锁的操作,就降低了并发程度(降低了效率),提高了隔离性(提高了数据的准确性)

    4.2 不可重复读

    问题描述:

    • 还是我写代码,同学想看,约定好我写的时候不许看,等我提交了,再通过码云来看。当前约定好了写加锁。
    • 我写代码提交了版本1,此时就有同学开始读这个代码了;于是我又打开代码继续修改优化代码,然后又提交版本2。这个同学开始读的过程中,读到的是版本1的代码,读着读着我提交了版本2,此时这个同学读的代码,刷的一下变样了。这个问题,叫做“不可重复读"。
    • 事务1已经提交了数据,此时事务2开始去读取数据,在读取过程中,事务3修改了数据提交了新的数据,此时意味着同一个事务2之内,多次读数据,读出来的结果是不相同的(预期是一个事务中,多次读取结果得一样)就叫做"不可重复读"。即同一个事务中第二次读取的结果不能复现第一次的结果。

    解决方法:读的时候不能写,读操作加锁。

    • 解决不可重复读问题,需要给 读操作加锁
    • 同学发现了这个问题之后,知道了是在他读的过程中,我又改代码了,于是来找我和我约定,同学读代码的时候,我也不能修改。
    • 脏读问题约定的是,我修改的时侯,提交之前,同学不要读,是给写加锁。而不可重复读问题是在写加锁的基础上约定,同学读的时候,我不能修改,就是给读加锁。
    • 通过这个读加锁,又进一步的降低了事务的并发处理能力(处理效率也降低),提高了事务的隔离性(数据的准确性又提高了)

    4.3 幻读

    问题描述:

    • 当前已经约定了读加锁和写加锁,解决了不可重复读和脏读问题。
    • 由于约定了读加锁,同学读的时候我不能修改代码,我在这干的等着光摸鱼不干活有点难受,所以我想了办法,同学读Student.java文件,我就创建一个Teacher.java文件,写这个代码; 这样的情况,大多数情况下都没事,少数情况下,个别同学发现了,读代码读着突然冒出个Teacher.java,有的同学就觉得接受不了。
    • 在读加锁和写加锁的前提下,一个事务A两次读取同一个数据,发现读取的数据值是一样的,但是结果集不一样(Student.java 代码内容不变,但是第一次看到的是只有Student.java这个文件,第二次看到的是Student,java和Teacher.java ..)这种就称为"幻读"。

    解决方法:串行化执行事务。

    • 数据库使用"串行化"这样的方式来解决幻读,彻底放弃并发处理事务,一个接一个的串行的处理事务,这样做并发程度是最低的(没并发了,效率最慢的),隔离性是最高的(准确性也是最高的)
    • 相当于是同学们要求,在他们读代码的时候,我不要摸电脑,必须强制摸鱼!!!

    4.4 隔离级别

    上述三个问题,就是并发处理事务的三个典型问题。

    mysql提供了4种隔离级别,对应上述三个问题。针对隔离程度进行设置,来应付不同的需求场景情况:

    1. read uncommitted (读未提交) 没有进行任何锁限制,并发程度最高(效率最高),隔离性最低(准确性最低)
    2. read committed (读已提交) 给写加锁了,并发程度降低(速度减低了),隔离性提高了(准确性提高了)。
    3. repeatable read (可重复读) 给写和读都加锁,并发程度又降低(速度减低了),隔离性又提高了(准确性提高了)。
    4. serializable (串行化) 严格的按照串行的方式,一个一个的执行事务,并发程度最低(没有并发,速度最低),隔离性最高(准确性最高)。

    上述隔离级别是mysql内置的机制,可以直接在mysql配置文件中,修改数据库的隔离级别,来设置当前mysql 工作在哪种状态下。

     这几个隔离级别,如何选择?

    • 根据不同的实际需求/业务场景了,修改配置文件,设置不同的隔离级别。
    • 例如:转账的时候,一分钱都不能差,哪怕慢点,也得转对。准确性要拉满,效率不关键。
    • 例如:短视频点赞,一个视频有多少赞,要求快,赞的数量差个十个八个都没事。追求的是效率,准确性就不关键。
    • 如果没有通过修改mysql配置文件,手动的去设置隔离级别;默认的隔离级别是repeatable read (可重复读)。一般默认的隔离级别,就能很好的应对开发中的绝大部分场景了。


    好啦Y(^o^)Y,本节内容到此就结束了。下一篇内容一定会火速更新!!!

    后续还会持续更新MySQL方面的内容,还请大家多多关注本博主,第一时间获取新鲜的知识。

    如果觉得文章不错,别忘了一键三连哟! 

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

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

    相关文章

    华为网路设备学习-19 IGP路由专题-路由策略

    一、 二、 注意&#xff1a; 当该节点匹配模式为permit下时&#xff0c;参考if else 当该节点匹配模式为deny下时&#xff1a; 1、该节点中的apply子语句不会执行。 2、如果满足所有判断&#xff08;if-match&#xff09;条件时&#xff0c;拒绝该节点并跳出&#xff08;即不…

    基于DrissionPage的表情包爬虫实现与解析(含源码)

    目录 ​编辑 一、环境配置与技术选型 1.1 环境要求 1.2 DrissionPage优势 二、爬虫实现代码 三、代码解析 3.1 类结构设计 3.2 目录创建方法 3.3 图片链接获取 3.4 图片下载方法 四、技术升级对比 4.1 代码复杂度对比 4.2 性能测试数据 五、扩展优化建议 5.1 并…

    区间和数量统计 之 前缀和+哈希表

    文章目录 1512.好数对的数目2845.统计趣味子数组的数目1371.每个元音包含偶数次的最长子字符串 区间和的数量统计是一类十分典型的问题&#xff1a;记录左边&#xff0c;枚举右边策略前置题目&#xff1a;统计nums[j]nums[i]的对数进阶版本&#xff1a;统计子数组和%modulo k的…

    全能 Sui 技术栈,构建 Web3 的未来

    本文翻译自&#xff1a;FourPillarsFP&#xff0c;文章仅代表作者观点。 2025 年&#xff0c;SuiNetwork正在以一套全栈区块链策略强势出击&#xff0c;彻底打破加密行业的传统范式。正如 Mysten Labs 联合创始人 Adeniyi Abiodun 所说&#xff1a;“Sui 不只是一条区块链&…

    linux安装单节点Elasticsearch(es),安装可视化工具kibana

    真的&#xff0c;我安装个es和kibana&#xff0c;找了好多帖子&#xff0c;问了好几遍ai才安装成功&#xff0c;在这里记录一下&#xff0c;我相信&#xff0c;跟着我的步骤走&#xff0c;99%会成功&#xff1b; 为了让大家直观的看到安装过程&#xff0c;我把我服务器的es和ki…

    RK3xxx 部分无法连接虚拟机 无法进行adb连接

    我发现部分rk板子可以连接到虚拟机上&#xff0c;部分连接不上。其中尝试了一块是安卓系统的rk板子是可以连接虚拟机。但是用了linux系统的rk板子连接不上虚拟机。尝试了很多办法还是无法连接虚拟机。 然后也看到一些相关资料&#xff0c;但是太少了&#xff0c;只有这个链接提…

    26考研——存储系统(3)

    408答疑 文章目录 一、存储器概述二、主存储器三、主存储器与 CPU 的连接四、外部存储器五、高速缓冲存储器六、虚拟存储器七、参考资料鲍鱼科技课件26王道考研书 八、总结复习提示思考题常见问题和易混淆知识点 一、存储器概述 文章链接: 点击跳转 二、主存储器 文章链接: …

    C# 实战_RichTextBox选中某一行条目高亮,离开恢复

    C# 中控件richtextbox中某一行的条目内容高亮&#xff0c;未选中保持不变。当鼠标点击某一行的条目高亮&#xff0c;离开该条目就恢复默认颜色。 运行效果&#xff1a; 核心代码实现功能&#xff1a; //高亮指定行的方法private void HighlightLine(RichTextBox rtb,int lineI…

    Servlet小结

    视频链接&#xff1a;黑马servlet视频全套视频教程&#xff0c;快速入门servlet原理servlet实战 什么是Servlet&#xff1f; 菜鸟教程&#xff1a;Java Servlet servlet&#xff1a; server applet Servlet是一个运行在Web服务器&#xff08;如Tomcat、Jetty&#xff09;或应用…

    2025上海车展:光峰科技全球首发“灵境”智能车载光学系统

    当AI为光赋予思想&#xff0c;汽车将会变成什么样&#xff1f;深圳光峰科技为您揭晓答案。 2025年4月23日&#xff0c;在刚刚开幕的“2025上海车展”上&#xff0c;全球领先的激光核心器件公司光峰科技举办了主题为“AI光影盛宴&#xff0c;智享未来出行”的媒体发布会&#x…

    BiliNote:开源的AI视频笔记生成工具,让知识提取与分享更高效——跨平台自动生成结构化笔记,实现从视频到Markdown的智能转化

    引言:视频学习的痛点与BiliNote的解决方案 随着知识视频化趋势的加速,B站、YouTube等平台成为学习与信息获取的重要渠道,但手动记录笔记耗时低效、信息碎片化等问题依然突出。BiliNote的出现,通过AI驱动的自动化流程,将视频内容转化为结构清晰的Markdown笔记,支持截图插…

    图纸安全防护管理:构建企业核心竞争力的关键屏障

    在当今高度竞争的商业环境中&#xff0c;图纸作为企业核心技术的重要载体&#xff0c;其安全防护管理已成为企业知识产权保护体系中的关键环节。无论是建筑行业的施工蓝图、制造业的产品设计图&#xff0c;还是高科技企业的研发图纸&#xff0c;都承载着企业的核心竞争力和商业…

    借助内核逻辑锁pagecache到内存

    一、背景 内存管理是一个永恒的主题&#xff0c;尤其在内存紧张触发内存回收的时候。系统在通过磁盘获取磁盘上的文件的内容时&#xff0c;若不开启O_DIRECT方式进行读写&#xff0c;磁盘上的任何东西都会被缓存到系统里&#xff0c;我们称之为page cache。可以想象&#xff0…

    Nacos简介—2.Nacos的原理简介

    大纲 1.Nacos集群模式的数据写入存储与读取问题 2.基于Distro协议在启动后的运行规则 3.基于Distro协议在处理服务实例注册时的写路由 4.由于写路由造成的数据分片以及随机读问题 5.写路由 数据分区 读路由的CP方案分析 6.基于Distro协议的定时同步机制 7.基于Distro协…

    TCP协议理解

    文章目录 TCP协议理解理论基础TCP首部结构图示字段逐项解析 TCP是面向连接&#xff08;Connection-Oriented&#xff09;面向连接的核心表现TCP 面向连接的核心特性TCP 与UDP对比 TCP是一个可靠的(reliable)序号与确认机制&#xff08;Sequencing & Acknowledgment&#xf…

    用 LangChain 手搓 RAG 系统:从原理到实战

    一、RAG 系统简介 在当今信息爆炸的时代&#xff0c;如何高效地从海量数据中获取有价值的信息并生成准确、自然的回答&#xff0c;成为了人工智能领域的重要课题。检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;RAG&#xff09;系统应运而生&#xff0c;…

    联合体和枚举类型

    1.联合体类型 1.1:联合体类型变量的创建 与结构体类型一样&#xff0c;联合体类型 (关键字:union) 也是由⼀个或者多个成员变量构成&#xff0c;这些成员变量既可以是不同的类型&#xff0c;也可以是相同的类型。但是编译器只为最⼤的成员变量分配⾜够的内存空间。联合体的特…

    C语言指针5

    1.void*概述 void称为无类型&#xff0c;void*称为无类型指针&#xff0c;void不可以单独定义变量&#xff0c;却可以定义无类型的指针&#xff0c;而且所定义的指针称为泛型指针&#xff0c;所谓泛型指针&#xff0c;其含义是void*类型的指针可以接收一切类型变量的地址 struc…

    文档构建:Sphinx全面使用指南 — 强化篇

    文档构建&#xff1a;Sphinx全面使用指南 — 强化篇 Sphinx 是一款强大的文档生成工具&#xff0c;使用 reStructuredText 作为标记语言&#xff0c;通过扩展兼容 Markdown&#xff0c;支持 HTML、PDF、EPUB 等多种输出格式。它具备自动索引、代码高亮、跨语言支持等功能&#…

    深度理解C语言函数之strlen()的模拟实现

    文章目录 前言一、strlen的模拟实现二、模拟实现代码及思路2.1 计数法2.2 指针相减法三、递归计数法 总结 前言 我写这篇文章的目的主要是帮助理解C语言中重要函数的用法&#xff0c;后面也会总结C相关的函数的模拟实现&#xff0c;这里的算法不一定是最好的&#xff0c;因为只…