回答重点逻辑外键是一种在应用程序层面上管理和维护数据完整性的方法,而不是通过数据库本身的外键约束。主要是利用应用程序代码来保证引用的完整性。
逻辑外键的优缺点优点:
灵活性高:应用程序层面控制,可以更灵活地实现复杂的业务逻辑。
性能优化:避免了数据库层面的约束检查,可以在某些情况下提高性能(详细看扩展知识)。
跨数据库兼容性:逻辑外键在不同类型的数据库之间更容易迁移。
缺点:
代码复杂...
回答重点如果没有 MVCC,系统必须频繁地对读写操作进行加锁来保证数据的正确性,因为增加了锁的获取和释放的开销,会导致整体系统响应速度变慢,这种实现叫 LBCC (Lock-Based Concurrent Control)。
扩展知识LBCC (Lock-Based Concurrent Control)想象一下有一个事务 1 正在执行,此时一个事务 2 修改了记录 A,还未提交事务。
此...
回答重点MySQL 默认的隔离级别是可重复读( Repeatable Read ),即 RR。
原因是为了兼容早期 binlog 的 statement 格式问题,如果是使用读已提交、读未提交等隔离级别,使用了 statement 格式的 binlog 会导致主从(备)数据库数据不一致问题。
扩展知识进一步分析 binlog statement 格式和可重复级别的影响接下来我们来展开讲解下,...
回答重点1)脏读(Dirty Read):
一个事务读取到另一个事务未提交的数据。如果该未提交事务最终被回滚,那么第一个事务读取的数据就是不一致的(脏的)。
2)不可重复读(Non-repeatable Read):
在同一事务中,读取同一数据两次,但由于其他事务的提交,读取的结果不同。例如,事务 A 读取了一行数据,事务 B 修改并提交了这行数据,导致事务 A 再次读取时得到不同的值...
回答重点自动检测与回滚:
MySQL 自带死锁检测机制(innodb_deadlock_detect),当检测到死锁时,数据库会自动回滚其中一个事务,以解除死锁。通常会回滚事务中持有最少资源的那个。
也有锁等待超时的参数(innodb_lock_wait_timeout),当获取锁的等待时间超过阈值时,就释放锁进行回滚。
手动 kill 发生死锁的语句:
可以通过命令,手动快速地找出被...
回答重点在 MySQL 中,int(11) 中的 11 表示显示宽度,并不影响存储的大小或数值范围。具体来说:
显示宽度:当使用 ZEROFILL 属性时,int(11) 表示如果数值的位数少于 11 位,则会在前面填充零。例如,数值 42 将显示为 00000000042。不使用 ZEROFILL 时,显示结果是 42(前面有九个空格)
存储大小:int 类型始终占用 4 字节(32 位...
回答重点CHAR 和 VARCHAR 是两种用于存储字符串的列类型,它俩最大的不同就是一个是固定长度,一个是可变长度。
CHAR(n):固定长度的字符串。CHAR 列的长度是固定的,即使存储的字符串长度小于定义的长度,MySQL 也会在字符串的末尾填充空格以达到指定长度(如果 char 类型的字符串后面有空格的话,innodb 会忽略)。
VARCHAR(n):可变长度的字符串。VARCH...
回答重点一般会使用主从架构来避免单点故障,主数据库处理写操作,从数据库处理读操作,主数据库故障时可以切换到从数据库。
同时会对数据进行定期备份并存储在不同的物理位置,以便在发生故障时能够快速恢复数据。
并且需要建立监控系统,实时监控数据库的健康状态,并在发生故障时及时告警。
扩展知识MySQL 主从,主备或者主主架构介绍
主备架构主备架构就是主机和备机。备机是不干活的,也就是不对外提供服务,...
回答重点
首先需要明确一个点延迟是必然存在的,无论怎么优化都无法避免延迟的存在,只能减少延迟的时间。
常见解决方式有以下几种:
二次查询。如果从库查不到数据,则再去主库查一遍,由 API 封装这个逻辑即可,算是一个兜底策略,比较简单。不过等于读的压力又转移到主库身上了,如果有不法分子故意查询必定查不到的查询,这就对主库产生冲击了。
强制将写之后立马读的操作转移到主库上。这种属于代码写死了...
回答重点做法一:代码封装讲白了就是代码层面抽出一个中间层,由中间层来实现读写分离和数据库连接。
利用个代理类,对外暴露正常的读写接口,里面封装了逻辑,将读操作指向从库的数据源,写操作指向主库的数据源。
优点:简单,并且可以根据业务定制化变化,随心所欲。
缺点:如果数据库宕机了,发生主从切换了之后,就得修改配置重启。如果系统是多语言的话,需要为每个语言都实现一个中间层代码,重复开发。
做法...
回答重点1)先分析业务需求:
确定数据量及增长趋势,评估分库分表的必要性。(需要一定的预判但是不要过度设计)
2)设计分库分表方案:
选择适合的分库和分表策略(水平、垂直、哈希、范围等),并规划分库分表的结构。
3)实现数据路由:
根据分库分表策略设计数据路由机制,一般通过应用层代码或数据库中间件来实现,将请求路由到相应的数据库或表。
4)数据迁移:
将现有数据迁移到新的分库分...
回答重点1)首先是事务的问题。
我们使用关系型数据库,有很大一点在于它保证事务的完整性。
而分库之后单机事务就用不上了,必须使用分布式事务来解决,而分布式事务相对而言就比较重了,而且大部分的分布式事务只能保证最终一致性,所以业务上会存在数据不一致的场景。
2)连表 JOIN 问题
在一个库中的时候我们还可以利用 JOIN 来连表查询,而跨库了之后就无法使用 JOIN 了。
此时的解决方案就是...
回答重点在 MySQL 中,获取数据并不总是直接从磁盘读取。MySQL 使用缓存机制,比如 InnoDB 存储引擎,会将常用的数据和索引缓存在内存中,以提高读取性能。当查询数据时,系统首先会检查缓存(如缓冲池),如果数据存在于内存中,则直接从内存中读取;如果不在,则会从磁盘读取并加载到缓存中。
扩展知识MySQL 中的缓存MySQL 从缓存中读取所指的缓存,实际上包含了两个缓存:
1)查询缓...
回答重点分库分表是数据库性能优化的一种方法,通过将数据分散存储在多个数据库或表中,来提高系统的可扩展性、性能和可用性。
分库分表的类型(或策略) 包括:
1)水平分表:
将同一张表的数据按行划分,分散到多个表中。例如,可以按用户 ID 的范围将数据分为多个表(如 user_1、user_2)。
2)垂直分表:
将一张表的不同列拆分到多个表中,以减少每张表的字段数量和提高查询效率。例如,...
回答重点MySQL 的 Doublewrite Buffer 是 InnoDB 存储引擎中的一个机制,用于确保数据的安全性和一致性。其作用是将数据首先写入一个内存缓冲区(双写缓冲区),然后再将其写入数据文件。这种方式可以防止在写入过程中因崩溃或故障导致数据损坏,确保数据的一致性和完整性。
工作原理简述:
写入流程:当事务提交时,InnoDB 首先将数据写入 Doublewrite Buff...
回答重点性能问题:
多表 JOIN 可能导致查询性能下降,尤其是在处理大数据集时,JOIN 操作的计算复杂度会显著增加,需要进行大量的数据扫描和匹配,增加了内存和CPU的消耗,导致响应时间变长。
可读性和维护性:
多表 JOIN 的查询语句较为复杂,降低了 SQL 的可读性和可维护性。复杂的语句可能会增加错误发生的概率,使得后续的调试和优化更加困难。
扩展知识多表 JOIN这里的多表...
回答重点MySQL 中的 Log Buffer 是一个内存区域,用于暂时存储事务日志(redo log)的数据。在 InnoDB 存储引擎中,它的主要作用是提高性能,通过批量写入操作将日志数据从内存中写入磁盘,减少磁盘 I/O 操作的频率。
扩展知识进一步理解 Log Buffer我们来看一下官网的一张图:
我们看看 Log Buffer。从上面的图我们可以得知,它是 redo...
回答重点优化方式可以有三种:
1)子查询
比如 select * from mianshiya where name = ’yupi‘ limit 99999990,10; 这样的一条查询语句,可以优化成:
12345select * from mianshiya where name = 'yupi' and id >= (select id from mians...
回答重点可以利用 MySQL 自带的 slow_query_log 来监控慢 SQL,它是 MySQL 提供的一个日志功能,用于记录执行时间超过特定阈值的 SQL 语句。
对于慢查询,再使用 EXPLAIN 分析执行计划,查看查询的执行顺序、使用的索引、扫描的行数等,以识别潜在的性能瓶颈。
基于 EXPLAIN 再进行针对性的优化,常见的优化方向有:
根据 EXPLAIN 的结果,检查是否...
回答重点
Delete 用于删除行数据,但保留表结构和相关的对象。
Drop 用于完全删除数据库表,包括数据和结构。
Truncate 只删除数据,不会删除表结构和索引等其他结构。
从性能来看,Drop > Truncate > Delete
扩展知识Delete本质上这个删除其实就是给数据行打个标记,并不实时删除,因此 delete 之后,空间的大小不会变化。
而且 del...
回答重点INNER JOIN:
只返回两个表中匹配的行。如果没有匹配,则该行不会出现在结果集中。
适用于只关心交集数据的场景。
LEFT JOIN(或 LEFT OUTER JOIN):
返回左表中的所有行,即使右表中没有匹配的行。如果右表没有匹配,则结果中的右侧列会显示为NULL。
适用于需要保留左表所有数据的场景。
RIGHT JOIN(或 RIGHT OUTER JOIN):
...
回答重点MySQL 事务的二阶段提交是指在 MySQL 中,为了确保redo log(重做日志)和 binlog(二进制日志)之间的一致性,使用的一种机制。MySQL 通过二阶段提交来保证在crash recovery(崩溃恢复)时,不会出现数据丢失或数据不一致的情况。
二阶段提交的两个阶段:
准备阶段(Prepare Phase):在事务提交时,MySQL 的 InnoDB 引擎会先写入...
回答重点在 MySQL 的 InnoDB 存储引擎中,B+ 树默认数据页大小为 16KB。
参数:
每个节点页大小为 16KB(即 16384 字节)。
假设每个数据记录的主键和数据大小为 1KB(一般会比这个小,但这里取整方便计算)。
每个内部节点(非叶子节点)存储的是指向子节点的指针和索引键。
三层 B+ 树的存储计算:
叶子节点:第三层为叶子节点,每个叶子节点页可存储 16 条...
回答重点设计表的时候,在满足业务需求的情况下,需要额外考虑表结构的高效性、扩展性以及维护性。
1)选择合适的数据类型:为字段选择合适的数据类型可以有效减少存储空间,并提高查询效率。例如:
使用 INT 而不是 BIGINT,前提是如果数据不会超出 INT 范围。
使用 VARCHAR 而不是 TEXT,如果字段长度比较短且可变。
使用 DATE、DATETIME 或 TIMESTAMP 而...
这种题目都是开放性的,面试过程中也不奢望聊出所有的设计细节,仅仅需要抛出一些大致的设计需求与要点,然后简单的方案实现思路即可。
关于文件上传系统有几个最主要的核心点需要解决:
1)如何支持超大文件上传2)避免重复文件存储,节省空间3)限流问题
大文件上传假设有个 10 G 的文件需要上传,正常情况下是将文件转成流传到后端,如果不做任何处理,前端一直传,后端存储这些流直到传递完成,后端非常容易...
一般在分库分表场景,就会有分布式 ID 的需求,因为需要有一个唯一标识来标记一个订单或者其他类似的数据等。
全局唯一 ID 有很多种实现,例如 UUID ,优势就是本地生成,很简单。但它是无序的,如果需要将唯一 ID 作为主键,则 UUID 不合适,首先是太长了,其次无序插入会导致数据页频繁分裂,性能不好。
在回答这个面试题的时候可以先提下 UUID,简单说下优缺点(UUID 的缺点其实侧面...
限流是什么?首先来解释下什么是限流?
在日常生活中限流很常见,例如去有些景区玩,每天售卖的门票数是有限的,例如 2000 张,即每天最多只有 2000 个人能进去游玩。
那在我们工程上限流是什么呢?限制的是 「流」,在不同场景下「流」的定义不同,可以是每秒请求数、每秒事务处理数、网络流量等等。
而通常我们说的限流指代的是 限制到达系统的并发请求数,使得系统能够正常的处理 部分 用户的请求,来...
这个问题我觉得可以从 HashMap 的一些关键点入手,例如 hash函数、如何处理冲突、如何扩容。
可以先说下你对 HashMap 的理解。
比如:HashMap 无非就是一个存储 <key,value> 格式的集合,用于通过 key 就能快速查找到 value。
基本原理就是将 key 经过 hash 函数进行散列得到散列值,然后通过散列值对数组取模找到对应的 index 。...
这种设计类问题还是一样,先说下理解,表明你是知道这个东西的用处和原理的,然后开始 阐述。
基本上就是按照现有的设计来说,再添加一些个人见解。
线程池讲白了就是存储线程的一个容器,池内保存之前建立过的线程来重复执行任务,减少创建和销毁线程的开销,提高任务的响应速度,并便于线程的管理。
我个人觉得如果要设计一个线程池的话得考虑池内工作线程的管理、任务编排执行、线程池超负荷处理方案、监控。
初始化...
业务场景一般在即时通讯项目(比如聊天室)中,我们会采用下拉分页的方式让用户加载历史消息记录。
区别于标准分页每次只展示当前页面的数据,下拉分页加载是 增量加载 的模式,每次下拉时会请求加载一小部分新数据,并放到已加载的数据列表中,从而形成无限滚动的效果,确保用户体验流畅。
比如用户有 10 条消息记录,以 5 条为单位进行分页,刚进入房间时只会加载最新的 5 条消息:
下拉后,会加载历史...