面试的一些问题 Posted on 2023-03-23 22:07:34 2023-03-23 22:07:34 by Author 摘要 面试的常见问题 写一篇关于redis两种持久化方式的博文,讲解通俗易懂 Redis是一种基于内存的键值型数据库,它可以提供高性能和高可用性的数据服务。但是,内存中的数据是易失的,如果服务器发生故障或重启,内存中的数据就会丢失。为了解决这个问题,Redis提供了两种持久化方式:RDB和AOF。 RDB(Redis Database)持久化方式是将Redis内存中的数据定期保存到磁盘上的一个二进制文件中。这个文件可以作为数据备份,也可以用于在其他服务器上恢复数据。RDB持久化方式有以下几个特点: - RDB文件是一个压缩后的二进制文件,占用空间小,传输速度快。 - RDB文件是一个完整的数据快照,恢复数据时只需要加载一次文件即可。 - RDB持久化方式可以配置不同的保存策略,比如每隔多少秒或者每达到多少次写操作时触发保存。 - RDB持久化方式有两种触发方式:手动触发和自动触发。手动触发可以使用save或bgsave命令,其中save命令会阻塞主进程直到保存完成,而bgsave命令会创建一个子进程来执行保存操作。自动触发则根据配置文件中的save参数来决定何时执行bgsave命令。 RDB持久化方式的优点是: - RDB文件可以作为灾难恢复的最后手段,如果AOF文件损坏或者丢失,可以使用RDB文件来恢复数据。 - RDB文件可以用于迁移或复制数据到其他服务器上。 - RDB持久化方式对主进程的影响较小,只有在fork子进程时会有短暂的阻塞。 RDB持久化方式的缺点是: - RDB持久化方式不能保证数据的实时性或者秒级别的一致性。如果在两次保存之间发生故障,那么这段时间内的数据就会丢失。 - RDB持久化方式需要fork子进程来执行保存操作,这会消耗一定的CPU和内存资源,并且可能导致主进程暂停服务。 - RDB文件有多个版本格式,并不兼容老版本的Redis服务。 AOF(Append Only File)持久化方式是将Redis执行过的所有写命令追加到一个日志文件中。这个日志文件可以保证数据不丢失,并且可以重放所有写命令来恢复数据。AOF持久化方式有以下几个特点: - AOF文件是一个纯文本文件,记录了所有写命令及其参数。AOF文件可以被人类阅读和修改。 - AOF文件通过追加写入来保证原子性和耐久性,并且支持多种同步策略来控制何时将缓冲区中的内容刷新到磁盘上。 - AOF持久化方式支持自动重写机制来减少AOF文件大小,并且支持增量备份机制来备份AOF文件。 AOF持久化方式优点是: - AOF持久化方式可以保证数据不丢失,并且支持实时同步或者近实时同步策略。 - AOF重写机制可以有效地减少AOF文件大小,并 数据库的隔离级别是什么?为什么需要它们?有哪些隔离级别?它们各有什么优缺点?本文将尝试用通俗易懂的语言来回答这些问题。 首先,我们要了解什么是事务。事务是一组对数据库进行的操作,要么全部成功,要么全部失败。例如,银行转账就是一个事务,如果A给B转100元,那么A的账户要减少100元,B的账户要增加100元。如果在转账过程中发生了错误,比如网络断开或者电源故障,那么事务就应该回滚,恢复到转账之前的状态,保证数据的一致性。 但是,在实际的数据库系统中,并不是只有一个事务在执行,而是有多个事务同时并发地执行。这就可能导致一些问题,比如脏读、不可重复读、幻读等。为了解释这些问题,我们先假设有两个事务T1和T2,并且T1先于T2开始执行。 - 脏读:指的是一个事务读取了另一个事务未提交的数据。例如,T1给B转了100元,但还没有提交事务;此时T2查询了B的余额,发现多了100元;然后T1因为某种原因回滚了事务;最后T2得到了错误的数据。 - 不可重复读:指的是在同一个事务中,多次读取同一条数据却得到不同的结果。例如,T1第一次查询了B的余额为1000元;然后T2给B转了100元,并提交了事务;接着T1第二次查询了B的余额为1100元;最后T1发现两次查询结果不一致。 - 幻读:指的是在同一个事务中,多次查询同一范围的数据却得到不同数量或内容的结果。例如,T1第一次查询了所有余额大于500元的用户有10个;然后T2给其中一个用户转了500元,并提交了事务;接着T1第二次查询了所有余额大于500元的用户有11个;最后T1发现两次查询结果不相符。 数据库的隔离级别是指在并发访问数据库时,一个事务对数据所做的修改是否能够影响到其他事务的执行,以及其他事务能否看到这些修改。不同的隔离级别会导致不同的并发问题,例如脏读、不可重复读、幻读等。因此,选择合适的隔离级别是保证数据库正确性和性能的重要因素。 一般来说,数据库支持四种隔离级别,分别是: - 读未提交(Read Uncommitted):最低的隔离级别,允许一个事务读取另一个未提交事务的修改。这种情况下,可能出现脏读(Dirty Read),即一个事务读取到了另一个事务回滚之前的数据。 - 读已提交(Read Committed):较低的隔离级别,只允许一个事务读取另一个已提交事务的修改。这种情况下,可以避免脏读,但可能出现不可重复读(Non-Repeatable Read),即一个事务在执行过程中多次读取同一数据,但由于其他事务的修改而导致数据不一致。 - 可重复读(Repeatable Read):较高的隔离级别,保证一个事务在执行过程中多次读取同一数据时,结果是一致的。这种情况下,可以避免脏读和不可重复读,但可能出现幻读(Phantom Read),即一个事务在执行过程中多次查询同一范围的数据时,由于其他事务插入或删除了数据而导致结果集不一致。 - 串行化(Serializable):最高的隔离级别,保证所有事务都是串行执行的,即每个事务都必须等待前一个事务完成后才能开始执行。这种情况下,可以避免所有并发问题,但会牺牲很大的性能。 不同数据库系统对这四种隔离级别有不同的实现方式和优化策略。例如,在 MySQL 中,默认使用可重复读作为隔离级别,并使用多版本并发控制(MVCC)来实现快照隔离(Snapshot Isolation),从而解决幻读问题;而在 SQL Server 中,默认使用读已提交作为隔离级别,并提供快照隔离作为另一种选项。 总之,在选择数据库的隔离级别时,需要根据业务需求和性能考虑进行权衡。如果对数据正确性要求很高,则应该选择较高或最高的隔离级别;如果对性能要求很高,则应该选择较低或最低的隔离级别. MVCC是多版本并发控制的缩写,它是一种在数据库管理系统中实现对数据库的并发访问的方法。MVCC的基本思想是,每个事务操作的数据都有一个版本号,事务开始时会根据隔离级别获取一个全局快照,只能看到快照中的数据。这样就可以避免加锁和阻塞,提高并发性能。 在本文中,我们将具体介绍MySQL中的MVCC机制,包括以下几个方面: - MVCC适用的存储引擎和隔离级别 - MVCC如何生成和维护数据版本 - MVCC如何判断数据可见性 - MVCC的优缺点 ## MVCC适用的存储引擎和隔离级别 MySQL支持多种存储引擎,但不是所有的存储引擎都支持MVCC。目前只有InnoDB和NDB Cluster存储引擎支持MVCC。其他存储引擎如MyISAM、Memory等使用表锁或行锁来实现并发控制。 MySQL支持四种事务隔离级别,分别是: - 读未提交(READ UNCOMMITTED) - 读已提交(READ COMMITTED) - 可重复读(REPEATABLE READ) - 串行化(SERIALIZABLE) 其中,只有可重复读和串行化两种隔离级别使用了MVCC。读未提交和读已提交两种隔离级别没有使用MVCC,而是直接读取最新版本的数据。 ## MVCC如何生成和维护数据版本 在InnoDB存储引擎中,每行记录都有两个隐藏的列:DB_TRX_ID和DB_ROLL_PTR。DB_TRX_ID记录了最后修改该行记录的事务ID;DB_ROLL_PTR指向了回滚段中该行记录上一个版本的位置。通过这两个列,InnoDB可以构建出一条记录的所有历史版本链。 当一个事务对一条记录进行插入、删除或更新操作时,InnoDB会为该记录生成一个新版本,并将当前事务ID赋值给DB_TRX_ID列,并将原来的版本信息保存到回滚段中,并将其位置赋值给DB_ROLL_PTR列。这样就形成了一个新旧版本链表。 当一个事务结束时,如果它是提交状态,则它修改过的所有记录都会保留最新版本,并且删除旧版本;如果它是回滚状态,则它修改过的所有记录都会恢复为旧版本,并且删除新版本。 ## MVCC如何判断数据可见性 当一个事务要读取一条记录时,它需要判断该记录是否对自己可见。这取决于该记录最后修改时所属事务ID与当前事务快照中包含的所有活跃事务ID之间的关系。 如果该记录最后修改时所属事务ID小于当前事务快照中最小活跃事务ID,则说明该记录已经被提交了,并且在当前事务开始之前就已经存在了,因此对当前事务可见。 如果该记录最后修改时所属事务ID等于当前事务自身ID,则说明该记录是当前事务自己修改过的,并且还没有提交或回滚,因此对当前事务可见。 如果该记录最后修改时所属事务ID大于当前事务快照中最大活跃事务ID,则说明该记录是在当前事务开始之后才被 具体讲述一下MyIsam和InnoDB MySQL是一种关系型数据库管理系统,它支持多种存储引擎,不同的存储引擎有不同的特点和适用场景。本文将具体讲述一下MySQL中最常用的两种存储引擎:MyIsam和InnoDB,它们之间的区别和优缺点。 MyIsam存储引擎 MyIsam是MySQL 5.1及之前版本的默认存储引擎,它提供了高速的存储和检索能力,以及全文索引、压缩、空间函数等特性。但是MyIsam不支持事务、外键、行级锁等高级数据库功能,而且在崩溃后无法安全恢复。 MyIsam的数据文件分为三个部分:表定义文件(.frm)、数据文件(.MYD)和索引文件(.MYI)。这样的结构使得MyIsam在跨平台的数据转移中很方便,在备份和恢复时也可以针对单个表进行操作。但是也增加了磁盘空间的占用和碎片化的风险。 MyIsam支持三种不同的存储格式:静态表、动态表和压缩表。静态表是默认的格式,它要求所有字段都有固定的长度,这样可以提高查询效率,但是注意数据末尾不能有空格,否则会被去掉。动态表允许字段有可变长度,这样可以节省空间,但是会降低性能,并且容易产生碎片。压缩表是一种只读的格式,它在创建时对数据进行压缩,可以大大减少磁盘空间占用,适合那些不需要修改操作的表。 MyISAM强调性能优先,在每次查询时都具有原子性,并且执行速度比InnoDB更快。但是它只支持表级锁,并发访问受限。当一个更新语句执行时会锁住整张表,导致其他查询或更新被阻塞。如果插入操作满足并发条件,则可以在表尾插入新数据而不影响其他操作。 MyISAM保存了整个表的行数,在执行select count(*) from table时只需要读取该值即可,非常快速。但是如果包含where条件,则两种存储引擎处理方式相同。 MyISAM支持FULLTEXT类型的全文索引,在进行模糊搜索时非常有用。同时它也支持空间索引(GIS),可以处理地理位置信息。 总结一下MyISAM存储引擎适合以下场景: - 表中主要是读操作而很少写操作 - 表中没有事务处理需求 - 表中需要进行全文搜索或者空间搜索 - 表中数据量较小或者容易修复 InnoDB存储引擎 InnoDB是MySQL 5.1之后版本的默认存储引擎,它提供了事务安全、外键约束、行级锁定等高级数据库功能,并且具有自动崩溃恢复能力。除非有特殊原因需要使用其他存储引擎,否则应该优先考虑InnoDB。 InnoDB将所有数据都保存在一个或多个共享表空间文件中(innodb_data_file_path),而不是按照每个 InnoDB是MySQL和MariaDB的一个存储引擎,它提供了标准的ACID事务特性,以及外键支持(声明式引用完整性)。自从2010年MySQL 5.5.5版本发布后,它取代了MyISAM成为MySQL的默认表类型。InnoDB是Oracle公司在2005年收购了芬兰公司Innobase后的产品。该软件是双重许可的;它在GNU GPL v2或专有软件下分发。 本文将具体讲述一下InnoDB的特点、优势和限制,以及与MyISAM存储引擎的区别。 ## InnoDB的特点 - InnoDB支持SQL和XA事务,可以保证数据的一致性、原子性、隔离性和持久性。 - InnoDB支持表空间,可以将多个表存储在一个文件中,或者将一个表分散到多个文件中。 - InnoDB支持外键,可以在表之间定义参照完整性约束。 - InnoDB支持全文搜索索引,从MySQL 5.6(2013年2月)和MariaDB 10.0开始。 - InnoDB支持空间操作,遵循OpenGIS标准。 - InnoDB支持虚拟列,在MariaDB中。 ## InnoDB的优势 - InnoDB使用行级锁定,而不是MyISAM使用的表级锁定,这意味着并发写入操作不会相互冲突。 - InnoDB使用多版本并发控制(MVCC),可以提高读取性能,并避免脏读、不可重复读和幻读等问题。 - InnoDB使用缓冲池来缓存数据和索引页,减少磁盘I/O开销,并提高查询速度。 - InnoDB使用变更缓冲来缓存插入、更新和删除语句,提高效率。 - InnoDB使用双写缓冲来恢复半写入的页。 - InnoDB使用重做日志来记录事务的修改,并在崩溃恢复时重放这些修改。 - InnoDB使用撤销日志来保存行的旧版本,并在回滚或读取时使用它们。 - InnoDB支持在线DDL,在某些情况下可以对表进行修改而不影响其他操作。 - InnoDB支持页面压缩,比COMPRESSED行格式更复杂。 - InnoDB支持数据擦除,确保删除数据时完全移除。 ## Innodb的限制 尽管InnoDB有很多优点,但也有一些限制: - Innodb不支持全文搜索索引中包含停用词(stopwords)或通配符(wildcards)的查询。 - Innodb不支持哈希索引。 - Innodb不支持压缩表空间中包含BLOB或TEXT列。 - Innodb不支持跨数据库外键。 ## Innodb与MyISAM的区别 Innodb和MyISAM是MySQL最常用的两种存储引擎。它们有以下主要区别: | 特征 | Innodb | MyISAM | | ------------ | ----------------------- | ------ | | 事务 | 支持 | 不支持 | | 外键 | 支持 | 不支持 | | 锁定级别 | 行级 | 表级 | | MVCC | 支持 | 不支持 | | 全文搜索索引 | 支持(从MySQL 5.6开始) | | 死锁是指多个进程因为竞争资源而相互阻塞的现象,导致系统无法正常运行。死锁的产生需要满足以下四个条件: - 互斥条件:每个资源要么已经分配给一个进程,要么就是可用的。 - 请求与保持条件:已经得到了某些资源的进程可以再请求新的资源,而不必释放已经得到的资源。 - 不剥夺条件:已经分配给一个进程的资源不能被其他进程强行夺走,只能由占有该资源的进程主动释放。 - 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已经获得了链中下一个进程所请求的资源。 如果要避免或预防死锁,就必须破坏上述四个条件中的至少一个。常见的解决办法有以下几种: - 银行家算法:该算法模拟银行对贷款者的贷款策略,通过设置安全状态和不安全状态来判断是否分配资源给请求者。如果分配后系统处于安全状态,则可以分配;否则,就不分配。 - 资源有序分配法:该方法规定所有的资源按照某种顺序编号,并且每个进程按照编号递增(或递减)的顺序请求资源,并及时释放不再使用的资源。这样可以避免循环等待条件。 - 资源预分配法:该方法要求每个进程在开始执行之前就申请它所需要的全部资源,并一次性分配给它。如果系统无法满足它所需求的全部资源,则该进程就不执行。这样可以避免请求与保持条件。 - 死锁检测与恢复法:该方法允许系统发生死锁,但是要求系统定期检测是否存在死锁,并在发现死锁后采取相应措施来恢复系统正常运行。例如,撤销或挂起一些死锁进程,回收并重新分配它们占用的资源。
{{ item.content }}
{{ child.content }}