每日一问记录

【每日一问:20260320】问:MySQL选择InnoDB作为引擎,它有什么优势?

答案:

MySQL 默认的存储引擎是 InnoDB,这是因为 InnoDB 在性能、事务支持和容错能力等方面具有较好的特性,适合大多数应用场景。下面是一些原因:
●支持事务:InnoDB 是一个支持事务的存储引擎。事务是一组数据库操作的原子性执行,可以保证操作的一致性和完整性。
●并发控制:InnoDB 支持行级锁定, 在高并发环境下可以最大程度地减少锁冲突,提高并发性能。相比之下,MySQL 的另一个存储引擎 MyISAM 只支持表级锁定,并发性能较低。
●外键约束:InnoDB 支持外键约束,可以保证数据的完整性。外键用于建立表与表之间的连接,通过外键约束可以实现数据之间的关联和参照完整性。
●崩溃恢复:InnoDB 具有自动崩溃恢复的能力。即使在发生意外故障或系统崩溃时,InnoDB 引擎也能够自动进行崩溃恢复,保障数据的一致性。
●支持热备份:InnoDB 支持在线热备份,可以在不停止数据库服务的情况下进行备份操作。这对于需要实时运行且对数据可用性要求高的应用程序非常重要。
●需要注意的是,虽然 InnoDB 是 MySQL 默认的存储引擎,但在某些场景下,可以根据实际需求选择其他存储引擎,如 MyISAM、Memory 等。不同的存储引擎适用于不同的应用场景和需求。

 

 

【每日一问:20260322】问:小明公司的数据库用的MySQL 引擎是Innodb。小明创建了一张表,忘记给这张表添加主键,请问这边表有没有聚簇索引?如果有的话聚簇索引是什么样的?
聚簇索引创建的原则:
●主键存在:如果表中定义了主键,主键即为聚簇索引。
●没有主键时:如果没有定义主键,InnoDB 会选择第一个唯一且非空的索引作为聚簇索引。
●既没有主键也没有唯一索引时:如果既没有主键也没有合适的唯一索引,InnoDB 会自动创建一个隐藏的6字节的行 ID (ROWID) 用作聚簇索引。这个是内部管理的,对用户不可见。

官网参考:https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html
相关源码: https://github.com/mysql/mysql-server/blob/8.0/storage/innobase/handler/ha_innodb.cc  @所有人

 

【每日一问:20260201】SQL场景实战问题
https://docs.qq.com/doc/DVUZGZlhUQklMbURB

问题: 请问事务1 的第二次查询结果是什么?为什么?

答案: 4条数据。 事务2新增数据提交之后,事务1更新的当前读是可以操作成功,根据可见性规则:当前事务更新的数据对当前事务是可见的。所以事务1的第2个查询是可以看到id=20这条数据,再加上快照里面的3条数据,一共就是4条数据。
 @所有人

 

【每日一问:20260325】  想清理一下这张订单表(mysql数据库)历史数据,请问这三种

truncate、delete、drop方式哪种更好些?有什么区别吗?
truncate、delete、drop方式 在面试中问得很多,也是工作经常使用的SQL语句,他们的特性如下:
一、DELETE语句
特点:
1. 可以根据条件删除部分数据
2. 支持事务,可以回滚
3. 删除数据时会记录日志
4. 删除速度较慢
5. 不会释放表空间
6. 会一行一行地删除
适用场景:
1. 需要删除部分数据
2. 需要保留删除记录
3. 需要事务支持
4. 表数据量不大
二、TRUNCATE语句
特点:
1. 删除速度快
2. 会释放表空间
3. 表的自增ID重置为1
4. 不能根据条件删除
5. 不支持事务回滚
6. 不记录日志
适用场景:
1. 需要删除全表数据
2. 需要重置自增ID
3. 对删除速度有要求
4. 不需要保留删除记录
三、DROP语句
特点:
1. 执行速度最快
2. 完全释放表空间
3. 删除表结构和索引
4. 删除整个表定义
5. 不支持事务回滚
6. 需要重建表结构
适用场景:
1. 需要删除整个表
2. 表结构需要重建
3. 不需要保留任何信息
【实用建议】
1. 如果只是想清理部分历史数据:
使用DELETE,可以指定条件
示例:DELETE FROM orders WHERE create_time < '2024-01-01';
2. 如果想清空整个表但保留表结构:
使用TRUNCATE,速度快且释放空间
示例:TRUNCATE TABLE orders;
3. 如果要完全废弃这个表:
使用DROP,删除整个表
示例:DROP TABLE orders;
【安全建议】
1. 执行删除操作前先备份数据
示例:CREATE TABLE orders_backup AS SELECT * FROM orders;
2. 对于大表删除,建议分批执行
示例:DELETE FROM orders WHERE create_time < '2024-01-01' LIMIT 10000;
3. 在业务低峰期执行删除操作
4. 删除前先确认是否有外键关联
【性能对比】
1. 执行速度:DROP > TRUNCATE > DELETE
2. 空间释放:DROP = TRUNCATE > DELETE
3. 安全性:DELETE > TRUNCATE > DROP
4. 灵活性:DELETE > TRUNCATE > DROP
【总结】
选择合适的删除方式主要取决于:
1. 是否需要保留表结构
2. 是否需要部分删除
3. 是否需要事务支持
4. 是否需要删除日志
5. 表的大小和业务影响
选择合适的删除方式可以大大提高效率,同时避免不必要的风险。在实际操作中,建议先在测试环境验证,确保操作安全无误后再在生产环境执行。 @所有人

 

 

【每日一问:20260327】订单表3年积累了5000万条数据,需要删除1年前的历史订单(约3000万条),要求不影响线上业务,请说下你的方案?
先不关注订单在业务上是否允许,生产上也有类似场景,比如一些日志表。重点关注方案设计。
先分析这个场景:
●数据量大(3000万条)
●不能影响线上业务(不能长时间锁表)
●需要保证数据安全
一般有以下几个方案,大家可以对比下:
方案1:直接DELETE(这个是不推荐的),主要的问题会有:
●会产生巨大的锁,阻塞其他业务操作
●回滚日志(undo log)巨大,可能导致磁盘空间不足
●主从复制延迟严重
●执行时间可能数小时,期间数据库压力极大
方案2:分批删除,可以按照主键分批删除,通过批处理或者存储过程实现。这种方案的特点: 每次只锁少量数据
可以在业务低峰期分多批次多天执行,每个批次大小:5000-10000条(这个要根据自己项目的服务器性能调整)
出问题可以随时停止
对主从复制影响小

方案3:先做归档后删除,这种方案数据可追溯,万一需要还能找回更安全,不用担心误删。但是需要需要额外存储空间,耗时也可能更长。

方案4:按时间分区表。这个需要提前做好设计,如果经常需要清理历史数据,建议改造成分区表。我们可以按照分区删除历史数据,性能快,不产生锁,也不影响其他分区查询。

所以推荐相对安全和完善的方案: 提前做好数据备份+分批删除+业务低峰期执行+做好数据监控以及验证,有条件改造成分区表最好,另外记得做完这类大范围删除操作,要OPTIMIZE TABLE 回收空间,减少内存碎片。

 

 

 

 

【每日一问:20260330】面试官问他mysql查询的时候使用where 1=1会不会影响性能?你的答案是什么呢?说说你的看法。

很多小伙伴会在where后面跟上1=1的保证语,经常看网上的八股文说1=1会影响性能, 建议用Mybatis的<where>标签。两种方案,该如何选择?
●如果 MySQL Server版本小于 5.7,用了 MyBatis的话,建议使用<where> 标签。

●如果 MySQL版本大于等于 5.7,两个随便选;因为在MySQL5.7后,有一个所谓的(常量折叠优化)可以在编译期消除重言式表达式。什么是重言式表达式,就是任何时候永远都为true的结果, 就会被优化器识别并优化掉,好奇的话你可以通过show warnings;查看,就会发现1=1没有了。并且我也在一张100多万的表里面把1=1 和<where>标签分别做了100次查询, 耗时时间相差无几。 所以5.7后两种方式随便选。
当然现在 MySQL Server版本基本都是 5.7以上了,不是的话那赶紧升级吧。
 @所有人

 

 

【每日一问:20260402】学员的一个面试问题:一张表有500万数据,100多个字段,请问如何快速把数据查出来?
在处理大数据量和多字段的表时,优化查询性能是至关重要的。以下是一些策略,可以帮助你快速查询数据:

1. 选择必要的字段:
● 只选择你需要的字段,而不是使用`SELECT *`。这可以减少数据传输量和内存使用。

2. 使用索引:
● 确保查询条件中的列(如`WHERE`子句中的列)上有适当的索引。
● 使用覆盖索引(即索引包含所有查询的字段)可以避免回表查询。

3. 分页查询:
● 如果需要处理大量数据,考虑使用分页查询(如`LIMIT`和`OFFSET`)来分批获取数据。
● 注意:对于大偏移量的分页,`OFFSET`可能会导致性能问题,可以考虑使用“延续键”分页。

4. 优化查询条件:
● 使用高效的查询条件,避免在`WHERE`子句中使用函数或计算。
● 尽量使用等值查询而不是范围查询。

5. 数据库配置优化:
● 调整数据库配置参数,如`innodb_buffer_pool_size`,以便更好地利用内存。
● 确保数据库服务器有足够的内存和CPU资源。

6. 分区表:
● 对于非常大的表,可以考虑使用表分区,将数据按某个字段(如日期)分割成多个物理部分。

7. 缓存机制:
● 使用缓存机制(如Redis)来存储常用查询的结果,减少数据库的负载。

8. 分析执行计划:
● 使用`EXPLAIN`命令分析查询的执行计划,找出潜在的性能瓶颈。

9. 批量处理:
● 如果需要对大量数据进行批量处理,考虑使用批量操作而不是逐行处理。

通过结合这些策略,可以显著提高查询性能,尤其是在处理大数据量和多字段的复杂查询时。
 @所有人

 

 

【每日一问:20260403】假如今天不小心把数据库删了,领导让你把数据恢复出来,请问应该怎么做?
如果因为某些原因误删误删数据或者数据库,需要面对如何快速恢复问题。关于这个问题的解决总结如下:
一、恢复数据的方法:
(1). 误删数据表或数据库:
使用 `DROP TABLE`、`TRUNCATE TABLE` 或 `DROP DATABASE` 误删数据时,binlog 记录的是 statement 格式,可能不能通过 binlog 恢复。
恢复方法:依赖全量备份和增量日志。这个需要定期的全量备份和实时备份的 binlog。
(2) 误删数据行:
使用 `DELETE` 语句误删数据行,可以通过 Flashback或者美团闪回工具Myflash进行恢复数据。
美团Myflash详细介绍:

二、提升数据恢复效率:
MySQL 5.6 之后引入了延迟复制的备库,防止错误操作快速蔓延到从库,导致主从数据都被删除。具体方法: 通过命令 CHANGE MASTER TO MASTER_DELAY = N ,可以指定这个备库持续保持跟主库有 N 秒的延迟。这样可以缩短了整个数据恢复需要的时间,提高恢复数据的效率。

三、预防数据误删的方法
(1)) 规范数据库脚本审计以及脚本发布上线的流程,出现问题能够及时撤销和回退
(2) 数据库账号权限的管理,特别是Drop/Truncate权限必须严格管理
(3) 数据库配置层面也需要做好约束规范,sql_safe_updates 参数设置为 on。 delete 或者 update 语句中没有 where 条件,或者 where 条件里面没有包含索引字段的话,这条语句的执行就会报错
(4)为了防止集群集体删除的极端情况,我们做数据库备份的时候有条件尽量选择跨机房或者跨城市都可以,提高数据库可用性,降低数据丢失的损失。
 @所有人

 

【每日一问:20260405】 开放性讨论题:你知道MySQL常用的查询优化分析方法有哪些?说下你的看法和理解
(1)EXPLAIN分析执行计划,如果要看得更加详细清晰可以使用EXPLAIN FORMAT=JSON
或者EXPLAIN FORMAT=TREE,EXPLAIN ANALYZE,注意后面两个是mysql 8之后的新增功能。
(2) Optimizer Trace
MySQL Optimizer Trace功能会跟踪MySQL优化器对查询优化过程的关键信息,比如扫描的行数,成本,以及为什么选择哪个执行计划,都是有明确的指示。
使用方法:

-- 开启optimizer trace
set optimizer_trace='enabled=on';
-- query;
执行你的SQL;
-- 查看optimizer trace记录
select * from information_schema.optimizer_trace;
(3)Profiling。最新的 MySQL 版本是默认开启 Show Profile 功能的。Show Profiles 只显示最近发给服务器的 SQL 语句,默认情况下是记录最近已执行的 15 条记录,我们可以重新设置 profiling_history_size 增大该存储记录,最大值为 100。获取到 Query_ID 之后,我们再通过 Show Profile for Query ID 语句,就能够查看到对应 Query_ID 的 SQL 语句在执行过程中线程的每个状态所消耗的时间。

除了以上工具以外,我们还需要去分析mysql慢查询日志,还有服务器状态指标 比如CPU ,连接数,有没有长事务,page指标等等。我们需要综合各个技术手段和查询方法找到问题的SQL。
 @所有人

 

posted @ 2026-03-21 13:25  OMGq  阅读(2)  评论(0)    收藏  举报