数据库系统概念-面试复习

1、事务的四大特性?这四个特性mysql是怎么保证实现的?

答:事务的四大特性即ACID。原子性、一致性、持久性、隔离性。

原子性(atomicity)是指一个事务不可分割,要么全部提交成功,要么全部失败回滚; 一致性(consistency)是指一个事务能保证数据库从一个有效(正确)的状态“转移”到另一个有效(正确)的状态。 隔离性(isolation)指一个事务所做的修改在最终提交以前,对其他事务是不可见的。 持久性(durability)是指事务提交成功,所做的修改就一定会永久保存到数据库中。

  • 原子性是通过undo log日志保证的。
  • 一致性一般是业务层进行逻辑判断实现的,比如限定余额不能为负。
  • 隔离性是通过多版本并发控制机制实现的。
  • 持久性是通过redo log日志保证的。

在MySQL中,有三种日志。分别是redo log、binlog和undo log。

redo log 和 binlog
1、存储的内容

可以这样理解,binlog记载的是update/delete/insert这样的SQL语句,而redo log记载的是物理修改的内容(xxxx页修改了xxx)。所以在搜索资料的时候也会有这样的说法:binlog 记录的是数据的逻辑变化,redo log 记录的是数据的物理变化

2、功能

redo log的作用是实现持久化。数据库更新写完内存,如果数据库挂了,那我们可以通过redo log来恢复内存还没来得及刷到磁盘的数据,将redo log加载到内存里边,那内存就能恢复到挂掉之前的数据了。

binlog的作用是进行复制和恢复。

主从服务器需要保持数据的一致性,通过binlog来同步数据。

如果整个数据库的数据都被删除了,binlog存储着所有的数据变更情况,那么可以通过binlog来对数据进行恢复。

3、载体

redo log是InnoDB引擎特有的。binlog是MySQL的Server层实现的,所有引擎都可以使用。

4、记录方式

redo log是循环写的,空间固定会用完;binlog是追加写入的,一个文件写满后会切换到下一个文件而不会去覆盖以前的日志。

undo log
undo log主要有两个作用:回滚和多版本并发控制(MVCC)

在数据修改的时候,不仅记录了redo log,还记录undo log,如果因为某些原因导致事务失败或回滚了,可以用undo log进行回滚undo log主要存储的也是逻辑日志,比如我们要insert一条数据了,那undo log会记录的一条对应的delete日志。我们要update一条记录时,它会记录一条对应相反的update记录。

回滚的实现就是找到undo log中对应的相反操作语句执行。 而多版本并发控制则是利用undo log做版本的回退(聊MVCCC时再具体讲)

2、事务隔离级别,4个级别分别有什么并发问题?

1⃣️ mysql的数据隔离级别如下:

  • 可串行化(serializable):通常保证可串行化调度。
  • 可重复读(repeatable-read):只允许读取已提交的数据。
  • 已提交读(read committed):只允许读取已提交的数据,但是不要求可重复读。
  • 未提交读(read uncommitted):允许读取未提交的数据,这是SQL允许的最低的一致性级别

2⃣️ 事务的并发问题

  • 脏读:事务A读取了事务B更新的数据,然后事务B回滚,那么A读取到的数据就是脏数据
  • 不可重复读:事务A多次读取同一个数据,事务B在事务A读取的时候对数据作了更新并提交,事务A多次读取同一个数据的时候,结果不一致。
  • 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读
  • 丢失更新:修改的时候允许修改,进而造成数据丢失

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。

3⃣️ MySQL各个隔离级别可能会出现的并发问题:

![image-20220312155907744](/Users/weiyifeng/Library/Application Support/typora-user-images/image-20220312155907744.png)

3、MySQL默认隔离级别?如何保证线程安全?

mysql的默认隔离级别为——可重复读(repeatable read)

主从复制是基于binlog复制的,binlog有三种格式,分别是statement、row、mixed。

但是在5.0这个版本以前,binlog只支持statement这种格式!而这种格式在读已提交(read-committed)这个隔离级别下的主从复制是有bug的,因此MySQL将可重复读(Repeatable - read)作为默认的隔离级别。

bug的原因其实很简单,就是在master上执行的顺序为先删后插!而此时binlog为STATEMENT格式,它记录的顺序为先插后删!从(slave)同步的是binglog,因此从机执行的顺序和主机不一致!就会出现主从不一致!

如何解决?
解决方案有两种!
(1)隔离级别设为可重复读(Repeatable Read),在该隔离级别下引入间隙锁。当Session 1执行delete语句时,会锁住间隙。那么,Session 2执行插入语句就会阻塞住!
(2)将binglog的格式修改为row格式,此时是基于行的复制,自然就不会出现sql执行顺序不一样的问题!奈何这个格式在mysql5.1版本开始才引入。因此由于历史原因,mysql将默认的隔离级别设为可重复读(Repeatable Read),保证主从复制不出问题!

在实际项目中使用读已提交,而不使用默认的可重复读的原因:

  • 在可重复读的隔离级别下,存在间隙锁,导致出现死锁的概率要比读已提交大的多!
  • 在可重复读的隔离级别下,条件列未命中索引会缩表,而在读已提交的隔离级别下,只锁行。
  • 在读已提交这个隔离级别下,引入了半一致性读的特性增加了update操作的可能。

总结:互联网项目请使用读已提交这个隔离级别!

# 补充内容,使用命令行更改数据库的隔离级别

#查看当前会话的隔离级别
select @@tx_isolation;

#查看当前系统的隔离级别
select @@global.tx_isolation;

#设置当前对话的隔离级别
set session transaction isolation level repeatable read;

#设置系统当前的隔离级别
set global transaction isolation level repeatable read;

如何保证线程安全还未补充


4、存储引擎Innodb和Myisam的区别以及使用场景?

1⃣️ 二者最大的区别就是Innodb支持事务,而Myisam不支持事务。

它们主要区别如下:

1)InnoDB 支持崩溃后安全恢复,MyISAM 不支持崩溃后安全恢复;

2)InnoDB 支持行级锁,MyISAM 不支持行级锁,只支持到表锁;

3)InnoDB 支持外键,MyISAM 不支持外键;

4)MyISAM 性能比 InnoDB 高 —— Myisam是一种非事务性的引擎,使得Myisam引擎的mysql可以提供高速存储和检索,以及全文搜索能力,适合数据仓库等查询频繁的调用;

5)MyISAM 支持 FULLTEXT 类型的全文索引,InnoDB 不支持 FULLTEXT 类型的全文索引,但是 InnoDB 可以使用 sphinx 插件支持全文索引,并且效果更好;

6)InnoDB 主键查询性能高于 MyISAM。

2⃣️ 如何选择

MyISAM适合:

  • (1)做很多count 的计算;
  • (2)插入不频繁,查询非常频繁,如果执行大量的SELECT,MyISAM是更好的选择;
  • (3)没有事务。

InnoDB适合:

  • (1)可靠性要求比较高,或者要求事务;
  • (2)表更新和查询都相当的频繁,并且表锁定的机会比较大的情况指定数据引擎的创建;
  • (3)如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表;
  • (4)DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的 删除;
  • (5)LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

5、介绍Innodb锁机制,行锁,表锁,意向锁

为什么要加锁:锁机制用于管理对共享资源的并发访问。

6、哈希索引是怎么实现的?

7、数据库索引为什么要使用B+树,相较于B树有什么优点?为什么不能用红黑树?

8、如何避免全表扫描?

1、应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫描。

2、应尽量避免在where子句中使用!=或< >运算符,否则将导致引擎放弃使用索引而进行全表扫描。

3、应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。

4、in 和 not in也要慎用,否则也会导致全表扫描。

5、尽量避免使用模糊查询like,如果因为业务需要一定要使用模糊查询,则至少保证不要使用全模糊查询。

6、尽量避免在where子句中使用参数

7、应尽量避免在where子句中对字段进行表达式操作

8、应尽量避免在where子句中对字段进行函数操作

9、不要在where子句中的“=”的左边使用函数、算术运算或其他表达式运算

10、很多时候使用exists代替in是一个很好的选择

11、任何地方都不要使用select * from t,用具体的字段列表代替*,不要返回用不到的任何字段。

12、尽量避免大事务操作,提高系统并发能力

13、尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应的需求是否合理;

9、MySQL中一条SQL语句的执行过程?

csdn博客地址

根据要执行的语句的类型的不同,可以简单分为查询语句和更新语句两种情况,这两种语句的执行过程是不同的。

10、数据库几大范式?

posted @ 2022-03-12 20:30  yfwei  阅读(68)  评论(0编辑  收藏  举报