数据库面试题小结

数据库

内外连接的区别?

内连接:通过条件查询,两个表求交集(结果求交集,条件都满足)

外连接:左外连接,右外连接,全外连接

​ 左外连接:左表查询出来的结果在结果集中一定有,右表不满足的用null代替

​ 右外连接:右表查询出来的结果在结果集中一定有,左表不满足的用null代替

​ 全外连接:左表和右表的并集

SQL语言包括哪些类型?

  • DDL:数据定义语言 — 定义修改数据库结构
  • DML:数据操作语言 — 增删改
  • DQL:数据查询语言 — 查
  • DCL:数据控制语言 — 权限
  • TCL:事务控制语言

SQL约束有哪几种?

  • 主键约束 : primary
  • 唯一约束 : unique
  • 外键约束 : foreignkey
  • 非空约束 : not null
  • 检查约束 : check
  • 默认约束 : default

视图的作用是什么?视图可以更改吗?

视图是虚拟表,并不是真实存在的,主要用来存储查询语句的返回结果;视图实际上是存储查询,并不存储数据本身,当基本表的数据发生更改时,视图会自动反应变化

作用:

1.简化复杂查询

2.限制用户查询查询子集,保证数据的安全性

3.视图提供逻辑数据独立性,当基础表的结构发生变化时,如果这些变化被隐藏在视图后面

更改:

1.间接改变视图:当基本表改变时,视图中对应数据会自动反映

2.直接改变视图:取决于视图的类型和定义,某些视图是支持更新操作的,但大多数情况下,尤其是那些包含JOIN、GROUP BY等复

杂操作的视图,是不可更新的。直接改变视图(可以看作一张表)时,有时候会检查条件是否满足,这主要取决于查询语句有没有检

查条件,cascade会级联检查关联的视图,local仅检查当前视图的条件。

什么是事务和锁?

  • 事务:是一组不可分割的原子操作,要么全部成功,要么全部失败。有ACID四个特性,包括原子性、一致性、持久性、隔离性。
  • 锁:是数据库管理系统控制并发访问的核心机制,通过限制多个事务同时操作共享资源(如数据行、表等),确保数据的一致性和完整性。主要用来解决脏读、不可重复读、幻读;锁主要有两种,排他锁和共享锁。

事务的四大特性实现原理是什么?

(ACID)

  • 原子性:事务的所有操作要么全部完成,要么全部不完成,不存在中间状态。主要通过undolog(回滚日志)来实现,记录事务对数据修改的反向操作,用于回滚事务未提交或失败的事务。
  • 持久性:事务提交后,对数据的修改是永久的,即时系统崩溃也能恢复。主要通过redolog(重做日志)和 Binary Log(Binlog,二进制日志),redolog记录物理层面的数据修改,用于崩溃恢复时重建数据;Binary记录数据库的逻辑变更(如SQL语句),用于主从复制和数据恢复。
  • 隔离性:事务之间互不干扰,一个事务的中间结果对其他事务不可见。主要通过锁机制和MVCC实现。
  • 一致性:事务执行前后,数据库从一个合法状态转换到另一个合法状态,符合业务规则(如约束、触发器等)。依赖其他三个特性。

  • 读未提交:最低隔离级别,允许事务读取其他事务未提交(未提交即可能回滚)的数据。可能会出现脏读、不可重复读、幻读
  • 读已提交:事务只能读取其他事务已提交的数据。可能会出现不可重复读和幻读。
  • 可重复读:事务内多次读取同一数据的结果始终一致(除非本事务自己修改)。可能会出现幻读
  • 串行化:最高隔离级别,事务串行执行,完全避免并发问题。

脏读、不可重复读、幻读是什么?

  • 脏读:读到另一个事务未提交数据
  • 不可重复读:同个事务中读取同一数据结果不一样。
  • 幻读:事务内多次查询同一条件的结果集数量不一样

锁的分类有哪些?

  • 按锁的粒度分:页级锁、表级锁、行级锁
  • 按锁的模式分:排他锁、共享锁、意向锁
  • 按使用方式划分:悲观锁、乐观锁
  • 特殊锁类型:间隙锁、临键锁、元数据锁

悲观锁有哪些劣势?

1.悲观锁在事务开始时就对数据加锁,直到事务结束才释放锁。在高并发场景下,多个事务对同一资源的请求会被阻塞,导致系统吞吐量降低。

2.有死锁风险,多个事务互相等待对方释放锁,循环等待,导致系统僵局

3.会造成其他线程阻塞和等待,用户体验差

索引的缺点是什么?

1.占用一定的存储空间

2.写操作变慢,在进行写操作时,也要同步维护索引

3.维护成本变高

索引的分类有哪些?

  • 按索引性质分:唯一索引、主键索引、普通索引
  • 按数据结构分:B+树索引、Hash索引、全文索引
  • 按字段范围分:单列索引、联合索引
  • 按存储位置分:聚簇索引、非聚簇索引
  • 按其他特性分:覆盖索引、空间索引、前缀索引

聚簇索引的实现原理是什么?为什么使用聚簇索引?

聚簇索引底层的数据结构是B+树,MySQL数据库对其进行了优化,添加了指向相邻节点的指针,其核心特点是数据行的物理存储顺序与索引键的逻辑顺序一致。聚簇索引支持范围查询,且非叶子结点存储键值,可以存储更多的数据,每个结点可以有多个子节点,所以树的层级较浅,查询速度快。通过数据与索引物理合一的结构,显著提升了范围查询、主键查询和关联操作的性能,但需权衡写入开销和主键设计

数据库如何优化性能?

1.对常用于查询、排序、分组的字段建立索引

2.对查询频繁的表建立索引

3.尽量使用联合索引。减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省空间

4.减少 I/O:通过索引、缓存和分区。

5.降低锁竞争:优化事务和并发控制。

6.持续监控与调优:根据实时数据调整策略。

索引如何优化?

  1. 针对于数据量较大,且查询比较频繁的表建立索引。
  2. 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
  3. 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
  4. 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
  5. 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
  6. 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
  7. 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

如何优化关联查询?

1.选择合适的连接类型。

2.在关联字段上考虑建立索引

3.尽可能的缩小查询范围

为什么要分库分表?

分库分表的核心目的是解决单库单表的性能瓶颈和扩展性问题:

  • 提升性能:数据量过大时,单表查询、索引效率下降,分表减少单表数据量;单库高并发时分库分散连接压力,提升吞吐量。
  • 扩展性:通过水平扩展(增加服务器)替代垂直扩展(升级硬件),更灵活应对业务增长。
  • 可用性:分布式架构下,单节点故障不影响整体服务,提升容错能力。
  • 资源优化:垂直分表按字段拆分冷热数据(如用户核心信息与扩展信息分离),降低存储成本并加速高频查询。
  • 数据隔离:按业务或时间分库分表,便于独立维护、备份和迁移,同时增强安全性(如敏感数据隔离)。

分库分表有几种方法?

1.分表方法:

  • 垂直分表:按字段拆分,将关联性弱的字段分到不同表(如用户表拆分为基本信息表和扩展表)。
  • 水平分表:按数据行拆分,将数据分到多个表中,常见策略包括:
  • 哈希分片:根据主键哈希值分配(如用户ID取模)。
  • 范围分片:按时间或字段范围划分(如按月份分订单表)。
  • 一致性哈希:动态扩展分片,减少数据迁移成本。

2.分库方法:

  • 按业务模块分库:将不同业务拆分为独立库(如订单库、用户库),降低耦合并提升专库专用的效率。
  • 按数据分片分库:结合水平分表,将数据分布到多个数据库实例,需配合中间件(如ShardingSphere)管理路由。

如何保证多个主从数据库之间的数据一致?

通过以下机制实现数据同步与一致性:

1.主从复制:

  • 异步复制:主库不等待从库确认,延迟低但可能丢失数据。
  • 半同步复制:主库等待至少一个从库确认后再返回,平衡延迟与可靠性。
  • 全同步复制:主库等待所有从库确认,延迟高但数据零丢失(需权衡性能)。

2.中间件管理:

  • 使用ShardingSphere等工具统一管理分片数据,确保分片间数据路由和事务一致性。
  • 定期校验数据(如_checksum校验),修复主从不一致问题。

3.冲突处理:

  • 避免跨分片事务,或通过分布式事务(如Seata)保证最终一致性。
  • 通过唯一约束和幂等设计减少数据冲突。

数据库并发造成的读问题有哪些?如何解决?

常见问题:

  • 脏读、不可重复读、幻读:事务隔离级别不足导致读到未提交或中间状态的数据。

  • 锁竞争:高并发读写时,行锁或表锁导致读请求阻塞。

  • 热点数据读慢:频繁访问同一数据页,导致缓存命中率低或锁竞争加剧。

解决方案:

  1. 调整事务隔离级别:使用READ COMMITTED(默认)或REPEATABLE READ(InnoDB默认)避免脏读和不可重复读。
  2. 优化索引与查询:确保查询命中索引,减少全表扫描和锁范围。
  3. 读写分离:将读请求分发到从库,降低主库压力(需处理主从延迟问题)。
  4. 缓存加速:使用Redis/Memcached缓存高频读数据,减少直接访问数据库。
  5. 水平扩容:通过分库分表分散读压力,避免单点成为瓶颈。
  6. 减少热点:采用哈希分片分散热点数据,或设计业务逻辑避免集中访问。

数据库的三范式是什么?

1NF:数据库表中的字段必须是单一值,即每个字段都只能包含一个值,不能存储多个值或重复组。

2NF:除了满足第一范式外,还要求所有非主键字段完全依赖于整个主键,而不是部分主键(适用于复合主键的情况)。

3NF:除了满足第二范式外,还要求所有非主键字段直接依赖于主键,不允许存在传递依赖(即非主键字段A依赖于另一个非主键字段B,而B又依赖于主键)。

数据库日志分为哪几种?

  • 事务日志:记录数据库中所有事务及其对数据所做的更改
  • 重做日志(redo log):主要用于数据库恢复过程。它记录了所有已提交但尚未写入数据文件的更改信息。在数据库崩溃后重启时,可以使用这些日志重新应用这些更改,以恢复到崩溃前的状态。
  • 撤销日志(undo log):用于支持事务回滚操作。当一个事务需要被回滚时,撤销日志包含了必要的信息来撤消该事务执行的所有更改,使数据库返回到事务开始之前的状态。
  • 归档日志:对于一些数据库管理系统,当重做日志文件达到一定大小或条件时,会自动将它们归档。归档日志对于时间点恢复(Point-in-Time Recovery)非常重要,因为它允许从某个历史时刻的数据状态进行恢复。
  • 错误日志:包含数据库运行期间发生的各种错误信息、警告以及关键的通知。这些日志对于诊断和解决数据库运行中的问题非常有用。
  • 审计日志:记录数据库用户的行为,特别是安全相关的活动,如登录尝试、权限变更等。这有助于监控数据库的安全状况,并满足合规要求。

主键、超键、候选键、外键的定义是什么?

  • 主键:是一列或一组列,用于标识唯一的一行,每个表中只有一个主键,并且主键值不为null
  • 超键:一列或多个列的集合,,其中包含足够的信息来唯一标识表中的每一行记录。换句话说,超键是能够唯一确定表中一行的所有属性集。
  • 候选键:候选键是最小超键,没有冗余的属性。
  • 外键:外键是一个列或一组列的组合,其值与另一个表的主键(或候选键)相匹配。外键用于建立和加强两个表之间的连接,维护引用完整性。

drop、delete与truncate的区别是什么?

  • DROP 语句用于删除数据库对象,如表、视图等。对于表而言,它不仅删除了表中的所有数据,还删除了表的结构定义。
  • DELETE用于删除表中行数据
  • TRUNCATE 是一个DDL(数据定义语言)操作,它会快速地移除表中的所有数据,而不删除表本身。

MySQL中in和exists的区别是什么?

  • IN:当使用 IN 子查询时,外部查询会等待子查询返回所有符合条件的结果集,然后逐一比较外部查询的每一行是否在这个结果集中。
  • EXISTS:EXISTS 子查询则是基于“存在性检查”,即一旦找到匹配项就会立即停止搜索并返回结果,不会继续检查剩余的记录。因此,EXISTS 更加高效,特别是在子查询可能返回大量数据的情况下。

MySQL默认的事务隔离级别是什么?

在MySQL中,默认的事务隔离级别是 可重复读(Repeatable Read)。这是由InnoDB存储引擎提供的默认设置。在这个隔离级别下,事务能够看到自己所做的一系列变更,并且在同一事务内的多次读取之间不会看到其他事务所做的更改,除非这些更改被提交。这意味着,在一个事务内执行的多次相同查询会得到同样的结果,即使在这期间有其他事务对数据进行了修改并提交。

读未提交: 事务隔离级别的最低级别,一个事务读到另一个事务未提交数据,可能出现脏读、不可重复读和幻读

读已提交:只允许一个事务读另一个事务已提交事务,可能会出现不可重复读和幻读

可重复读:默认的事务隔离机制,事务内多次读取同一数据前后保持一致,可能会出现幻读。

串行化:事务隔离级别的最高级别,事务串行执行。

MySQL索引的发展过程是怎样的?

  1. 全文扫描:没有索引的阶段
  2. 二叉排序树(BST):解决全文扫描效率低
  3. 平衡二叉树:解决BST的不平衡问题。
  4. B-tree索引:为适应磁盘I/O特性,解决平衡二叉树的I/O效率问题。
  5. B+tree索引:在B树基础上进一步优化,成为数据库索引的主流结构(如InnoDB的默认索引)。
  6. hash索引:针对等值查询(如WHERE id = 1)的极致优化。

MySQL支持哪些存储引擎?

  • InnoDB:支持事务,支持行锁,支持外键,支持B+树索引和自适应Hash索引
  • MyISAM:不支持事务,支持表锁,支持B+树索引
  • Memory:不支持事务,支持表锁,支持B+树索引和Hash索引,存储在内存中,

MySQL的Innodb引擎如何实现MVCC的?

InnoDB引擎通过多版本并发控制(MVCC, Multi-Version Concurrency Control)来提高数据库的并发性能,并实现非锁定读取。MVCC允许查询操作读取旧版本的数据,而写操作则可以创建新版本的数据,这样就减少了读写操作之间的冲突。

主要通过隐藏字段、undo日志(版本链)、readView(读视图)实现

隐藏字段:

  • DB_TRX_ID:最近更改这行记录的事务ID,每次修改都会更新此值。
  • DB_ROLL_PTR:回滚指针,指向undo日志记录,用于存储旧版本的数据。

MyISAM和InnoDB有什么区别?

  • MyISAM:不支持Hash索引,不支持事务,不支持外键,支持表锁
  • InnoDB:支持自适应Hash索引,支持事务,支持外键,支持行锁

为什么阿里巴巴《Java开发手册》不建议使用物理外键?使用物理外键会带来什么问题?

1.性能损耗。外键需要依赖索引实现约束,每次插入、更新或删除数据时,数据库必须维护外键关联的索引(如主表的主键索引和从表的外键索引),导致额外的I/O操作和计算开销。

2.并发风险。高并发场景下,多个事务可能同时操作关联表(如订单和订单项),数据库需为外键约束加锁,导致锁竞争加剧,甚至引发死锁

3.分布式系统的不兼容性。当数据量增大时,通常需要分库分表。但外键约束无法跨数据库或分片生效,导致关联表可能分布在不同节点,无法保证数据一致性

4.开发灵活性降低,外键的存在限制了表结构的修改(如删除主表字段需先处理从表约束),增加维护复杂度。

物理删除和逻辑删除有什么区别?日常开发中会使用哪种删除方式?为什么?

物理删除:delete语句直接删除行数据,这样就在数据库中删除了

逻辑删除:在表中添加字段用以标识是否删除(is_deleted),数据物理上还存在

日常开发中,两种方式都会涉及到,物理删除主要是那些不太重要的数据,缓存(如缓存),逻辑删除主要用于类似于订单表这种,需要后续进行审计

内连接和外连接有什么区别?什么是自连接?举例说明一下。

内连接:通过条件查询,两个表求交集(结果求交集,条件都满足)

外连接:左外连接,右外连接,全外连接

​ 左外连接:左表查询出来的结果在结果集中一定有,右表不满足的用null代替

​ 右外连接:右表查询出来的结果在结果集中一定有,左表不满足的用null代替

​ 全外连接:左表和右表的并集

自连接:自连接(Self Join) 是一种 SQL 语句中的连接操作,指将同一张表视为两个或多个独立的表,通过表的别名(Alias)进行连接,从而实现对表内数据的关联查询。它主要用于处理表中存在层次关系或行间关联的场景,例如员工与经理的关系、分类的父子层级等。例如员工与经理、分类的父子层级、组织结构等。

-- 查询员工及其经理的姓名
SELECT 
    e1.name AS employee_name, 
    e2.name AS manager_name
FROM 
    employee e1  -- 别名 e1 表示员工
INNER JOIN 
    employee e2  -- 别名 e2 表示经理
ON 
    e1.manager_id = e2.id;  -- 关联条件:员工的经理ID等于经理的ID

创建索引时会锁表吗?为什么?

会锁表,但锁表时间取决于 MySQL 版本和配置。

  • 数据一致性保障:创建索引时,数据库需要确保索引构建过程中数据的一致性。如果允许其他事务同时修改数据(如插入、更新或删除),可能会导致索引构建过程中数据不一致(例如索引未包含新插入的行,或包含已删除的行)
  • 操作原子性:索引创建是一个原子性操作,必须保证要么完全完成,要么完全回滚。锁表可以避免中途中断导致索引损坏。

聚簇索引和非聚簇索引有什么区别?

  • 聚簇索引:在主键上创建(若未显式定义主键,InnoDB 自动创建隐藏主键),叶子结点存储的是行数据(数据与索引物理上合并),每个表只能有一个。
  • 非聚簇索引:非主键字段上创建,叶子结点存储的是主键,每个表可以生成多个。

聚簇索引等于主键索引吗?聚簇索引的生成规则是什么?

主键索引通常是聚簇索引,但聚簇索引不一定是主键索引(依赖表设计)。其生成规则优先主键,次选唯一非空索引,最后生成隐藏ROWID。

关系型和非关系型数据库的区别是什么?

关系型数据库以结构化数据和强事务为核心,适合复杂业务;非关系型数据库以灵活性和扩展性为优势,适合海量数据和高并发场景。选择时需根据业务需求权衡一致性、扩展性和查询复杂度。

关系型数据库:

  • 结构化数据,基于表格(行和列),遵循关系模型
  • 支持ACID事务(原子性、一致性、隔离性、持久性),保证强一致性,
  • 使用SQL(结构化查询语言),支持复杂查询(如JOIN、事务)。
  • 水平扩展困难,依赖分库分表

非关系数据库:

  • 支持文档、键值、图等模型
  • 使用自定义查询语言(如MongoDB的JSON查询、Redis的命令行),灵活性高
  • 通常弱化事务支持(如Redis支持单命令原子性,但不保证多命令事务)
  • 天然支持水平扩展,适合海量数据和高并发场景(如NoSQL的分布式设计)。

详细说一下一条MySQL语句执行的步骤。

1.建立连接:客户端与 MySQL 服务建立通信连接。

2.查询缓存:如果命中,快速返回缓存结果,避免重复执行相同查询。

3.SQL 解析:验证 SQL 语法并生成执行计划的输入。

4.查询优化:生成最高效的执行计划

5.查询执行:实际执行 SQL 并获取数据。

6.结果返回:将查询结果返回给客户端。

7.连接管理:维护连接状态或释放连接。

MySQL使用索引的原因是什么?

1.减少数据查询范围,解决全文扫描带来的效率低下

2.加速数据查找范围

3.优化排序和分组操作

索引的三种常见底层数据结构以及优缺点是什么?

索引的三种常见底层数据结构是 哈希表(Hash)、B+树(B+Tree) 和 有序数组(Sorted Array)

数据结构 等值查询 范围查询 插入/删除 空间开销 适用场景
哈希表 O(1) 不支持 O(1) 低(无冗余) 纯等值查询(缓存、键值存储)
B+树 O(log n) O(log n) O(log n) 较高 通用数据库索引
有序数组 O(log n) O(log n) O(n) 最低 静态数据或只读场景

索引的常见类型以及它是如何发挥作用的?

  1. B树索引:支持范围查询,InnoDB默认结构)。
  2. 哈希索引:(等值查询高效,无范围支持)。
  3. 唯一/主键索引:(约束唯一性,加速查询)。
  4. 聚集/非聚集索引:(数据存储方式差异)。
  5. 全文索引:(倒排索引,文本检索)。
  6. 复合索引:(多列联合查询,最左前缀原则)。

MyISAM和InnoDB实现B树索引方式的区别是什么?

  • MyISAM:主键索引的叶子节点存储数据地址(物理指针)。辅助索引的叶子节点存储数据地址(与主键索引结构相同)。
  • InnoDB:主键索引的叶子节点存储行数据。辅助索引的叶子节点存储主键值(而非数据地址)。

InnoDB为什么设计B+树索引?

  1. 节点存储效率更高:B+树的非叶子节点仅存储索引键值,不存储实际数据,因此每个节点可以容纳更多键值(例如,一个节点可存储数千个键),树的高度更矮。
  2. 减少磁盘访问次数:对于主键查询(如 SELECT * FROM table WHERE id=1),B+树的主键索引叶子节点直接存储数据行,只需一次 I/O(从根到叶子节点)。对于范围查询(如 WHERE age BETWEEN 20 AND 30),叶子节点的双向链表允许按顺序遍历,利用磁盘预读特性减少随机 I/O。
  3. 叶子节点有序且链表连接:B+树的叶子节点按键值顺序排列并形成链表,范围查询时只需遍历相邻节点,无需回溯到根节点。
  4. 插入/删除效率。树高稳定:B+树的高度通常在 3~4 层(即使数据量达到数十亿),插入/删除操作仅需调整局部节点,无需频繁重组树结构。页分裂优化:InnoDB 的页(Page)大小为 16KB,节点分裂时仅需调整指针,避免大规模数据移动。
  5. 数据有序性。天然支持排序和分组:B+树的有序性使 ORDER BY、GROUP BY 等操作无需额外排序,直接按叶子节点顺序读取即可。

什么是覆盖索引和索引下推?

覆盖索引:覆盖索引是指查询所需的所有字段都能在索引中找到,无需通过索引回表查询数据行

索引下推:索引下推是 InnoDB 在 5.6 版本引入的优化技术,允许在索引遍历时提前过滤条件,减少不必要的回表操作

哪些操作会导致索引失效?

1.头部模糊匹配

2.or前后没有同时使用索引

3.字符串没有用单引号

4.在索引列运算

5.如果MySQL评估使用索引比全表更慢,则不使用索引。

MySQL的change buffer是什么?

Change Buffer(写缓冲区) 是 InnoDB引擎 的一种优化机制,用于减少磁盘I/O,提升写操作(INSERT/UPDATE/DELETE)的性能。其核心思想是:将对非唯一二级索引的变更操作延迟合并到磁盘页中。

MySQL是如何判断一行扫描数的?

行扫描数(Rows Examined) 是MySQL执行查询时实际扫描的行数,通常通过 EXPLAIN 命令的 rows 列(预估行数)和 Rows_examined(实际行数)体现。

MySQL的redo log和binlog区别是什么?

Redo Log:

  • InnoDB内部机制,关注数据页的物理一致性。
  • 必须存在,即使未开启Binlog。
  • Crash-Safe:通过Redo Log保证事务即使崩溃也能恢复。

Binlog:

  • MySQL服务器层功能,提供逻辑操作记录。
  • 需手动开启,用于主从同步和逻辑恢复。
  • 不保证实时性:仅在事务提交时写入。

为什么需要redo log?

保证事务持久性:

  • 事务提交后,数据可能暂时只存在于内存的Buffer Pool中(脏页),若此时数据库崩溃,数据会丢失。
  • Redo Log通过WAL(Write-Ahead Logging)机制,先将事务的物理修改记录到日志中(先写Redo Log,再写数据页),确保即使崩溃后也能通过日志恢复数据。

解决磁盘IO性能问题:

  • 直接将数据页写入磁盘存在两大问题:
  • 随机IO效率低:数据页可能分散在磁盘不同位置,频繁随机写入耗时。
  • 浪费资源:修改少量数据需写入整个16KB数据页。
  • Redo Log记录物理修改的最小变更(如页号、偏移量、新值),日志文件小且顺序写入,大幅减少IO开销。

支持崩溃恢复:

  • 在数据库重启时,Redo Log可重做(Redo)已提交但未刷盘的事务,确保数据一致性。

为什么redo log具有crash-safe的能力,是binlog无法替代的?

物理层恢复能力:

  • Redo Log记录的是数据页的物理变更,可直接定位到磁盘上的具体位置进行修复。例如,若数据页因崩溃未完全写入,Redo Log可重做缺失的修改。

  • Binlog仅记录逻辑操作(如UPDATE user SET age=25 WHERE id=1),无法直接修复物理损坏的数据页。
    事务提交的强依赖:

  • Redo Log是事务提交的必要条件(提交前必须写入),而Binlog是事务提交后的可选操作。若未配置Binlog,不影响事务的持久性保障。

性能与效率:

  • Redo Log的顺序写入效率远高于Binlog的随机写入(Binlog需记录完整SQL语句或行数据)。

当数据库crash后,如何恢复未刷盘的数据到内存中?

1.重启时加载数据页到Buffer Pool:
从磁盘读取数据页到内存,但可能包含未提交或未完全刷盘的事务修改。

2.Redo Log重做(Redo)已提交事务:
步骤:

  • 从Redo Log的检查点(Checkpoint)开始,按顺序重做所有已提交事务的修改。
  • 将数据页恢复到崩溃前的最新状态。

原理:Redo Log记录了所有未刷盘的物理修改,确保数据页与Redo Log一致。

3.Undo Log回滚未提交事务:
步骤:

  • 扫描所有未提交的事务(通过事务表)。
  • 使用Undo Log撤销这些事务的修改(如将数据页恢复到修改前的值)。

原因:未提交的事务可能修改了数据页,但未生效,需通过Undo Log回滚到一致状态。

redo log的写入方式是什么?

1.内存缓冲区(Redo Log Buffer):
事务执行时,修改操作首先记录到内存的Redo Log Buffer中(非阻塞,提升性能)。

2.刷盘时机:
由参数 innodb_flush_log_at_trx_commit 控制:

  • 值为1(默认):事务提交时,Redo Log Buffer立即刷盘。
  • 值为0:每秒刷盘一次(性能最高,但可能丢失1秒数据)。
  • 值为2:事务提交时刷盘到OS Buffer,每秒由OS刷盘(折中方案)。

3.顺序写入磁盘:

  • Redo Log文件是固定大小的循环日志(如ib_logfile0、ib_logfile1),写满后从头开始覆盖。
  • LSN(Log Sequence Number):记录日志的写入位置,用于追踪和恢复。

redo log的执行流程是怎样的?

1.事务开始:

  • 事务启动,分配Undo Log空间用于回滚。

2.修改数据:

  • 读取数据页到Buffer Pool(若未加载)。
  • 修改内存中的数据页(形成脏页),同时生成对应的Redo Log记录。

3.Redo Log写入Buffer:

  • 将修改的物理信息(页号、偏移量、新值)写入Redo Log Buffer。

4.事务提交:
关键步骤:

  • 将Redo Log Buffer刷盘(根据innodb_flush_log_at_trx_commit配置)。
  • 更新事务的提交状态(如设置COMMIT标志)。
  • 此时事务对数据的修改逻辑上完成,但数据页可能未刷盘。

5.后台刷盘与Checkpoint:

  • 主线程(Master Thread):定期将脏页刷盘,并推进Checkpoint,减少Redo Log的覆盖范围。
  • 日志组提交(Group Commit):多个事务的Redo Log合并一次刷盘,提升效率。

6.崩溃恢复流程:
步骤:

  • 重启时加载数据页到Buffer Pool。
  • 从Checkpoint开始,重做(Redo)所有已提交的Redo Log记录。
  • 回滚未提交的事务(通过Undo Log)。

结果:数据恢复到崩溃前的最新一致状态。

binlog的概念是什么?起到什么作用?可以保证crash-safe吗?

binlog是MySQL的二进制日志,记录数据库所有逻辑变更(如SQL语句或行数据修改),用于主从复制、数据恢复和操作审计。它不能保证crash-safe,因为崩溃时未提交的事务可能未记录,且物理层恢复需依赖InnoDB的Redo Log。

什么是两阶段提交?

两阶段提交(2PC)是分布式事务的协调协议,分准备阶段(参与者投票是否提交)和提交阶段(协调者统一通知提交或回滚),确保所有节点达成一致,但可能因超时或网络问题导致阻塞。

MySQL怎么知道binlog是完整的?

MySQL通过检查binlog文件的EOF标记和校验和,确保日志写入完整无截断;同时,事务提交时binlog需先写入磁盘(由sync_binlog参数控制),避免崩溃时日志不完整。

什么是WAL技术?有什么优点?

WAL(Write-Ahead Logging,预写日志)是先将数据修改记录到日志再写入磁盘的技术,优点包括:

  • 提升性能:通过顺序写日志减少随机IO;
  • 保证崩溃恢复:日志可重做未刷盘的修改,确保数据一致性。

binlog日志的三种格式是什么?

  • STATEMENT:记录SQL语句(可能因非确定性操作导致复制不一致);
  • ROW:记录行级变更(精确复制,但日志体积大);
  • MIXED:混合模式,根据语句自动选择格式。

redo log日志格式是怎样的?

Redo Log记录物理页的修改,包含:

  • LSN(日志序列号):日志位置标识;
  • 页号:修改的数据页地址;
  • 操作类型(如插入、更新)和数据块:记录具体修改内容,用于崩溃后重做数据。

原本可以执行得很快的SQL语句,执行速度却比预期的慢很多,原因是什么?如何解决?

  • 全表扫描(缺少索引);
  • 锁竞争(高并发导致阻塞);
  • 索引失效(如函数操作或范围条件后跟NULL);
  • 临时表过大(复杂查询生成大临时表)。

解决方案:添加合理索引、重写查询、优化锁策略或调整配置(如增大tmp_table_size)。

InnoDB数据页结构是怎样的?

InnoDB数据页大小为16KB,结构包含:

  • 页头:元信息(如页号、LSN、checksum);
  • 单元数组:存储行数据或索引条目;
  • 空闲空间:未使用的区域;
  • 页目录:快速定位单元的索引。

MySQL是如何保证数据不丢失的?

通过Redo Log和事务ACID机制:

  • WAL技术:事务提交前先写Redo Log,确保崩溃后可重做未刷盘的数据;
  • 双1机制:innodb_flush_log_at_trx_commit=1时,事务提交前Redo Log强制刷盘,保证持久性。

误删数据怎么办?

  1. 立即停止写入:避免覆盖数据;
  2. 使用备份恢复:从最近备份恢复并回放binlog;
  3. 回放binlog:通过mysqlbinlog定位误删前的语句重放;
  4. InnoDB的Undo Log:通过 flashback功能(需开启innodb_undo_log_truncate=OFF)或第三方工具回滚。

你可能感兴趣的:(数据库,数据库,oracle,java)