news 2026/8/9 3:16:07

测试开发-MySQL学习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
测试开发-MySQL学习

提示:适用于想要学习测开方向的MySQL知识的学习,完全够用

SQL语句分类

DDL:数据定义语言,用来定义数据库对象(库,表,字段)

DML:数据操作语言,增删改

DQL:数据查询语言,查询数据库中表中的记录

DCL:数据控制语言,创建数据库用户,控制用户访问权限

查询字段去除重复数据

selectdistinct字段 from 表名

数值函数

ceil(x) 向上取整

floor(x) 向下取整

mod(x,y) 返回x/y的模

rand() 生成0-1之间的随机数

round(x,y) 求参数四舍五入的值,保留y位小数

字符串函数

字符串截取之substring_index(str,delim,count)

str:要处理的字符串

delim:分隔符

count:计数

日期函数

curdate() 获取当前的年月日

curtime() 获取当前的时分秒

now() 获取当前的年月日-时分秒

year(date) 获取指定date的年份

month(date) 获取指定date的月份

day(date) 获取指定date的日数

date_add(date,interval expr type) 在指定的date上增加一个时间间隔expr后的时间值(ytpe单位,年月日)

datediff(date1,date2) 返回两个日期之间相差的天数

流程控制函数

if(value,t,f) 如果value为真则输出t否则f

ifnull(value1,value2) 若value1不为空,返回value1,否则返回value2

case when [val] then [1] else [2] end 若val为真则返回1否侧返回2

case [expr] when [val1] then [1] else [2]

约束

非空约束 not null 限制阻断数据不能为null

唯一约束 unique 保证字段的数据都唯一,不重复

主键约束 primary key (配用auto_increment 一行数据的唯一标识,非空且唯一

外键约束 foreign key 用来让两张表之间建立连接,抱持数据的完整性和一致性

这里需要注意的是,有具有外键的表为子表,外键所关联的表为父表

添加外键:

1.create table 表名 (

字段1 类型 constrant [外键名称] foreign kry (外键字段名) references 主表(字段)

2.alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表(关联字段)

删除外键:

alter table 表名 drop foreign key 外键名称;

删除/更新行为

alter table 表名 add constraint 外键名称 foreign key (外键字段名称) references 主表(关联字段)

默认约束 default 保存数据时,如果未指定字段值的值,则用默认值

检查约束 check 抱持字段满足某一个条件

多表查询

一对多(多对一)

例如:员工和部门之间的关系

解决方案:添加外键关联

多对多

例如:学生和选课之间的关系

添加中间表对应

一对一

例如:个人基本信息和个人其他信息的关系

多表查询分类:

连接查询:

内连接:

查询表A,B的交集部分

隐式内连接:

select 字段列表 from 表1,表2 where 条件;

显示内连接:

select 字段列表 from 表1 [inner] join 表2 on 条件;

外连接:

左外连接:

select 字段列表 from 表1left[outer] join 表2 on 条件;

(查询的是表1和表2共同的数据,以及表1的所有数据)

右外连接:

select 字段列表 from 表1right[outer] join 表2 on 条件;

(查询的是表1和表2共同的数据,以及表2的所有数据)

自连接:

当前表与自身连接查询,自连接必须用别名

select 字段列表 from 表1 别名1 join 表1 别名2 on 条件;

自连接可以是内自连接也可以是外自连接

连结查询

select 字段列表 from 表A

union [all]

select 字段列表 from 表B

union all / union

union all 数据整合不去重

union 去重

注意:连结查询的多张表必须字段列数抱持一致,字段类型也抱持一致。

子查询

标量子查询:子查询的结果为的单行单列(单个值)

常见的操作符为:> ,>=,< ,<=,=,<>

列子查询:子查询的结果为一列(可以是多行)

常见的操作符为:in,not in,any=some(子查询返回的列表中,有一个满足即可),all(子查询返回的列表中,必须所有的满足)

行子查询:子查询的结果为一行(可以是都多列)

常见的操作符为:=,<>,in not in

表子查询:子查询的结果为多行多列

常见的操作符为:in

---------------------------------------------------------------------------------------------------------------------------------

这里我们重点讲解一下分组查询:group by

可能在进行多表连结完之后再进行分组完之后,对于初学者来说可能会犯蒙,并且只有select指定的字段时才能查看其图,但是我们对它原本分组之后的构造却不清晰,这里我们来讲解一下。

首先第一点:分组之后select的字段的条件:

1.必须是group by 分组字段

2.聚合函数(count/avg/distinct)

这一点很重要,查询其他的字段则会报错

第二点:这里我们举例子讲解

用户信息表 user_profile:

device_iduniversity
2138北京大学
3214复旦大学
6543北京大学
2315浙江大学
5432山东大学
2131山东大学
4321复旦大学

答题情况明细表question_practice_detail,其中question_id是题目编号,result是答题结果。

device_idquestion_id
2138111
3214112
3214113
6543111
2315115
2315116
2315117
5432118
5432112
2131114
5432113

要求:取出学校答过题的用户平均答题数量情况数据

1.首先进行内连接之后再分组

select ? from user_profile as us ,question_practice_detail qpd where us.device_id=qpd.device_id group by university;

那么上方分组后的逻辑到底是怎样的呢?

其实分组之后你不取select特定的字段,它不算一个表,而是四个独立的组,它只是一个逻辑

分组名称(university)组内包含的所有原始行(共 11 行,按学校拆分)组内关键统计(为后续计算用)
北京大学

行 1:2138、北京大学、111

行 2:6543、北京大学、111

总行数 = 2

去重 device_id 数 = 2

复旦大学

行 3:3214、复旦大学、112

行 4:3214、复旦大学、113

总行数 = 2

去重 device_id 数 = 1

浙江大学

行 5:2315、浙江大学、115

行 6:2315、浙江大学、116

行 7:2315、浙江大学、117

总行数 = 3

去重 device_id 数 = 1

山东大学

行 8:5432、山东大学、118

行 9:5432、山东大学、112

行 10:2131、山东大学、114

行 11:5432、山东大学、113

总行数 = 4

去重 device_id 数 = 2

👉 核心理解:

  • 分组后不存在 “新的行”,而是把原始行 “归类到不同的组里”;
  • 每个组的边界是university,组内是该学校的所有答题记录;
  • 数据库执行group by后,会 “以组为单位” 处理数据(比如用聚合函数统计每组的总行数、去重用户数)。

事务

简介:事务是一组操作的集合,是一个不可分割的单位。它可以把一系列操作作为一个整体向系统发起提交或者撤回。要么同时成功,要么同时失败。

(注意:默认的MySQL是自动提交的,也就是说,当执行一条DML语句,MySQL会隐式提交。)

事务的操作:

查看事务的提交方式:

select @@autocommit;

设置事务的提交方式:

set @@autocommit=0(手动提交,提交是需要commit;)

此处需要注意的是,一但开启手动提交,则当前会话的所有的提交都为手动提交

若只想开启一个临时的事务块,则:

start transaction;(或者begin) ---仅对事务开启后,commit/rollback之前的语句有效

回滚:

rollback;

事务的四大特性:

原子性:事务是不可分割的最小操作单元,要么全部成功,要么全部失败

一致性:事务完成时,必须使所有数据保持一致状态

隔离性:数据库事务的隔离机制,保证事务不受外部并发操作的影响

持久性:一旦提交或者回滚,对数据的操作是永久的

并发事务的问题:

脏读:一个事务读取到另一个事务还没有提交的数据

不可重复读:一个事务先后读取同一条数据,但是两次的数据不一样

幻读:一个事务内多次执行同一范围查询,但两次查询之间,另一个事务提交了插入 / 删除操作,导致查询结果集的行数变化(核心是 “插入 / 删除” 操作引发)

事务隔离级别:

隔离级别脏读不可重复读幻读并发性能适用场景
READ UNCOMMITTED(读未提交)最高几乎不用(仅测试)
READ COMMITTED(读已提交)较高多数 OLTP 场景(Oracle 默认)
REPEATABLE READ(可重复读)中等MySQL 默认(推荐)
SERIALIZABLE(串行化)最低数据一致性要求极高的场景

READ UNCOMMITTED:会出现脏读问题,事务A会读取事务B未commit的数据

READ COMMITTED(读已提交):解决事务的脏读问题。但是会出现不可重复读问题。同样一个SQL在同一个事务中查询不一致。

REPEATABLE READ:解决不可重复读问题。即使事务B对数据库做出操作,但是事务A两次查询结果都一样,只有事务A最后commit才最终修改。但是解决不了幻读问题。

serializable(串行化):解决幻读问题。强行阻塞一个事务A的运行,只有等事务B commit之后才显示SQL结果

-- 查看事务的隔离级别:

select @@transaction_isolation

-- 设置事务的隔离级别

set [session/global] transaction isolation level [read uncommited/read commited/repeatable read/serializable]

存储引擎

MySQL体系结构:

客户端连接器:

  • 是什么:用户(或程序)连接MySQL的“桥梁”,比如Python/PHP/Java代码、Navicat工具、甚至Excel插件。

  • 类比:你用“图书馆APP”“实体借书卡”“微信小程序”借书——不同工具对应不同的“连接方式”(图中的Native C API、JDBC、ODBC、.NET、PHP、Python等)。

  • 作用:把用户的请求(比如“查用户表”)转换成MySQL能理解的格式,传给下一层。

连接层:

包含认证、线程复用、连接限制、内存检查、缓存

  • 认证:验证“读者身份”——比如你用MySQL账号root/123456登录,连接池会查“用户表”确认密码对不对。

  • 线程复用:避免“每个请求都开新线程”——比如100个读者同时查书,接待处不会开100个新员工,而是用“复用线程”(比如5个员工轮流处理),节省资源。

  • 连接限制:控制“同时进馆人数”——比如MySQL设置max_connections=100,超过100人就排队,防止服务器崩溃。

  • 缓存:存“常用信息”——比如“热门查询的结果”“用户权限”,不用每次都查数据库。

服务层:

这是MySQL的“大脑”,处理所有请求的核心逻辑,包含4个模块:

  • ① SQL接口:“接收读者的问题”——处理所有SQL语句(比如SELECT/INSERT/UPDATE)、存储过程、视图、触发器。

  • ② 解析器:“翻译+权限检查”——把你的SQL翻译成MySQL内部指令(比如SELECT * FROM user→“查user表的所有列”),还要检查你有没有权限(比如“普通用户不能查管理员表”)。

  • ③ 查询优化器:“找最快的找书路线”——比如你要查“年龄>18的用户”,优化器会选“用年龄索引”还是“全表扫描”(就像导航选“地铁”还是“打车”),目标是最快返回结果

  • ④ 缓存:“常用结果暂存”——如果100个人都查“热门书籍”,缓存会把结果存起来,第101个人查的时候直接返回,不用再查书库。

引擎层:

可插拔存储引擎,是MySQL最核心的“数据存储层”,包含InnoDB、MyISAM、Memory等引擎:

  • 是什么:不同的“书库管理方式”——比如:

    • InnoDB:支持事务(比如“买东西时,扣钱和加库存必须同时成功/失败”)、行锁(改一行数据时,不影响其他行),是现在的默认引擎(比如淘宝、微信的用户数据都用它)。
    • MyISAM:不支持事务,但查询快(比如以前的论坛帖子,主要是查,不用改),但崩溃后容易丢数据。
    • Memory:数据存在内存里(比如临时统计数据),速度极快,但重启MySQL就没了。
  • 关键特点可插拔——你可以随时把“文学书库”换成“工具书库”(比如把表引擎从InnoDB改成MyISAM),不用改上面的服务层。

存储层:

包含系统文件文件日志,是数据的“物理存储”:

  • 系统文件:比如NTFS、ext2/3文件系统(Windows/Linux的磁盘格式),就像图书馆的“书架材质”——用什么方式存文件。
  • 文件日志:记录所有操作的“历史账本”,包括:
    • Redo日志(重做日志):比如你改了一条数据,先写Redo日志,再写数据文件——万一断电,用Redo恢复数据(就像图书馆的“操作记录”,万一书被烧了,能重新买一本)。

    • Undo日志(回滚日志):比如你执行UPDATE没提交,想撤销——用Undo恢复到之前的状态(就像“撤销键”)。

    • Binary日志(二进制日志):记录所有“修改数据的操作”(比如INSERT/UPDATE/DELETE),用来做主从复制(主库的日志传给从库,从库重放操作,保持数据一致,就像图书馆的“副本账本”)。

用“查用户数据”的场景,串起全流程

现在你用Python程序查“id=1的用户姓名”,整个过程是这样的:

  1. 客户端连接器:Python通过JDBC连接MySQL(就像用APP连图书馆)。

  2. 连接层:连接池验证Python的账号密码(认证),分配一个线程(接待员),检查连接数没超限制。

  3. 服务层

    • SQL接口接收请求:SELECT name FROM user WHERE id=1
    • 解析器翻译SQL,检查你有没有查user表的权限。
    • 查询优化器决定:用id的索引(如果有的话),比全表扫描快。
    • 缓存检查:有没有人之前查过这个id?如果有,直接返回缓存结果。
  4. 引擎层:如果缓存没有,InnoDB引擎去存储层找id=1的记录(就像去书库找书)。

  5. 存储层:从磁盘文件里读出数据,返回给引擎层,再传给服务层,最后给Python程序。

存储引擎简介:

创建表的时候指定存储引擎:

create table 表名(

字段1,类型,【注释】

...

)engine=innodb [注释]

查看数据库支持的引擎:

show engines;

InnoDB存储引擎:

特点:支持事务(ACID),行级锁(提高并发访问性能),外键(抱持数据的完整性一致性)

文件:xxx.ibd(xxx为表名)

MySIAM存储引擎:MySQL早期默认存储引擎

特点:

不支持事务

不支持行级锁,支持表锁,

没有外键

访问速度快

文件:

xxx.sdi:存储表结构信息

xxx.MYD:存储数据

xxx.MYI:存储索引

Memory存储引擎:表数据存储在内存中,受硬件,断电影响,只能将这些表作为临时表或者缓存使用

特点:

内存存放

hash索引

文件:

xxx.sdi:存储表结构信息

索引:帮助MySQL高效获取数据的数据结构

优点:提高查询效率,排序效率

索引结构:

B+Tree索引:最常见的索引,大部分引擎都支持B+树索引

hash索引:底层数据结构使用hash表实现的,只有精确匹配索引列的查询有效,不支持范围查询(between ,<,>,...)

R-Tree索引(空间索引):MySIAM引擎支持的特殊索引类型,主要用于地理空间数据类型,使用叫较少

Full-text索引(全文索引):是一种建立倒排索引,快速匹配文档的方式

索引的分类:

按照【物理存储】分类(InnoDB专属)

聚集索引(必须有,且只能有一个):将数据存储和索引放到一块,索引结构的叶子节点保留了行数据

二级索引(可以存在多个):将索引和数据分开存储,索引结构的叶子节点关联的对应的主键

聚集索引的选取规则:

如果存在主键,则主键索引就是聚集索引

如果没有主键,则第一个唯一索引(unique)作为聚集索引

如果没有主键,也没有合适的唯一索引,则INnoDB会自动生成一个rowid作为隐藏的聚集索引

最后,我们来讲解一下,到底什么是索引?我们可以想象一下,如果我们没有创建索引,也就是只有一张表,那么我们查找某些数据的时候就是全局扫描,查找效率很慢。但是如果我们对一张表创建了索引的话,索引就是一种数据结构,一种算法,来帮助我们快速检索,提高查找速率。

索引语法

创建索引:

create [unique/fulltext] index 索引名称 on 表名(字段1,...);

(删除索引:drop index 索引名称 on 表名)

查看索引:

show create index from 表名;

删除索引:

drop index 索引名称 on 表名;

索引-性能分析

SQL执行频率

show [global/session] status like 'com_______(七个下划线)';

慢查询日志

查询慢查询日志是否开启:

show variables like 'slow_query_log';

开启MySQL慢查询日志:

show_slow_log=1;

设置慢日志的时间为2秒,如果查询时间超过2秒,则会被记录:

long_query_time=2;

profile详情

show profile能够帮助我们在做SQL优化的时候时间都消耗在哪里,通过have_profile参数,能够查看当前MySQL是否支持profile参数

select @@have_profiling;

select @@profiling;(0表示关闭,1表示开启)

默认的profiling是关闭的,我们可以通过set语句在[global/session]级别开启profiling

set 【global/session】 profiling=1;

查看每一条SQL语句的耗时情况:

show profiles;

查看指定的query_id在各个阶段的耗时情况::

show profile for query query_id;

查看指定的query_id 在cpu的使用情况:

show profile cpu for query query_id;

explain执行计划:

explain/desc可以详细查看select的执行语句,包括如何连接和连接顺序

直接在select语句前加上explain执行语句

索引的使用

最左前缀法则

如果使用了联合索引,就要遵守最左前缀法则,即查询从索引的最左侧的字段开始,并且不跳过某一列,如果跳过了,则会部分索引失效(后面的字段索引失效)

注意:最左侧的列必须存在,如果不存在,则全部的索引失效

不能在索引列上进行运算操作 ,否则索引将失效
字符串索引使用时,不加引号,索引失效
联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。

所以,在业务允许的情况下,尽可能的使用类似于>=<=这类的范围查询,而避免使用><

尾部模糊查询,索引不会失效,首部模糊查询,索引会失效
如果用or的连接条件,只要有一侧没有索引,则整个索引都会失效
数据评估影响:如果MySQL优化器在评估我们的sql语句时,使用索引比全表更慢,则不使用索引
SQL提示:是优化数据库的重要手段,通过加入一些人为提示来达到SQL优化的目的
user index 建议使用

explain select * from 表名 use index(索引名称) where ...

ignore index 不使用

explain select * from 表名 ignore index(索引名称) where ...

force index 强制使用

explain select * from 表名 force index(索引名称) where ...

覆盖索引:

在查询的时候,尽量使用覆盖索引,即查询的字段在索引都都可以找到,避免使用*查询

前缀索引:

当字段类型为字符串的时候,有时候需要索引很长的字符串,会让索引变得很大,查询时浪费磁盘I/O资源。此时可以只取字符串的一部分作为前缀,节省索引空间,提高索引效率

语法:create index 索引名称 on 表名(字段(n));

索引长度可根据选择性决定。选择性越高,索引效率越高。唯一索引的选择性是1,性能最好

select count(distinct 字段 )/count(*) from 表名 ;

select count(distinct substring(字段名,起始位置,截至位置))/count(*) from 表名;

SQL优化

插入数据

1.批量插入

2.手动提交事务

3.主键顺序插入

如果一次性插入大量数据,使用insert语句效率会很低,此时可以使用MySQL提供的load指令

##客户端连接MySQL服务器时,加上参数--local-infile(MySQL 默认出于安全考虑,禁止客户端读取本地文件并发送给服务器,所以必须加这个参数才能用批量导入功能)

mysql--local-infile -u root -p

##设置全局参数为1,开启从本地读取数据的开关

(查看开关是否开启:select @@local_infile;)

set global local_infile=1;

##执行load指令将准备好的数据加载到表结构中

load data local infile '要读取的文件地址' into table 表名 fileds terminated by '字段之间如何分割' lines terminated by '每行之间如何分割'

主键优化

1.满足业务需求的情况下,尽量降低主键的长度

2.主键顺序插入,选择auto_increment自增

3.尽量不要使用UUID(不重复的无序的随机字符串)或者其他作为主键,比如身份证号

4.业务操作时,避免对主键的修改

order by优化

using filesort:不是利用索引排序的,而且在缓冲区sort_buffer中排序然后再返回

using index:利用索引本身的有序性

1.根据排序字段建立合适的索引,多字段排序时,也需要遵循最左前缀法则

2.尽量使用覆盖索引

3.多字段排序(一个升序,一个降序)此时需要注意联合索引在创建的时候的规则

4.如果不可避免出现filesort,大量数据排序时,可以适当增加缓冲区大小

group by优化

1.在分组时可以建立索引来提高效率

2.分组操作时,索引的使用也满足最左前缀法则

limit优化

如果查询分页的数据特别大时,比如limit 2000000,10,此时MySQL会优先对前200000条数据进行扫描丢弃,,然后返回第20000001到第20000010条记录,查询排序的代价非常大

优化思路:覆盖索引+子查询

count优化

按照效率排序:

count(字段)<count(主键)<count(1)<count(*)

update优化:

InnoDB引擎针对索引加的是行锁,如果更新的字段没有加索引,则会升级为表锁,把整张表都锁住。一旦升级为表锁,则并发性能会降低

视图:

视图是一种虚拟存在的表,行和列数据来自于创建视图时所查询的表,并且是在使用视图时动态生成的。

创建:

create view 视图名称(列名列表) as select语句 【with (cascaded/local) check option】

查询视图:

查看创建视图语句:show create view 视图名称;

查看试图数据:select * from 视图名称;

修改视图:

alter view 视图名称(列名列表) as select语句 【with (cascaded/local) check option】;

replace view 视图名称(列名列表) as select语句 【with (cascaded/local) check option】;

删除视图:

drop view [if exists] 视图名称;

视图-检查选项

with check option:

限制通过视图插入 / 更新的数据必须满足视图的WHERE条件(防止插入 / 更新后数据 “消失” 在视图中)。


cascaded(级联,MySQL 默认):

当视图基于其他视图创建时,会检查本次以及所有底层视图的 WHERE 条件(当前视图 + 所有依赖的视图)。


无with check option(即无 cascaded):

不做任何条件检查,可插入 / 更新不符合视图条件的数据(插入后数据不会出现在视图中,但会写入基表)。

关键规则:即使某个视图没有with check option,但如果它基于的上游视图有check option,那么上游视图的检查规则仍然会生效。

向视图中插入数据,由于视图是不存在的,是基于基表创建的,所以实际是向基表中插入数据

1.cascaded(级联的)

2.global:不会将这个检查效果传递给其他视图

视图:更新及作用

视图的更新:

要是视图可以更新,必须使视图中的行与基础表中的行存在一对一的关系

视图的作用:

简单:简化用户操作。那些经常被使用的操作可以定义为视图,从而用户不必为以后的操作指定全部的条件

安全:通过视图用户只能查看和修改用户权限所能看到的数据

数据独立:视图可以帮助用户屏蔽基础表的变化

锁的本质:

锁是mysql为了解决并发访问数据冲突而设计的机制

锁的分类:

按照锁的粒度分:

全局锁:每次锁定数据库中所有的表

表级锁:只锁定一张表

行级锁:只锁定一行数据

全局锁:

全局锁的主要用途是全库逻辑备份(比如用mysqldump导出全部数据),目的是保证备份过程中数据的一致性。仅允许读,阻塞所有写

加锁:flush tables with read lock;

备份数据:mysqldump -uroot -p(密码)数据库名 > 所要导入的文件名.sql

解锁:unlock tables;

缺点:全局业务锁定,不能进行插入更新,业务基本停摆

代替:在innodb引擎中,我们可以添加参数single-transaction来完成无锁备份(MVCC(多版本并发控制)+一致性快照)

mysqldump --single-transaction -uroot -p(密码)数据库名 > 所要导入的文件名.sql

表级锁:

发生锁冲突的概率最大,并发度最低,应用在myisam,innodb中
分类:
表锁:

表共享读锁(read lock):

只能读,不能写

表独占写锁(write lock):

只有自己可以读和写,其他人不能读写

语法:

加锁:lock tables 表名...read/write;

解锁:unlock tables /断开客户端连接

元数据锁(meta data lock MDL):

隐藏的表级锁:MySQL 5.5 + 默认自动加,无需手动操作,用于保护表结构(防止读数据时表结构被修改)

触发场景:

执行select/insert/update/delete时,自动加 MDL 读锁(注意与全局锁的读锁区分);

执行altertable/drop table时,自动加 MDL 写锁(注意与全局锁的写锁区分);

核心特点:MDL 读锁之间不互斥,但 MDL 写锁会阻塞所有 MDL 读锁(比如改表结构时,所有读 / 写操作都会被阻塞)。

意向锁:

┌─────────────────────────────────────────────────────────┐ 核心特点 │ ├─────────────────────────────────────────────────────────┤ ✅ 表级锁(锁的是整个表,但目的是声明行锁意图) │

│ ✅ 不与行级锁冲突(这是关键!) │

✅ 自动加锁,无需手动干预 │

│ ✅ 提高锁冲突判断效率 │ └─────────────────────────────────────────────────────────┘

主要解决表锁和行锁的冲突问题

意向共享锁(IS):与表级共享锁(read)兼容,与表级排他锁(write)互斥

意向排他锁(IX):与表级共享锁(read)和排他锁(write)都互斥

行锁:

每次操作锁住对应行的数据,锁粒度最低,并发程度最高,发生锁冲突概率最低。innodb专属

innodb的数据是基于索引所致的,行锁是对索引项加锁,而不是对记录加锁

分类:
行锁:

锁定单个行记录,防止其他事务进行update和delete,在repeatable read和repeatable comment隔离级别支持

1.共享锁(S):允许一个读,不允许排他锁

2.排他锁(X):不允许共享锁和排他锁

innodb引擎的行锁是对索引加的锁,如果没有索引,则innodb会升级为表锁

间隙锁:

锁定索引之间的间隙,防止其他事务在这个间隙之间insert,产生幻读。在repeatable read的隔离级别下支持

临键锁:

行锁和间隙锁的组合。在RR隔离级别下支持

InnoDB引擎

逻辑存储结构

架构

缓冲池(Buffer Pool)是什么?

  • 缓冲池就是内存里的一块“临时仓库”。

  • 它用来存放磁盘上的真实数据,这样当你读、改、删数据时,不必每次都去慢慢读硬盘。

  • 操作顺序:

    1. 先看缓冲池里有没有数据。

    2. 如果没有,就从磁盘读入并缓存。

    3. 然后再按一定频率,把修改后的数据刷回磁盘。

  • 好处:减少磁盘操作,提高处理速度。

2. 缓冲池是怎么管理数据的?

  • 缓冲池按页(Page)来管理数据,每页是固定大小的一块数据。

  • 每页可以是三种状态:

    1. 空闲页(free page):这页没用过,可以直接存新数据。

    2. 干净页(clean page):这页已经用过,但是数据没有改过,和磁盘上的数据是一致的。

    3. 脏页(dirty page):这页被修改过了,内存里的数据和磁盘上的不一致,需要以后刷新回磁盘。

3. 图中几个部分

  • Buffer Pool(缓冲池):存放数据库数据的内存区域。

  • Change Buffer(变化缓冲区):暂存一些修改操作。

  • Log Buffer(日记缓冲区):记录数据变化,保证数据安全。


简单说,缓冲池就像内存里的小仓库,帮你快速操作数据,减少慢慢访问硬盘的次数。不同的页状态就是为了知道哪些数据可以直接用,哪些需要更新到硬盘。

事务原理

事务是一组操作的集合,是不可分割的单位。这些操作要么同时成功,要么同时失败

四大特性:

原子性 隔离性 持久性 一致性

redo log:

重做日志。记录用户修改数据的记录,用来实现事务的持久性

该日志文件由两部分组成:

重做日志缓冲(red0 log buffer),重做日志文件(redo log file)。前者储存在内存中,后者储存在磁盘中

undo log:

回滚日志,用来记录数据修改之前的信息。作用包含两个:提供回滚和MVCC(多版本并发控制)

MVCC(多版本并发控制)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 15:28:10

62.不同路径

一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。问总共有多少条不同的路径&#xff1f;class Solut…

作者头像 李华
网站建设 2026/7/14 15:28:13

DOM DocumentType 概述

DOM DocumentType 概述DocumentType 是 DOM&#xff08;文档对象模型&#xff09;中的一个接口&#xff0c;表示文档的文档类型声明&#xff08;DOCTYPE&#xff09;。它包含文档类型名称、公共标识符&#xff08;publicId&#xff09;和系统标识符&#xff08;systemId&#x…

作者头像 李华
网站建设 2026/7/14 15:28:14

go面经(2)

&#xff08;本文面经来自牛客大佬&#xff09;得物go后端校招二面面经1、协程和进程 2、goroutine过多的问题 3、客户端到服务端的完整链路 4、负载均衡的策略 5、缓存和数据库一致性的问题 6、先删缓存再删数据库会有什么问题 7、消息队列的用处和可能出现的问题 8、设计一个…

作者头像 李华
网站建设 2026/7/14 15:28:14

DC-DC vs AC-DC:如何为你的电子项目选择正确的电源转换器?

DC-DC vs AC-DC&#xff1a;如何为你的电子项目选择正确的电源转换器&#xff1f; 你是否曾经面对一个电子项目&#xff0c;看着手边一堆电源模块&#xff0c;却不确定该用哪一个&#xff1f;或者&#xff0c;在为一个新想法采购元件时&#xff0c;面对琳琅满目的“降压模块”、…

作者头像 李华