目录

数据库 八股文

数据库的三大范式?

范式是数据库设计时遵循的一种规范,不同的规范要求遵循不同的范式。

第一范式(1NF)

属性不可分割,即每个属性都是不可分割的原子项。(实体的属性即表中的列)

第二范式(2NF):

满足第一范式;且不存在部分依赖,即非主属性必须完全依赖于主属性。(主属性即主键;完全依赖是针对于联合主键的情况,非主键列不能只依赖于主键的一部分)

第三范式(3NF):

满足第二范式;且不存在传递依赖,即非主属性不能与非主属性之间有依赖关系,非主属性必须直接依赖于主属性,不能间接依赖主属性。(A -> B, B ->C, A -> C)

什么是事务?

事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务的四大特性?

原⼦性

事务是⼀个不可分割的⼯作单元,要么完全执⾏,要么完全不执⾏。如果在事务执⾏的过程中发⽣了错误,系统会撤销事务中已经执⾏的操作,将数据库恢复到事务开始前的状态。原⼦性是通过 undo log(回滚⽇志) 来保证的。

⼀致性

确保事务将数据库从⼀个⼀致的状态转变为另⼀个⼀致的状态。事务执⾏的结果必须满⾜数据库的完整性约束和规则,保持数据库的⼀致性。⼀致性则是通过持久性+原⼦性+隔离性来保证的

隔离性

多个事务并发执⾏时,每个事务都不能看到其他事务的中间状态。每个事务都应该感觉就像它是唯⼀在数据库上运⾏的事务⼀样。防⽌了多个事务之间的相互⼲扰。隔离性是通过 MVCC(多版本并发控制)锁机制来保证的。

持久性

⼀旦事务被提交,其结果将永久保存在数据库中,即使系统发⽣故障。即使系统发⽣崩溃,事务的结果也不应该丢失,持久性是通过 redo log (重做⽇志)来保证的。

并行事务出现的问题?

并⾏事务是指多个事务同时执⾏,这可以提⾼数据库系统的性能和吞吐量。但是并⾏事务也可能引发⼀些问题

脏读:读到其他事务未提交的数据

⼀个事务读取了另⼀个事务未提交的数据,如果另⼀个事务后来回滚,读取的数据就是⽆效的。读到了并不⼀定最终存在的数据,这就是脏读。

不可重复读:前后读取的数据不⼀致

在⼀个事务内,同⼀查询可能返回不同的结果,因为在事务执⾏期间其他事务可能修改了数据。

幻读:前后读取的记录数量不⼀致

在⼀个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不⼀样的情况,就意味着发⽣了「幻读」现象

隔离级别有哪些?

  1. 读未提交: 最低的隔离级别。在这个级别下,⼀个事务可以读取到另⼀个事务未提交的数据。这可能导致脏读(Dirty Reads)和不可重复读、幻读等问题

  2. 读提交: 在这个级别下,⼀个事务只能读取到已经提交的其他事务的数据。这解决了脏读的问题,但仍可能遇到不可重复读的问题

  3. 可重复读 在这个级别下,⼀个事务在其⽣命周期内多次执⾏相同的查询,将始终看到相同的数据,但是,仍可能发⽣幻读。也是MySQL InnoDB 引擎的默认隔离级别

  4. 可串⾏化 提供了最⾼的隔离级别。会对记录加上读写锁,在多个事务对这条记录进⾏读写操作时,如果发⽣了读写冲突的时候,后访问的事务必须等前⼀个事务执⾏完成,才能继续执⾏,在这个级别下,事务的执⾏效果就好像它们是按顺序执⾏的,事务之间没有并发。这可以防⽌脏读、不可重复读和幻读,但也可能导致性能下降,因为并发性降低

你知道MVCC吗?

MVCC,全称Multi-Version Concurrency Control,即多版本并发控制,是一种并发控制的方法。

MVCC是一种用来解决读写冲突的无锁并发控制,也就是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照

  • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能;
  • 解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题

MySQL中锁的种类?

全局锁 顾名思义,全局锁就是对整个数据库实例加锁。 典型使⽤场景:全库逻辑备份,即把整个库的表都select出来存成⽂本

表级锁

表锁

元数据锁(meta data lock,MDL) MDL 不需要显式使⽤,在访问⼀个表的时候会被⾃动加上。 MDL 的作⽤:保证读写的正确性。

意向锁 意向锁⽤于指示⼀个事务在未来可能会请求对某些资源(如数据⾏)的锁

⾏级锁 顾名思义,⾏锁就是针对数据表中⾏记录的锁(也有⼈称为记录锁)。 这很好理解,⽐如事务 A 更新了⼀⾏,⽽这时候事务 B 也要更新同⼀⾏,则必须等事务 A 的操作完成后才能进⾏ 更新。

共享锁 排他锁 乐观锁 悲观锁

delete、drop和truncate区别?

  • delete 是数据操纵语言(DML),其按行删除,支持where语句,执行操作采用行锁,执行操作时会将该操作记录在redo和undo中,因此支持回滚。

  • truncate 是数据定义语言(DDL),其操作隐式提交,不支持回滚,不支持where,删除时采用表级锁进行删除

  • drop 也是DDL,不支持回滚,从数据库中删除整张表,其所有数据行,索引和权限也会被删除。

MySQL事务日志介绍下?

innodb 事务日志包括 redo log 和 undo log。

重做日志(Redo Log):记录所有数据修改操作的重做操作,包括 INSERT、UPDATE 和 DELETE 等操作,以便在发生故障时能够重新执行这些操作,以恢复数据的一性。先刷盘再写日志。

回滚日志(Undo Log):记录所有数据修改操作的撤销操作,主要用于事务回滚和 MVCC 等功能