Day06
1. 数据库怎么分类,描述一下你对这些数据库的理解?
数据库按数据模型可以分为关系型和非关系型。关系型数据库像 MySQL、Oracle,是通过表格结构组织数据的,使用 SQL 来操作,适用于需要保证数据一致性和完成性的场景;而非关系型数据库,比如 MongoDB、Redis,不依赖传统的表结构,存储形式更灵活,适合处理非结构化数据或高并发访问。
数据库是用于存储、管理和检索数据的系统,关系型数据库使用结构化查询语言(SQL)来管理数据,适用于需要保证数据一致性和完整性的场景;NoSQL 数据库则更加灵活,适用于需要处理大量非结构化数据或需要高可伸缩性的场景。
2. 什么情况使用MySQL,什么情况使用Redis?
一般来说,MySQL 用于持久化存储结构化数据,比如用户信息、订单记录、商品库存这些核心业务数据,数据需要严格的完整性、一致性保障,支持复杂查询和事务操作。而 Redis 更适合做缓存或处理高并发、快速响应的场景,比如保存登录验证码、热点数据、排行榜、会话信息等。它是基于内存的,读取速度快,支持多种数据结构,常和 MySQL 搭配使用,减轻数据库压力、提升系统性能。
3. Redis有什么持久化策略?
Redis 的读写操作都是在内存中完成的,因此性能非常高。一旦 Redis 重启,内存中的数据就会丢失。为了避免这种情况,Redis 提供了数据持久化机制,通过将数据写入磁盘,在重启后可以恢复原有数据。
- AOF 日志模式:每当执行一条写操作命令,就将该命令以追加的方式写入到 AOF 文件中。优点是数据丢失最少,恢复精度高,但缺点是文件体积大,恢复速度相对慢。
- RDB 快照模式:在指定的时间间隔内,将某一时刻的内存数据生成快照,以二进制文件形式写入磁盘。优点是恢复快、文件体积小,适合做定期备份;但可能会丢失最近一次快照之后的数据。
- 混合持久化方式(从Redis4.0开始支持):结合了 AOF 和 RDB 的优点。在重启恢复时,先通过 RDB 快速恢复,再用 AOF 补充增量数据,既提升了恢复速度,又保证了数据完整性。
4. MySQL有哪两种引擎,说一下它们的区别?
MySQL 中常用的存储引擎主要有 InnoDB 和 MyISAM,它们在事务支持、索引结构、锁粒度和统计效率上有明显区别。
- 事务支持:InnoDB 支持事务,这也是 MySQL 默认存储引擎从 MyISAM 切换到 InnoDB 的重要原因之一;而 MyISAM 不支持事务。
- 索引结构:InnoDB 使用聚簇索引,数据存储在主键索引的叶子节点上,因此必须有主键。主键查询效率很高,但辅助索引查询时需要先查辅助索引再通过主键定位数据,因此主键不宜过大,否则会影响其他索引大小。相比之下,MyISAM 采用非聚簇索引,数据和索引分离,索引存储的是数据文件的指针,主键和辅助索引相互独立。
- 锁粒度:InnoDB 支持行级锁,能够支持高并发操作;而 MyISAM 只支持表级锁,一次写操作会锁住整张表,导致其他查询和更新被阻塞,降低并发性能。
- 执行
SELECT COUNT(*)
这类统计时,MyISAM 速度更快,因为它维护了一个表的行数变量;InnoDB 不保存行数信息,需要全表扫描,效率较低。综上,InnoDB 更适合对数据一致性和事务有较高要求、并发访问频繁的场景,而 MyISAM 则适合读操作多、数据一致性要求不高的简单应用场景。
5. MySQL两个线程的update语句同时处理一条数据,会不会有阻塞?
会发生阻塞。因为 InnoDB 使用的是行级锁,第一个线程会获取这条记录的锁,第二个线程就必须等待第一个线程提交或回滚后,才能获得锁继续执行。所以虽然不会出现数据冲突或脏写,但确实会有阻塞现象。
6. 滥用事务,或者一个事务里有特别多sql的弊端?
- 锁定资源时间长:事务未提交前,持有的锁(行锁、间隙锁等)都无法释放,锁定的数据越多,越容易引发死锁或锁等待超时,影响并发。
- 回滚代价大:InnoDB 为了支持回滚和 MVCC,会记录每条变更的 undo log,SQL 越多,undo 数据越多,占用更多存储空间,一旦事务失败回滚,时间和代价都很高。
- 执行时间长,影响主从同步:MySQL 主库在事务提交之后才会写入 binlog 并同步到从库。如果一个事务执行10分钟,从库就会延迟至少10分钟,对读写分离架构影响很大。
- 资源释放延迟:事务执行期间占用连接、锁、内存等系统资源,直到提交才释放,长事务容易造成资源积压,甚至拖慢整个数据库的响应速度。
7. 两条update语句处理一张表的不同的主键范围的记录,一个 id < 10,一个 id > 15,会不会遇到阻塞?底层是为什么?
在 InnoDB 存储引擎中,如果两条 UPDATE 语句操作的是主键范围不重叠的数据,比如一条更新 id < 10,另一条更新 id > 15,是不会发生阻塞的。因为 InnoDB 使用的是基于索引的行级锁,锁住的只是语句命中范围的记录行。第一条语句锁住的是(-∞, 10) 区间,第二条语句锁住的是 (15, +∞),锁定范围完全不同,不会形成冲突,自然不会阻塞。当然,这种前提是语句能够正确使用索引,如果没走索引或者存在间隙锁、副索引等情况,也有可能扩大锁范围导致阻塞。
8. 如果2个范围不是主键或索引?还会阻塞吗?
如果两个 update 语句的条件字段不是主键或索引列,那么 InnoDB 无法通过索引精确定位要更新的行,会退化成全表扫描,并对满足条件的每一行加锁。即使两个语句的条件看起来互不重叠,比如一个更新 name = ‘Alice’,另一个更新 name = ‘Bob’,由于没有索引,可能在扫描过程钟锁住相同的行,从而发生阻塞。因此,为了避免锁冲突,更新操作应尽量使用主键或带索引的字段作为查询条件。
-- 线程1
UPDATE user SET age = age + 1 WHERE name = 'Alice';
-- 线程2
UPDATE user SET age = age + 1 WHERE name = 'Bob';
9. 除了表锁,行锁这些,还有别的形式的锁吗?
还有全局锁,可以通过执行 FLUSH TABLES WITH READ LOCK 来实现,它会让整个数据库处于只读状态,阻塞其他线程的增删改操作或表结构变更,常用于全库逻辑备份,确保备份期间数据一致性。此外,InnoDB 还实现了间隙锁、Next-Key Lock、意向锁、自增锁和元数据锁等多种锁机制,用于控制并发和防止幻读,比如间隙锁就会锁住两个索引值之间的范围,防止其他事务插入新记录。这些锁共同构成了 MySQL 在事务隔离和并发控制方面的完整机制。