回答重点自动检测与回滚:
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)水平分表:
将同一张表的数据按行划分,分散到多个表中。例如,可以按用户 ID 的范围将数据分为多个表(如 user_1、user_2)。
2)垂直分表:
将一张表的不同列拆分到多个表中,以减少每张表的字段数量和提高查询效率。例如,...
回答重点1)先分析业务需求:
确定数据量及增长趋势,评估分库分表的必要性。(需要一定的预判但是不要过度设计)
2)设计分库分表方案:
选择适合的分库和分表策略(水平、垂直、哈希、范围等),并规划分库分表的结构。
3)实现数据路由:
根据分库分表策略设计数据路由机制,一般通过应用层代码或数据库中间件来实现,将请求路由到相应的数据库或表。
4)数据迁移:
将现有数据迁移到新的分库分...
回答重点1)首先是事务的问题。
我们使用关系型数据库,有很大一点在于它保证事务的完整性。
而分库之后单机事务就用不上了,必须使用分布式事务来解决,而分布式事务相对而言就比较重了,而且大部分的分布式事务只能保证最终一致性,所以业务上会存在数据不一致的场景。
2)连表 JOIN 问题
在一个库中的时候我们还可以利用 JOIN 来连表查询,而跨库了之后就无法使用 JOIN 了。
此时的解决方案就是...
回答重点在 MySQL 中,获取数据并不总是直接从磁盘读取。MySQL 使用缓存机制,比如 InnoDB 存储引擎,会将常用的数据和索引缓存在内存中,以提高读取性能。当查询数据时,系统首先会检查缓存(如缓冲池),如果数据存在于内存中,则直接从内存中读取;如果不在,则会从磁盘读取并加载到缓存中。
扩展知识MySQL 中的缓存MySQL 从缓存中读取所指的缓存,实际上包含了两个缓存:
1)查询缓...
回答重点MySQL 的 Doublewrite Buffer 是 InnoDB 存储引擎中的一个机制,用于确保数据的安全性和一致性。其作用是将数据首先写入一个内存缓冲区(双写缓冲区),然后再将其写入数据文件。这种方式可以防止在写入过程中因崩溃或故障导致数据损坏,确保数据的一致性和完整性。
工作原理简述:
写入流程:当事务提交时,InnoDB 首先将数据写入 Doublewrite Buff...
回答重点MySQL 中的 Log Buffer 是一个内存区域,用于暂时存储事务日志(redo log)的数据。在 InnoDB 存储引擎中,它的主要作用是提高性能,通过批量写入操作将日志数据从内存中写入磁盘,减少磁盘 I/O 操作的频率。
扩展知识进一步理解 Log Buffer我们来看一下官网的一张图:
我们看看 Log Buffer。从上面的图我们可以得知,它是 redo...
回答重点性能问题:
多表 JOIN 可能导致查询性能下降,尤其是在处理大数据集时,JOIN 操作的计算复杂度会显著增加,需要进行大量的数据扫描和匹配,增加了内存和CPU的消耗,导致响应时间变长。
可读性和维护性:
多表 JOIN 的查询语句较为复杂,降低了 SQL 的可读性和可维护性。复杂的语句可能会增加错误发生的概率,使得后续的调试和优化更加困难。
扩展知识多表 JOIN这里的多表...
回答重点优化方式可以有三种:
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 而...
回答重点Netty 是高性能 Java 网络通信的底层框架,它使用异步、事件驱动等架构,解决了传统 Java 网络编程中的一些复杂问题:
传统BIO阻塞瓶颈:通过NIO多路复用实现单线程万级连接,避免线程爆炸
原生NIO开发复杂度:封装Selector/Channel/Buffer,提供Pipeline责任链式API
网络编程常见痛点:自带TCP粘包拆包、心跳检测、内存...
回答重点Reactor 是服务端在网络编程时的一个编程模式,主要由一个基于 Selector (底层是 select/poll/epoll)的死循环线程,也称为 Reactor 线程。
基于事件驱动,将 I/O 操作抽象成不同的事件,每个事件都配置对应的回调函数,由 Selector 监听连接上事件的发生,再进行分发调用相应的回调函数进行事件的处理。
React...
回答重点
前置知识:零拷贝的基本理念
避免在用户态和内核态之间拷贝数据,从而降低 CPU 占用和内存带宽的消耗。
除了系统层面的零拷贝,Netty 还强调在 buffer 之间避免不必要的数据拷贝。
Netty 中的零拷贝包括以下四个方面:
零拷贝机制
描述
FileRegion 接口
利用操作系统的 sendfile 系统调用,将文件数据直接从磁盘传输到网络接口,无需...
回答重点Netty 主要采用了 Reactor 模型,且通过细化线程池管理来处理不同的 I/O 任务。
Netty 的线程模型可以分为三个部分:
Boss 线程组:负责接收客户端的连接请求。
Worker 线程组:负责处理 I/O 读写操作。
业务线程组(可选):负责处理具体的业务逻辑。
具体工作机制1)Boss 线程组:
Boss 线程组中的线程(通常是一个)负责监...
回答重点Netty 的应用场景主要有以下几个:
许多框架底层通信的实现,比如说 RocketMQ、Dubbo、Elasticsearch、Cassandra 等,底层都使用到了 Netty。
游戏行业,在游戏服务器开发中,Netty 用于处理大量并发的游戏客户端连接,提供低延迟的网络通信能力
实现一个通讯系统,比如聊天室、IM 等,处理高并发的实时消息传输。
物联网即 IOT 场景,Net...
回答重点Netty 性能高的主要原因如下:
非阻塞 I/O 模型:Netty 底层使用了 NIO 非阻塞模型,并且利用I/O 多路复用,通过 Selector 监听多个 Channel 的 IO 事件,使得系统资源得到了充分利用,减少了线程开销。
高效的内存操作与内存池设计:ByteBuf 提供了丰富的功能,如动态扩展、复合缓冲区等,能高效地进行内存操作,并使用内存池技...
回答重点因为TCP 协议是面向字节流的,数据在传输过程中没有明确的边界,所以会发生粘包和半包问题。
1)粘包问题:
粘包指的是多个应用层的数据包在传输过程中被合并成一个 TCP 数据包,导致接收方无法区分各个独立的数据包。
2)半包问题:
半包指的是一个应用层的数据包在传输过程中被拆分成多个 TCP 数据包,接收方需要多次读取才能获取完整的数据。
常见解决粘包与半包问题有三个方案:
固定长...
回答重点Netty 提供了丰富的自带解码器为我们解决粘包和拆包的问题,也可以让我们自定义序列化解码器。
Netty 自带的解码器
DelimiterBasedFrameDecoder:分隔符解码器,使用特定分隔符来分割消息。
FixedLengthFrameDecoder:固定长度的解码器,可以按照指定长度对消息进行拆包,如果长度不够的话,可以使用空格进行补全,适用于每个消息长度固定的场景。...
回答重点Netty 作为许多中间件的底层网络通讯框架,内部设计使用了很多的设计模式:
1)策略模式
例如,Netty 提供了多种 EventLoopGroup 实现(如 NioEventLoopGroup、EpollEventLoopGroup),可以根据不同的操作系统和需求选择不同的实现。
2)单例模式
我们在面试鸭设计模式题库中提到池化设计经常就需要用到单例模式,Netty 的 Pool...
回答重点因为原生的 NIO 存在一些问题:
1)原生 NIO 接口较多,能支持更精细化的调用,但是对于通常的使用而言过于复杂。就好下面这张图,对于已经深耕的专业人员来说,可能极好,但对于大部分人员使用来说太复杂了。
所以如果用原生 NIO 开发的话,需要进行二次封装,开发效率不高,且原生 NIO 对开发者要求较高,不好开发。
2)原生的 NIO 存在一些 Bug,最让人熟悉的就是 Sel...