数据库常识:
1、数据库系统包含什么?
包含了数据库、数据库管理系统、数据库管理员和应用程序。
数据库(DB):顾名思义是存放数据的仓库,实现数据的持久化。
数据库管理系统(DBMS):类似于操作系用(OS),是计算机的基础软件,比如Mysql就是一种关系型的数据库管理系统,实现了对数据的统一管理与操纵。
数据管理员:人,数据库管理员负责管理和维护数据库系统
应用程序:应用程序是使用数据库系统的最终用户,它们通过执行数据库操作来实现特定的业务逻辑和功能。
2、数据库设计的步骤:
需求分析->概念设计->逻辑设计->物理设计->实施与应用以及维护。
对应用户要求->设计E-R图->将E-R图装换为数据模型(如关系模型)->建立索引(形成物理存储安排)
3、范式
第一范式:指属性不可再分(比如学籍可再分为学号和居住地,就不满足第一范式)
第二范式:指消除了非主属性对主键的部分函数依赖(比如主键是学号、课程号,非主属性是姓名,只对学号产生依赖,此时有必要拆分成两个表,避免这种依赖关系)
第三范式:消除了非主属性对主键的传递函数依赖(比如说主键是学号,非主属性是宿舍号和宿舍楼楼妈姓名,此时楼妈姓名就对学号产生了传递依赖,因为学号->宿舍号->楼妈姓名。)
BC范式:消除了主键内部主属性之间的部分函数依赖和传递依赖。
4、其他科班基本概念比如数据库的系统模式、数据库关系完整性等、以及主码、候选码等基本概念此处不赘述。
MySQL数据库:
一、事务
1、事务的四大基本特性是什么?在MySQL中是怎么实现的?
ACID四大基本特性指的是原子性、一致性、隔离性、持久性,在MySQL中如何实现呢?
①、原子性(Atomic):原子性是指事务中的语句要么全部执行,要么全部失败。MySQL中原子性是通过undo log来实现的,undo log是重做日志,会记录事务的操作,当事务执行失败后,MySQL 可以使用 undo log 进行回滚,撤销已经执行的操作,从而保证原子性。
②、一致性(Consistency):在 MySQL 中,一致性是通过事务管理和数据库约束来实现的。MySQL 提供了各种类型的约束,如主键约束、唯一约束、外键约束等,用于保证数据库的一致性。此外,MySQL 在执行事务时也会检查数据库的完整性约束,以确保事务执行前后数据库的一致性。
③、隔离性(Isolation):隔离性要求事务之间彼此独立,互不干扰。即使多个事务同时访问数据库,每个事务也应该像没有其他事务存在一样进行。在 MySQL 中,隔离性是通过事务管理和锁机制来实现的。MySQL 提供了四种隔离级别(Read Uncommitted、Read Committed、Repeatable Read、Serializable),用于控制事务之间的隔离程度。通过使用锁机制和多版本并发控制(MVCC),MySQL 可以确保事务之间的隔离性。
④、持久性(Durability):持久性要求事务一旦提交,其结果应该永久保存在数据库中,即使系统崩溃也不应该丢失。在 MySQL 中,持久性是通过事务管理和日志系统来实现的。MySQL 使用 redo log 来记录事务的操作,在事务提交后将操作记录到磁盘上,以确保即使系统崩溃,事务的结果也不会丢失。
2、数据库事务常遇到的三种问题
①、脏读:事务A对某数据做了修改,改完后事务B读取了该数据,但是事务A后续出错发生回滚,数据恢复原值,事务B读取到的就是脏数据。
②、不可重复读:事务A读取某数据后,事务B介入修改了该数据,事务A重复读取该数据,此时前后读取数据不一致,发生了重复读现象。
③、幻读:幻读指的是事务A两次执行相同的查询得到的结果不一致。这是因为在两次执行查询之间,另一个事务B插入了新的数据,导致了查询结果的变化。幻读与不可重复读类似,但不同之处在于幻读关注的是新增的数据而不是修改的数据。
3、四种事务隔离机制
①、读未提交:不解决任何问题,最差的隔离机制
②、读已提交:解决了脏读问题
③、可重复读:解决脏读问题、不可重复读问题,其是MySQL数据库的默认隔离级别
④、串行化:解决了全部的三个问题
二、索引
1、索引是什么?数据库中的索引常见的数据据结构有哪些?
def:索引是一种用于快速查询和检索数据的数据结构,其本质可以看成是一种排序好的数据结构。
常见数据结构:哈希表、二叉查找树、AVL树、红黑树、B树&B+树(MySQL中的两版存储引擎InnoDB和MyISAM均使用B+树)
2、 为什么InnoDB不用哈希表、二叉查找、AVL树、红黑树?(比较数据结构问题)B+树的优势在哪里?
比较:
哈希表会发生哈希碰撞,哈希索引适合用于等值查询。
二叉树很容易退化成链表,查询时间复杂度达到O(n)级别。
AVL树由于 需要频繁地进行旋转操作来保持平衡,因此会有较大的计算开销进而降低了数据库写操作的性能。并且, 在使用 AVL 树时,每个树节点仅存储一个数据,而每次进行磁盘 IO 时只能读取一个节点的数据,如果需要查询的数据分布在多个节点上,那么就需要进行多次磁盘 IO。
红黑树并不追求严格的平衡,而是大致的平衡。正因如此,红黑树的查询效率稍有下降,因为红黑树的平衡性相对较弱,可能会导致树的高度较高,这可能会导致一些数据需要进行多次磁盘 IO 操作才能查询到,这也是 MySQL 没有选择红黑树的主要原因。
B+树的优势:
1、首先B+树实现了非叶子节点存放索引,叶子的节点存放数据,使得查询效率稳定(相比B树)
2、B+树的叶子节点之间使用双向链表链接,便于进行范围查询。
3、作为多路平衡搜索树,相对高度低,适合于存储大规模数据集。
3、聚簇索引和非聚簇索引的区别?
聚簇索引:在聚簇索引中,数据与索引结构放在一起。换句话说,聚簇索引将表中的数据行存储在索引的叶子节点中,因此索引和数据是紧密关联的;在聚簇索引中,索引的键值必须是唯一的,因为索引的顺序与数据的顺序一致,不能有重复的键值;由于数据行的顺序与索引的顺序一致,因此通过聚簇索引进行范围查询或排序操作时,性能通常更好。但是,插入、删除和更新操作可能会导致数据移动,影响性能。 聚簇索引是一种物理排序索引,决定了数据行的物理存储引擎,聚簇索引的叶子节点上存放了该行所有的数据。
非聚簇索引:在非聚簇索引中,索引的叶子节点中存储的是指向实际数据行的指针或引用,而不是实际的数据行。因此,索引和数据是分开存储的;索引的键值可以是重复的,因为实际的数据行是分开存储的,不受索引的唯一性限制;非聚簇索引可以加速查询操作,特别是在搜索范围较小的情况下,但是范围查询和排序操作的性能可能不如聚簇索引高。非聚簇索引又称为二级索引,比如普通索引、唯一索引,其叶子节点上存放的是主键值。
4、主键索引和聚簇索引的关系?
主键索引和聚簇索引是密不可分的,主键是唯一且非空的,其作为表中唯一的标识符而存在,如果没有定义主键,则会默认唯一非空的其他键为主键。一般默认定义的主键索引就是聚簇索引。
5、二级索引有哪些?
包括唯一索引、普通索引、前缀索引、全文索引。
6、覆盖索引是什么?
覆盖索引是指查询使用了索引,并且需要返回的列,刚好在该索引中可以全部找到,不需要回表查询。比方说student(Sno,Sname,Ssex),其中Sno为主键,其主键索引实现了聚集索引,走Sno来查询效率就很高,Sname实现了普通索引,走这个二级索引来查询效率也可以,Ssex啥也不是这时有select Sno,Sname from student where Sno = '2',效率很好。但是若是select * from student where Sno = '2',就需要回表查询了,效率就降低了
使用覆盖索引的思路还可以解决超大分页的问题:
MySQL中分页是通过limit语句来实现的,例如select * from student limit 5,5,意思就是5条信息一页,我现在查看第6行-第10行的信息即第二页的信息。MySQL中的超大分页是指select * from student limit10000000,10,即查看第10000001页的信息,MySQL会对前面的数据排序,这样会导致查询时间长,可以使用覆盖索引来改进。改进后的语句:select * from student a,(select Sno from student order by sno limit 10000000,10) b where a.sno = b.sno,可大大提高查询效率。
7、联合索引
将多个列作为索引:
ALTER TABLE `cus_order` ADD INDEX id_score_name(score, name);
8、索引失效的场景:
1、使用联合索引时违背了最左前缀法则
(图片源自黑马)
2、建立索引后右边的列用到了范围查询
3、建立索引的字段上进行运算操作
4、建立索引的字段上发生类型强转
5、模糊查询以%开头
9、SQL语句执行很慢如何解决?
使用explain关键字来检查SQL语句
Key字段可以用来检测是否命中了索引,Extra字段查看是否发生回表查询(Using index condition表示使用了回表查询,Using index表示不需要使用回表查询)
Type字段:从上至下,性能逐渐变差:应该避免使用index和all,常用的是er_ref和ref。
三、锁机制
1、表级锁和行级锁了解吗?
-
行级锁(Row-level Locking):
- 行级锁是最细粒度的锁,它可以锁定数据表中的单行数据。当某个事务对数据行进行修改时,可以使用行级锁将该行数据锁定,防止其他事务同时修改同一行数据,从而保证数据的一致性。
- MySQL 使用 InnoDB 存储引擎默认支持行级锁,通过在事务中使用
SELECT ... FOR UPDATE
或SELECT ... LOCK IN SHARE MODE
等语句来获取行级锁。
-
表级锁(Table-level Locking):
- 表级锁是对整个数据表进行锁定,当某个事务对数据表进行修改时,可以使用表级锁将整个表锁定,防止其他事务同时对整个表进行修改,从而保证数据的一致性。
- MySQL 中的 MyISAM 存储引擎默认使用表级锁,通过在事务中使用
LOCK TABLES
和UNLOCK TABLES
等语句来获取和释放表级锁。
2、行级锁使用的注意事项:
InnoDB 的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。当我们执行 UPDATE
、DELETE
语句时,如果 WHERE
条件中字段没有命中唯一索引或者索引失效的话,就会导致扫描全表对表中的所有行记录进行加锁。
3、InnoDB有哪几类行锁:
InnoDB 行锁是通过对索引数据页上的记录加锁实现的,MySQL InnoDB 支持三种行锁定方式:
- 记录锁(Record Lock):也被称为记录锁,属于单个行记录上的锁。
- 间隙锁(Gap Lock):锁定一个范围,不包括记录本身。
- 临键锁(Next-Key Lock):Record Lock+Gap Lock,锁定一个范围,包含记录本身,主要目的是为了解决幻读问题(MySQL 事务部分提到过)。记录锁只能锁住已经存在的记录,为了避免插入新记录,需要依赖间隙锁。
MySQL可重复读这个默认隔离级别下使用的是临键锁 。
4、共享锁和排他锁:
概念类似于ReentrantReadWriteLock中的读锁和写锁。
5、意向锁:
作用:意向锁的作用是为了在获取行级锁之前,提前通知其他事务本事务的锁定意向,以便其他事务可以根据这个信息来避免锁冲突或提前释放资源。这样可以提高事务并发性,保证数据的一致性和完整性。
意向锁是表级锁,共有两种:
- 意向共享锁(Intention Shared Lock,IS 锁):事务有意向对表中的某些记录加共享锁(S 锁),加共享锁前必须先取得该表的 IS 锁。
- 意向排他锁(Intention Exclusive Lock,IX 锁):事务有意向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先取得该表的 IX 锁。
6、MVCC了解吗?
MVCC(Multi-Version Concurrency Control)多版本并发控制机制,在MVCC中,每个事务在启动时都会创建一个独立的一致性视图(Snapshot),用于读取数据。这个一致性视图反映了事务启动时数据库的状态,包括已提交的事务和未提交的事务对数据库所做的修改。而在事务执行期间,其他事务对数据库的修改不会影响到已经创建的一致性视图。
MVCC的实现通常依赖于两个关键机制:
-
版本号:每个数据行都会有一个版本号(或者说是时间戳),用于标识该数据行的修改历史。当一个事务对数据行进行修改时,会为修改前的数据行创建一个新版本,并更新数据行的版本号。
-
Undo log:用于存储数据行的历史版本信息。在数据库中,如果一个事务需要读取旧版本的数据,可以通过Undo log来获取。
四、存储引擎
InnoDB和MyISAM的区别:
InnoDB 和 MyISAM 是 MySQL 中两种常见的存储引擎,它们在设计理念、功能特性、性能表现等方面有很多不同之处。以下是它们的主要区别:
-
事务支持:
- InnoDB 支持事务(Transaction),具有 ACID(Atomicity、Consistency、Isolation、Durability)特性,可以实现事务的原子性、一致性、隔离性和持久性。
- MyISAM 不支持事务,不具备事务的特性,因此不能保证数据的完整性和一致性。
-
行级锁:
- InnoDB 使用行级锁(Row-level Locking),可以在并发情况下更好地处理多个事务对同一数据行的访问。
- MyISAM 使用表级锁(Table-level Locking),只能对整个表进行锁定,无法实现精细的并发控制,可能会导致锁冲突和性能瓶颈。
-
崩溃恢复:
- InnoDB 依赖如redo log可以在数据库崩溃或异常情况下保证数据的持久性和一致性。
- MyISAM 不支持崩溃恢复和事务日志,容易在数据库崩溃或异常情况下导致数据丢失或损坏。
-
表级缓存:
- InnoDB 使用行级缓存,可以减少锁冲突和提高并发性能。
- MyISAM 使用表级缓存,可能会导致大量的表锁等待和性能瓶颈。
5.索引方式:
1.InnnoDB使用的是聚簇索引。
2.MyISAM使用的是非聚簇索引。
五、MySQL三大日志
1、bin log:
归档日志属于server层,是 MySQL 的二进制日志文件,用于记录数据库的所有修改操作,包括数据变更、数据库结构变更等。归档日志是以二进制格式存储的,可以用于数据备份、数据复制、数据恢复等操作。主从复制和数据库恢复过程中都会用到归档日志。
2、redo log:
重做日志是 InnoDB 存储引擎的一部分,用于记录事务对数据库的修改操作。当执行事务提交时,对应的修改操作会先写入重做日志,然后再写入数据库的数据文件。这样即使在事务提交之前数据库发生崩溃,MySQL 可以通过重做日志来恢复未完成的事务,确保数据的一致性和持久性。
3、undo log:
Undo日志是MySQL中用于实现事务的回滚和MVCC(多版本并发控制)的一种机制。它记录了事务对数据库进行修改之前的数据值,以便在事务回滚时将数据恢复到修改之前的状态,Undo日志是MySQL中非常重要的一个组成部分,它提供了事务回滚、MVCC实现和长事务控制等功能,保证了数据库的一致性和可靠性。
六、数据库的优化
1、读写分离:
读写分离是数据库优化的一种措施,其是指通过多个从数据库实现读功能,写功能则交给主数据库完成,主从数据的同步是通过bin log来实现的,主服务器上的数据是最新的,它负责维护数据库的一致性和完整性,从服务器上的数据是主服务器的一个副本,因此可以处理大量的读取请求,减轻了主服务器的负载压力。
存在问题:主从数据一致性问题,可以使用bin log来同步、数据库中间件如MySQL proxy或者通过触发器来实现同步。
2、分库分表:
Q: 如果 MySQL 一张表的数据量过大怎么办?换言之,我们该如何解决 MySQL 的存储压力呢?
分库可以通过两种方式,水平分库和垂直分库。
垂直分库是指将数据库按照业务划分来进行分库,比如用户表、订单表等表的数据量巨大,可以根据业务直接垂直分库为用户数据库、订单数据库。。。
水平分库是指把同一个表按一定规则拆分到不同的数据库中,每个库可以位于不同的服务器上,这样就实现了水平扩展,解决了单表的存储和性能瓶颈的问题。
分表也有两种方式,水平分表和垂直分表。
垂直分表是指对数据表列的拆分,把一张列比较多的表拆分为多张表
水平分表是指是对数据表行的拆分,把一张行比较多的表拆分为多张表,可以解决单一表数据量过大的问题。
3、分库分表带来的问题?怎么解决?
分库分表会导致数据分布在不同的数据库实例或数据表中,可能会出现数据不一致的情况。例如,跨数据库实例的事务需要通过分布式事务管理器来保证数据的一致性,而跨数据表的事务可能会受到分布式锁的影响。
会增加系统的复杂度,包括数据同步、数据迁移、数据备份和恢复等方面的操作都会变得更加复杂和困难。
跨库查询和跨表查询可能会导致性能问题,因为需要在多个数据库实例或数据表之间进行数据的传输和处理。特别是在大数据量和高并发的情况下,可能会影响查询的性能和响应时间。
解决方式:
使用Apache ShardingSphere,其是一款分布式的数据库生态系统, 可以将任意数据库转换为分布式数据库,并通过数据分片、弹性伸缩、加密等能力对原有数据库进行增强。
Redis
1、Redis的持久化机制:
①、RDB快照:RDB快照是以快照的方式将内存中的数据写进磁盘中,写进形式是二进制的。RDB 的优点是它生成的文件相对来说比 AOF 文件更小,因为它是快照,只保存了在某个时间点上的数据状态。
②、AOF文件:AOF 以日志的形式记录服务器接收到的写命令,以此来记录数据的变化。这个日志文件是一个只进行追加操作的日志文件,AOF 文件通常比 RDB 文件更大,因为它记录了每个写命令。
③、还有二者混合的持久化方式。
④、RDB快照和AOF文件形式相比较。RDB速度更快,但是缺点在于记录的是上一次快照的信息,AOF相比起来文件会更大,但是安全性会更好,并且在数据库崩溃时,通常使用AOF文件来恢复信息。
2、Redis中五种基本数据类型和其对应的数据结构是什么?
Redis的五种基本数据类型包括String、List、Hash、Set、Zset(有序集合),底层数据结构分别是简单动态字符串、双向链表、哈希表、哈希表、压缩列表->跳表
3、Redis的应用场景有哪些?
①、Redis 最常见的用途之一是作为缓存层,将经常访问的数据缓存在内存中,以加速读取速度。通过将数据库查询结果或计算结果缓存到 Redis 中,可以大幅度减少数据库或其他后端服务的压力。
从他的数据结构出发,来详细分析一下Redis不同数据结构常见的应用场景:
②、String数据类型常被用作分布式锁、计数器
③、List数据类型底层时双向链表,所以常被用作消息的推送,比如微信公众号的新消息推送、微博的新微博发送。
④、Set数据类型底层是哈希表,其不允许有重复值存在,可以求并集、求交集,应用场景包括共同关注、共同好友等。
⑤、Hash数据类型的底层是哈希表,其常常被用于购物车场景,Redis中存储数据本身就是一个大的<k,v>,k对应的数据结构往往是String类型,V对应的数据结构是刚刚提到的数据类型。Set本身又是键值对的形式,因此适合于实现购物车,根据购物车id找到对应的商品id,商品id又对应商品的价格。
⑥、Zset有序集合,应用场景有排行榜,如微信运动排行榜、直播间礼物榜、
4、Redis的生产问题(重要);
①、缓存穿透:缓存穿透指的是大量恶意或者非法的请求经过缓存系统直接访问数据库,由于缓存系统无法命中缓存,每次请求都要直接访问后端存储,导致数据库宕机。
解决措施:可以在缓存层增加布隆过滤器等机制来拦截不存在的请求;接口限流,将恶意访问拉入黑名单
②、缓存击穿:是指在缓存中的某个热点数据刚好过期了,这时有大量的请求落到了数据库上,导致数据库的崩盘
解决措施:可以设置热点数据永不过期;可以给请求上互斥锁,避免同一时间大量访问。
③、缓存雪崩:大量缓存同时失效,使得大量的请求落在了数据库上。
解决措施:设置不同的过期时间;部署Redis集群,避免单机出现问题;设置缓存。