数据库面试常问3

视图的作用?

视图是一种虚拟的表,由一个或多个基本表(或其他视图)的行和列组成。它可以根据定义查询基本表,并返回所需的结果集。视图的主要作用包括:

  1. 简化复杂的查询:将多个表的关联查询合并为一个视图,简化查询的复杂性。
  2. 保护数据安全性:限制用户对数据的访问权限,只暴露给用户需要的数据字段,隐藏敏感信息。
  3. 数据逻辑独立性:将底层表的物理结构与应用程序的逻辑分离开来。
  4. 简化数据操作:作为一个容器,对数据进行封装和抽象,屏蔽了底层表的细节。
  5. 提高性能:对经常使用的查询进行预计算和缓存,提高查询性能。

可以考虑一个电子商务系统的情景。

假设我们有以下两个表:

  1. products - 包含产品的信息,如产品ID、名称、价格等。

  2. +----+--------------+-------+

    | ID | Name | Price |

    +----+--------------+-------+

    | 1 | Laptop | 1000 |

    | 2 | Smartphone | 700 |

    | 3 | Headphones | 150 |

    +----+--------------+-------+

  3. orders - 包含订单的信息,如订单ID、用户ID、产品ID等。

  4. +----+---------+---------+

    | ID | User_ID | Prod_ID |

    +----+---------+---------+

    | 1 | 101 | 1 |

    | 2 | 102 | 2 |

    | 3 | 103 | 1 |

    +----+---------+---------+

    现在,如果我们想要获取某个用户的订单信息以及相应的产品信息,可能需要进行联合查询来检索相关数据,这可能会变得复杂。

    为了简化这个过程,我们可以创建一个视图,该视图将用户订单的详细信息与产品信息联合在一起。

    我们可以创建一个名为 user_orders_view 的视图,它包含用户订单的详细信息以及相应的产品信息。视图的定义如下:

sql 复制代码
CREATE VIEW user_orders_view AS
SELECT o.ID AS Order_ID, o.User_ID, p.Name AS Product_Name, p.Price
FROM orders o
JOIN products p ON o.Prod_ID = p.ID;

现在,当我们需要获取用户订单的详细信息时,只需查询 user_orders_view 视图即可:
6. SELECT * FROM user_orders_view WHERE User_ID = 101;

非关系/关系型数据库的区别?

关系型数据库和非关系型数据库之间存在着几个重要的区别:

  1. 数据模型

    • 关系型数据库采用表格形式的数据模型,数据以行和列的形式组织,并且数据之间存在严格的关系。
    • 非关系型数据库则采用各种不同的数据模型,如文档型、键值型、列型、图形等,更灵活地存储数据。
  2. 数据一致性

    • 关系型数据库通常通过事务来确保数据的一致性,支持 ACID(原子性、一致性、隔离性、持久性)事务属性。
    • 非关系型数据库的一致性通常是灵活的,可以根据需求进行调整,有些数据库可能只提供 eventual consistency(最终一致性)。
  3. 数据操作

    • 关系型数据库支持 SQL(结构化查询语言)进行数据操作,包括插入、更新、删除和查询等操作。
    • 非关系型数据库通常使用各种不同的查询语言或 API 进行数据操作,取决于数据库的类型和特性。
  4. 水平扩展

    • 非关系型数据库通常更容易水平扩展,能够轻松处理大量数据和高并发访问。
    • 关系型数据库在水平扩展方面的支持相对有限,更适合于较小规模或需要严格数据一致性的应用。
  5. 数据一致性和持久性

    • 关系型数据库通常提供较高的数据一致性和持久性,但可能会影响性能。
    • 非关系型数据库在一致性和持久性方面的保证因数据库类型和配置而异。

(重要)数据库三大范式?

  1. 第一范式(1NF)

    • 第一范式要求数据库表中的每一列都是不可分割的原子数据项,即每一列都是不可再分的最小数据单元。这意味着每个字段都应该具有原子性,不可再分。
    • 例如,如果有一个包含学生信息的表,那么每个字段应该包含原子数据项,如学生的姓名、学号、性别等。
  2. 第二范式(2NF)

    • 第二范式要求数据库表中的非主键字段必须完全依赖于主键,即表中的每一列数据都和主键有直接关系,而不是部分依赖于主键。
    • 换句话说,如果一个表中有复合主键,那么每个非主键字段都必须完全依赖于这个复合主键,而不能只依赖于部分主键。
    • 例如,如果有一个订单详情表,其中包含订单号和产品编号作为复合主键,订单数量和产品价格应该直接依赖于订单号和产品编号,而不是只依赖于订单号或产品编号的其中一个。
  3. 第三范式(3NF)

    • 第三范式要求数据库表中的非主键字段之间不能存在传递依赖关系,即非主键字段之间不能相互依赖,而是直接依赖于主键。
    • 换句话说,如果一个非主键字段依赖于另一个非主键字段,那么应该将这个字段拆分出来,直接依赖于主键。
    • 例如,如果有一个员工表,其中包含部门编号和部门名称,那么部门名称应该直接依赖于部门编号,而不是依赖于员工编号。

主键外键?

主键(Primary Key)

  • 主键是表中用来唯一标识每一条记录的字段或字段组合。它具有以下特点:
    • 唯一性:主键值在表中必须是唯一的,不能重复。
    • 非空性:主键字段的值不能为 NULL,即每条记录都必须有主键值。
    • 稳定性:主键值一般不会发生变化,用来确保记录的唯一性和标识性。
  • 主键通常用于查询、修改和删除记录,它可以是单个字段,也可以是多个字段的组合。例如,在一个学生表中,学生的学号可以作为主键,因为每个学生的学号应该是唯一的且不会重复。

外键(Foreign Key)

  • 外键是表中的一个或多个字段,其值必须与另一个表中的主键值或唯一键值相匹配,用于建立表与表之间的关联关系。
  • 外键的存在可以确保数据的完整性和一致性,它表示了表与表之间的某种关系,通常是父表和子表之间的关系。
  • 例如,如果有一个学生表和一个班级表,班级表中有班级编号作为主键,那么学生表中的班级编号字段可以作为外键,与班级表建立关联,确保每个学生所属的班级在班级表中存在。

总结:

  • 主键用于唯一标识表中的记录,确保记录的唯一性和标识性。
  • 外键用于建立表与表之间的关联关系,保持数据的一致性和完整性,确保关联数据的存在性。

MySQL是如何执行一条SQL的?

MySQL执行一条SQL的过程主要包括以下几个步骤:

  1. 连接器(Connection Manager):处理客户端连接请求,进行身份验证和权限验证,管理连接池。

  2. 查询缓存(Query Cache):如果查询命中缓存,直接返回缓存中的结果,减少了对数据库的访问。

  3. 分析器(Parser):对SQL语句进行词法分析和语法分析,检查语句的合法性,确定语句的执行对象和执行方式。

  4. 优化器(Optimizer):对语句进行优化,生成多个可能的执行计划,并选择最优的执行计划。优化器会考虑索引的使用、连接顺序等因素,以提高查询效率。

  5. 执行器(Executor):执行选定的执行计划,操作存储引擎获取数据,并进行计算、过滤等操作,最终得到结果集。

  6. 存储引擎(Storage Engine):负责实际的数据存储和检索操作,提供对数据的读写接口。

  7. MySQL支持多种存储引擎,如InnoDB、MyISAM等,不同的存储引擎具有不同的特性和性能表现。

(重要)数据库引擎InnoDB与MyISAM的区别

  • InnoDB

InnoDB 是 MySQL 默认的事务型存储引擎,它在数据库系统中提供了许多重要的功能和优化,使其成为许多应用的理想选择。以下是对 InnoDB 各个方面的详细解释:

  1. 事务和隔离级别

    • InnoDB 支持 ACID(原子性、一致性、隔离性、持久性)属性,这保证了事务操作的可靠性和数据的完整性。
    • InnoDB 提供四个标准的隔离级别(读未提交、读提交、可重复读、可序列化),默认隔离级别是可重复读(REPEATABLE READ)。在此级别下,通过 MVCC(多版本并发控制)和间隙锁(Next-Key Locking)防止幻影读,确保事务之间的数据一致性。
  2. 聚簇索引

    • InnoDB 使用主键作为聚簇索引,即表的数据按主键顺序存储。这意味着数据行的物理存储顺序与主键的顺序一致,这样查询时可以快速找到数据。
    • 聚簇索引提高了主键查找的性能,因为数据和索引在一起,可以避免多次访问磁盘。
  3. 多版本并发控制(MVCC)和间隙锁

    • MVCC 允许多个事务同时读取数据,而不会互相阻塞。每个事务读取数据时都看到一个事务开始时的数据快照,这样读写操作可以并行进行。
    • 间隙锁(Next-Key Locking)是在索引键之间加锁,以防止其他事务在同一键值之间插入新的数据,防止幻影读。
  4. 自适应哈希索引

    • InnoDB 自动创建和管理自适应哈希索引,以提高查询性能。对于频繁的等值查询,哈希索引可以显著加速查询过程。
  5. 插入缓冲区

    • InnoDB 使用插入缓冲区(Insert Buffer)来优化插入操作。非唯一索引的插入操作首先写入缓冲区,然后在适当的时候批量应用到磁盘,这样可以减少对磁盘的随机写入,提高插入性能。
  6. 在线热备份

    • InnoDB 支持在线热备份,这意味着在进行备份时不需要停止写操作。InnoDB 通过创建一致性视图来确保备份的数据是一致的,而不影响正在进行的事务。
  • MyISAM

MyISAM 是 MySQL 中的另一个常用存储引擎,它具有一些与 InnoDB 不同的特性和行为。以下是对 MyISAM 的详细解释:

  1. 数据存储格式

    • MyISAM 使用紧密格式存储数据,这意味着数据在磁盘上的存储方式更为简单和紧凑。这种设计使得 MyISAM 在处理只读数据或者表比较小、可以容忍修复操作的情况下表现良好。
  2. 特性

    • MyISAM 提供了许多特性,例如压缩表和空间数据索引等。这些特性可以帮助优化数据存储和查询效率,适用于特定的应用场景。
  3. 不支持事务

    • MyISAM 不支持事务,这意味着它不具备 ACID 属性,无法保证事务的原子性、一致性、隔离性和持久性。因此,在需要事务支持的应用中,通常不推荐使用 MyISAM。
  4. 锁机制

    • MyISAM 不支持行级锁,而是只能对整张表进行加锁。在读取时,会对需要读取的所有表加共享锁;在写入时,则会对表加排它锁。这意味着在写入操作时可能会阻塞其他读取或写入操作,影响并发性能。
    • 不过,值得一提的是,MyISAM 允许在表有读取操作的同时向表中插入新的记录,这被称为并发插入(CONCURRENT INSERT)。

MySQL主从复制?

MySQL主从复制? Slave开一个IO线程,到Master读取二进制文件binlog,写入并转换位relaylog。 用一个SQL线程把relaylog转换位二进制文件在进行读取同步 主从复制延迟怎么办

MySQL 主从复制是一种常见的数据库复制技术,用于将一个 MySQL 数据库的更改同步到另一个 MySQL 实例上。这种复制是异步的,即主库上的操作不会等待从库完成,因此可能会出现复制延迟

下面是 MySQL 主从复制的详细步骤和解决延迟问题的方法:

  1. 设置主库和从库

    • 首先,需要在主库和从库上配置正确的参数和权限,确保它们可以相互通信并进行数据同步。
  2. 启动主库的二进制日志

    • 在主库上,需要启用二进制日志(binlog)。二进制日志记录了对数据库进行更改的所有操作。
  3. 配置从库的复制参数

    • 在从库上,需要配置正确的复制参数,包括主库的地址、用户名、密码等信息。
  4. 启动从库的复制线程

    • 从库会启动一个 IO 线程,连接到主库并读取主库的二进制日志(binlog)。IO 线程会将读取的 binlog 记录写入到本地的中继日志(relay log)中。
  5. 启动从库的 SQL 线程

    • 从库还会启动一个 SQL 线程,它会读取中继日志中的记录,并在从库上执行这些操作,从而使从库上的数据与主库保持一致。
  6. 解决主从复制延迟问题

    • 一般情况下,主从复制是异步的,可能会出现一定程度的延迟。要解决延迟问题,可以采取以下方法:
      • 监控复制延迟:建立监控系统,实时监测主从复制的延迟情况。
      • 优化网络和硬件:确保主从服务器之间的网络连接畅通,并优化服务器硬件配置,以提高复制性能。
      • 调整复制线程参数:可以调整从库的复制线程参数,如增加 IO 线程数量、提高 SQL 线程的优先级等。
      • 优化查询和事务:尽量避免在主库上执行大量耗时的查询和事务,以减少复制延迟的可能性。
      • 使用半同步复制:MySQL 还提供了半同步复制的功能,可以确保主库收到确认后再将数据复制到从库,从而减少延迟。

MySQL事务

#数据库事务的特性?(重要) 由引擎来实现,innodb支持事务

MySQL 中的事务具有四个主要特性,也称为 ACID 特性:

  1. 原子性(Atomicity)

    • 原子性指一个事务是一个不可分割的工作单元,要么全部执行成功,要么全部失败回滚。MySQL 中通过回滚日志(undo log)来实现原子性。如果事务执行失败,系统可以使用回滚日志来撤销事务中已经执行的操作,从而保证数据的一致性。
  2. 一致性(Consistency)

    • 一致性要求事务的执行前后数据库都必须保持一致状态。这意味着在事务执行过程中,数据库的约束、触发器、关联关系等都必须得到满足,从而确保数据的完整性和正确性。
  3. 隔离性(Isolation)

    • 隔离性指多个事务并发执行时,每个事务都感觉不到其他事务的存在,就像它是在系统独立运行一样。MySQL 中通过多版本并发控制(MVCC)或者锁机制来实现隔离性。MVCC 允许读取已提交的数据快照,从而避免了读取锁的产生,提高了并发性能。
  4. 持久性(Durability)

    • 持久性要求一旦事务提交,其修改的数据必须永久保存在数据库中,即使系统发生故障也不能丢失。MySQL 中通过重做日志(redo log)来实现持久性。重做日志记录了事务所做的修改操作,当系统发生崩溃时,可以通过重做日志来恢复数据,保证数据的持久性。

MVCC?

MVCC(多版本并发控制)是一种在数据库系统中实现并发控制的方法。它通过同时存在多个版本的数据来实现并发访问的控制,以提高数据库的并发性能和事务的隔离性。

简单来说,MVCC 在数据库中创建多个数据版本,而不是在整个数据库上进行锁定。每个事务在读取数据时,会根据自己的事务ID和数据行的版本号来确定读取哪个版本的数据。这样做的好处是,读操作不会被写操作阻塞,而是可以同时进行,提高了数据库的并发性能。

在数据库中,不同的隔离级别(如读已提交、可重复读等)都是基于 MVCC 实现的。通过使用 MVCC,数据库可以以更有效的方式处理读写冲突,从而提高了系统的性能和并发能力。

数据库的隔离级别有哪些?

  1. 脏读(Dirty Read):脏读是指一个事务读取了另一个事务未提交的数据。较低的隔离级别(如读未提交)允许脏读,因为它们允许事务读取未提交的数据,这可能导致不一致或错误的结果。

  2. 不可重复读(Non-Repeatable Read):不可重复读是指在同一个事务中,多次读取同一数据返回的结果不一致。较低的隔离级别(如读提交)可能导致不可重复读,因为事务可能在读取同一数据时,看到了其他事务已提交的变更。

  3. 幻读(Phantom Read):幻读是指在一个事务中多次查询同一个范围的数据时,结果集合不一致,通常是由于其他事务插入新的数据或删除数据造成的。幻读与不可重复读的区别在于,幻读是针对数据的整个范围,而不是特定的行。

隔离级别越高,数据库系统需要使用更严格的锁机制或多版本并发控制(MVCC)来确保数据的隔离性,因此性能效率会更低。例如,更高的隔离级别通常需要更多的锁来防止并发事务之间的数据冲突,这可能导致更多的资源竞争和阻塞,降低数据库的并发性能和响应速度。

数据库的隔离级别通常包括以下四种:

  1. 读未提交(Read Uncommitted):允许一个事务读取另一个事务尚未提交的数据,可能导致脏读问题。
  2. 读提交(Read Committed):保证一个事务只能读取到已经提交的其他事务的数据,可以避免脏读问题。
  3. 可重复读(Repeatable Read):保证在同一个事务中多次读取同样的数据时,结果保持一致,避免不可重复读问题。在 MySQL 中,InnoDB 默认的隔离级别就是可重复读。
  4. 串行化(Serializable):最高的隔离级别,通过对读写操作加锁来确保事务的并发执行顺序,避免了幻读问题,但是牺牲了并发性能。

不同的隔离级别解决了不同类型的并发问题,但随着隔离级别的提高,性能效率往往会降低,因为需要更多的锁机制来保证数据的一致性。

当一个事务在执行期间,如果其他事务并发地对数据库进行了修改或插入操作,可能会导致不可重复读和幻读的问题。

幻读与不可重复读?

不可重复读发生在一个事务内多次读取同一行数据时,如果在事务执行期间,其他事务修改了这行数据或者删除了这行数据,导致每次读取得到的结果不一致,即"不可重复"。

举例来说,假设一个事务在读取某个商品的价格时,多次读取得到的价格不同,因为在事务执行期间,其他事务修改了这个商品的价格,这就是不可重复读的情况。

幻读则是发生在一个事务内多次执行相同的查询时,如果在事务执行期间,其他事务插入了新的数据,导致每次查询得到的结果集合发生了变化,即"幻影"。

比如,一个事务在查询某个时间段内的订单数量时,多次查询得到的结果集合不一致,因为在事务执行期间,其他事务插入了新的订单数据,这就是幻读的情况。

不可重复读关注的是同一行数据的读取结果的一致性,而幻读关注的是整个结果集合的一致性。为了解决这些并发引起的问题,数据库系统通常采用了各种隔离级别和并发控制机制,例如锁机制或多版本并发控制(MVCC),以确保事务的隔离性和一致性。

如何防止幻读?

  1. 行级锁 :这是最常见的方法之一。你可以在事务中使用SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE语句来获取行级锁。这样可以确保其他事务无法修改或插入被锁定行的数据,从而防止幻读。但是,行级锁会增加额外的开销,并且可能会导致性能下降,特别是在高并发情况下。

  2. 间隙锁(Gap Locks):这是一种特殊的行级锁,它可以锁定一个范围而不是具体的行。比如,你可以通过锁定一个范围的值来防止其他事务插入或修改该范围内的数据,从而避免幻读。但是,间隙锁也可能会影响到其他事务的性能,特别是在范围较大的情况下。

  3. 版本控制(MVCC):MySQL通过实现基于快照隔离级别的多版本并发控制(MVCC)机制来避免幻读的发生。在MVCC中,每个事务在执行时都会建立一个快照,用来记录事务开始时数据库的状态。当一个事务更新或删除数据时,MySQL会创建新的版本,并将旧版本标记为已删除。其他事务在读取数据时,只能看到未被已删除版本覆盖的最新版本,这样可以避免幻读的发生。

什么时候死锁,如何解决?

死锁是指两个或以上的线程互相等待对方释放锁

  1. 避免循环等待 :死锁通常发生在多个资源之间形成循环等待的情况下。为了避免循环等待,可以按照固定的顺序获取锁。例如,在多个线程或进程需要同时获取多个资源时,可以约定按照特定的顺序获取,从而防止循环等待的发生。
  2. 使用超时机制:可以为锁设置超时时间,在获取锁时如果超过了一定时间仍未成功获取,则放弃当前操作并释放已获得的锁。这样可以避免一个线程或进程长时间占用锁,导致其他线程或进程无法继续执行而引发死锁。
  3. 资源有序分配法 :通过对系统资源进行编号,并要求所有进程按照编号递增的顺序请求资源,可以避免死锁。即每个进程在申请资源时,必须按照规定的顺序获取资源,释放资源也必须按照相反的顺序进行。
  4. 死锁检测和恢复 :可以实现死锁检测算法,周期性地检测系统中是否存在死锁。一旦检测到死锁,可以采取相应的恢复策略,如回滚事务或者强制终止进程,从而解除死锁。
  5. 合理设计事务和并发控制 :在数据库等具有事务和并发控制的系统中,合理设计事务的粒度和并发控制策略 ,可以减少死锁的可能性。例如,使用尽量短小的事务 ,减少事务持有锁的时间;选择合适的隔离级别,避免不必要的锁冲突

乐观锁和悲观锁?

乐观锁和悲观锁是两种并发控制的思想:

  1. 乐观锁:在操作数据时,默认不加锁,而是在更新数据时检查数据版本号或者其他标识,如果发现数据被其他线程修改,则放弃当前操作或者重新尝试。乐观锁适用于多读少写的场景,因为在多读的情况下,不会造成太多的锁竞争,而通过版本号或者其他标识来判断数据是否被修改,可以减少加锁的开销。

  2. 悲观锁:在操作数据时,会先加锁,确保在操作数据的整个过程中其他线程无法修改数据。悲观锁适用于多写的场景,因为在多写的情况下,如果不加锁可能会导致数据不一致或者丢失更新。悲观锁可以在代码层面进行加锁,也可以在数据库层面通过数据库的锁机制来实现。

乐观锁基本原理

  1. 读取数据:乐观锁在读取数据时,并不会加锁或者阻塞其他事务对数据的访问。通常会记录下读取时的版本号、时间戳或者其他标识,以便后续比较是否发生了修改。

  2. 执行操作:在执行操作之前,乐观锁不会对数据进行任何的锁定,允许其他并发操作同时对数据进行读取和修改。

  3. 冲突检测:在提交修改时,乐观锁会再次读取数据,并比较当前的版本号或时间戳等标识,与之前记录的标识进行比较。如果发现提交时的标识与之前记录的标识不一致,就表示数据在读取到提交之间已经被修改了,发生了冲突。

  4. 处理冲突:一旦发现冲突,乐观锁会根据具体的业务逻辑和应用场景来处理冲突,通常的处理方式包括放弃操作、重试操作、提示用户等。

乐观锁在处理冲突时可以选择不同的策略,具体取决于业务需求和系统设计:

  1. 放弃当前操作并重试:当发生冲突时,乐观锁可以放弃当前操作,回滚到读取数据的状态,然后重新尝试执行操作。这种策略适用于冲突发生的频率较低,而且操作可以安全地重试的情况。

  2. 合并修改:有时候冲突发生后,并不需要完全放弃当前操作,而是可以尝试将当前操作与其他操作合并起来,从而解决冲突。这种策略适用于操作之间有一定的兼容性,可以通过合并来消除冲突。

  3. 向用户提示冲突:在某些情况下,系统可以向用户提示发生了冲突,并提供相应的解决方案,让用户自行决定如何处理冲突。这种策略适用于用户参与的场景,让用户了解并处理数据冲突。

相关推荐
小码的头发丝、21 分钟前
Django中ListView 和 DetailView类的区别
数据库·python·django
Karoku06631 分钟前
【企业级分布式系统】Zabbix监控系统与部署安装
运维·服务器·数据库·redis·mysql·zabbix
周全全1 小时前
MySQL报错解决:The user specified as a definer (‘root‘@‘%‘) does not exist
android·数据库·mysql
白云如幻1 小时前
MySQL的分组函数
数据库·mysql
荒川之神1 小时前
ORACLE 闪回技术简介
数据库·oracle
时差9533 小时前
【面试题】Hive 查询:如何查找用户连续三天登录的记录
大数据·数据库·hive·sql·面试·database
让学习成为一种生活方式3 小时前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
秋意钟3 小时前
MySQL日期类型选择建议
数据库·mysql
Dxy12393102164 小时前
python下载pdf
数据库·python·pdf
桀桀桀桀桀桀5 小时前
数据库中的用户管理和权限管理
数据库·mysql