MySQL 基础知识
date
Dec 31, 2022
slug
mysql-knowledge-fundamentals
status
Published
tags
MySQL
Interview
summary
一些基本问题和答案
type
Post
Created Time
Oct 28, 2023 01:45 PM
Updated Time
Oct 28, 2023 01:45 PM
AI summary
MySQL基础知识包括事务的ACID特性(原子性、一致性、隔离性、持久性),InnoDB中事务更新操作的执行过程,MVCC的概念和MySQL的隔离级别,以及MySQL主从同步的过程和全同步复制与半同步复制的区别。
Status
MySQL 是什么?
MySQL 是一种流行的关系型数据库管理系统,是一个开源软件,广泛应用于各种类型的应用程序中。MySQL 支持多种操作系统,包括 Windows、Linux 和 macOS 等,而且它的性能、可靠性和可扩展性都非常优秀,因此成为了最流行的关系型数据库之一。
什么是索引?
在关系型数据库中,索引是一种单独的、物理的,对数据库表中的一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合,相当于图书的目录,可以根据图书的目录快速找到所需的内容。
索引是能够实现快速定位数据的一种存储结构,其设计思想是用空间换时间。
索引的分类
- 按照数据结构分类:B+tree 索引、Hash 索引、Full-text 索引。
- 按照物理存储分类:聚簇索引(主键索引)、非聚簇索引(二级索引、辅助索引)。
- 按照字段特性分类:主键索引、唯一索引、普通索引、前缀索引。
- 按照字段个数分类:单列索引、联合索引。
索引的优缺点
- 优点:
- 提高查询速度:可以大大减少检索数据的范围,减少磁盘的 IO,快速定位到所需的数据行,从而避免了全表扫描,提高数据查询的效率;
- 保证数据的唯一性:通过创建唯一索引,可以强制数据的唯一性。
- 优化排序和分组:在检索中使用分组和排序时,索引可以按照特定的顺序来检索数据,避免对整个表进行排序和分组。
- 改善并发性能:索引可以改善并发性能,因为它可以减少数据库的锁定时间,从而提高并发访问的效率。
- 加速外连接的效率:在外键上创建索引,可以加速表连接的查询效率。
- 缺点:
- 占用存储空间:索引需要占用存储空间,因为它们需要存储指向数据行的指针和其他索引数据。
- 增加写操作的时间:索引会增加写操作的时间,因为每次插入、更新或删除数据时,都需要更新索引数据。
- 增加系统负载:索引会增加系统的负载,因为它需要占用 CPU 和内存资源,尤其是在查询大数据量的情况下。
- 不适用于小表:对于小表来说,索引可能会降低查询性能,因为它需要额外的I/O操作和CPU时间来检索数据。
- 可能导致查询优化器选择错误的查询计划:在某些情况下,索引可能会导致查询优化器选择错误的查询计划,从而降低查询性能。
使用索引一定能提升效率吗?
不一定。虽然使用索引可以提高查询效率,但是必须根据具体情况来判断是否适合使用索引。以下是一些可能会影响索引效率的因素:
- 数据表的大小:如果数据表很小,使用索引可能不会提高查询效率,反而会增加额外的开销。
- 查询条件的复杂度:如果查询条件很复杂,使用索引可能不会提高查询效率,因为索引只能加速单个查询条件的匹配,而无法加速多个条件的匹配。
- 数据表的更新频率:如果数据表的更新频率很高,使用索引可能会降低写入效率,因为每次更新都需要更新索引。
- 索引的选择性:如果索引的选择性很低,即索引所包含的值有很多重复,那么使用索引可能不会提高查询效率,因为查询时需要扫描很多重复值。
- 数据类型的选择:如果使用了不适合索引的数据类型,如 BLOB 或 TEXT 类型,那么使用索引可能会降低查询效率。
聚簇索引和非聚簇索引的区别是什么?
- 聚簇索引(InnoDB)将数据存储在索引树的叶子节点上,因此,找到索引的同时就可以获取到数据,数据的物理存放顺序和索引的顺序是一致的,即如果索引是相邻的,那么数据也是相邻的。
- 非聚簇索引的叶子节点是不存放数据的,只存放数据行的地址(或主键 ID),也就是说,在查询数据时,需要两次操作,首先查询索引树,获取数据行的地址,再通过数据行的地址,查询数据。
在 MySQL 中 ,InnoDB 的主键是聚簇索引,而辅助索引的叶子节点存储的是对应的主键的值,MyISM 的主键和辅助索引都是非聚簇索引,表数据存储在独立的地址空间内,叶子节点指向数据行的地址。如果涉及大数据量的排序、全表扫描或 Count 之类的操作,MyISM 因为索引所占的空间较小,速度会相对较快一些。
聚簇索引的优缺点是什么?
优点:
- 对于非覆盖索引的查询,不需要进行二次查询,效率较高。
- 由于数据是顺序存放的,范围查询的效率较高。
缺点:
- 维护成本较高:在进行插入和更新操作时,需要同时维护索引,此时,可能造成分页或移动行数据。
- 当使用 UUID 作为主键时,可能造成数据稀疏,查询效率比全表扫描更慢。
- 主键索引的数据类型较大时,叶子节点需要占用很多的物理空间存储对应的值。
B 树和 B+ 树的区别是什么?
B 树(B-Tree)是一种自平衡的搜索树数据结构,它被广泛应用于数据库和文件系统中,以支持高效地插入、删除、查找和范围查询等操作。它的特点是可以存储大量的数据,并且能够在磁盘上高效地进行访问和操作。B 树的结构比较复杂,包含了多个节点。每个节点可以存储多个键值对,这些键值对按照键的大小进行排序。B 树的每个节点都有一个指向子节点的指针,这些子节点也是 B 树。由于 B 树的每个节点可以存储多个键值对,因此它可以存储更多的数据,而且在访问数据时,可以减少磁盘 I/O 操作的次数,提高了性能。B 树的平衡性是指树的高度不会太高,因此在查找数据时,需要的磁盘 I/O 操作次数也不会太多。为了保持平衡性,B 树在插入和删除元素时会自动调整节点的结构。这种自平衡的特性保证了 B 树的高效性和可靠性。
B+ 树相当于是 B 树的升级版。经典 B+ 树的非叶子节点只存储关键字,而不存储数据指针。所有的数据都存储在叶子节点中,叶子节点之间通过指针连接起来形成一个有序链表,叶子节点的顺序即为关键字的顺序。这种设计使得 B+ 树的查询效率更高,因为它可以减少非叶子节点的磁盘 I/O 操作次数。MySQL InnoDB 中的 B+ 树基于使用场景,和经典 B+ 树有所不同。
- 聚集索引:在 MySQL InnoDB 中,每个表都必须有一个主键,这个主键会被用作聚集索引,也就是数据在磁盘上存储的顺序。因此,InnoDB 的 B+ 树中的叶子节点包含的是完整的数据行,而不仅仅是数据指针。这种设计可以提高查询效率,因为它可以减少磁盘 I/O 操作的次数。
- 辅助索引:在 MySQL InnoDB 中,除了聚集索引外,还可以创建多个辅助索引。辅助索引的叶子节点不包含完整的数据行,而是包含指向聚集索引中对应数据行的指针。这种设计使得辅助索引的维护更加高效,因为它只需要维护指针而不需要维护完整的数据行。
- 自适应哈希索引:InnoDB 的 B+ 树还支持自适应哈希索引。自适应哈希索引是一种特殊的索引,它可以在 B+ 树的基础上自动创建和删除,并且只在需要的时候才会使用。自适应哈希索引可以提高一些特定查询的性能,例如等值查询和部分匹配查询等。
- B+ 树的分裂:在经典B+树中,为了保持平衡性,当一个节点满了之后会将其分裂成两个节点,但是这种操作可能会导致频繁的节点分裂和合并,影响性能。在 InnoDB 的 B+ 树中,当一个节点满了之后,会先尝试从相邻节点借用一些空间,如果无法借用则再进行分裂。这种设计可以减少节点的分裂和合并操作,提高性能。
InnoDB 中的 page 是什么?
在 InnoDB 存储引擎中,
page
(页面)是一个基本的存储单位。InnoDB 数据库引擎将数据和索引存储在固定大小(通常为 16KB)的连续内存块中,称为页面。页面是 InnoDB 存储管理的核心组成部分,用于组织和存储数据记录。InnoDB 的所有数据都被组织成一个由连续的 page 组成的逻辑空间。这个逻辑空间被称为表空间,它包含了所有的表、索引和其他数据结构。每个表和索引都被存储在一个或多个 page 中,这些 page 可以分布在不同的磁盘文件和文件系统中。InnoDB 中的页面可以分为以下几类:
- 数据页:存储表中的实际数据记录。数据记录按主键顺序组织在 B+ 树的叶子节点上。
- 索引页:存储索引记录,帮助加速数据查询。索引记录也组织在 B+ 树结构中。
- undo 页:存储 undo 日志记录,用于在事务回滚时恢复之前的数据状态。
- 系统页:存储 InnoDB 系统相关信息,如表空间头部信息、数据文件描述符等。
- 事务日志页:存储 redo 日志记录,用于事务恢复和崩溃恢复。
每个 page 由以下几个部分组成:
- File Header:文件头,描述页信息。
- Page Header(页头):存储了一些元数据信息,如 page 的类型、页码、数据存储状态等。
- Infimum + Supremum(最小和最大记录):这是两个虚拟的行记录。
- User Records(用户记录):存储行记录内容。
- Free Space(空闲空间):页中还没有被使用的空间。
- Page Directory(页目录):存储用户记录的相对位置。
- File Trailer(文件尾):存储了校验页是否完整的信息和其他一些元数据信息。
页面的组织方式有助于提高数据检索性能,同时通过将相关数据记录存储在相邻的页面中,降低了磁盘 I/O 开销。同时,InnoDB 使用了一些高级的数据结构和算法来管理 page 的分配和释放,以提高存储效率和性能。例如,InnoDB 使用了多版本并发控制(MVCC)来支持高并发的读写操作,并且可以动态地调整 page的大小,以适应不同的应用场景。在InnoDB中,page 的管理和操作是非常重要的,它直接影响到InnoDB 的性能和可靠性。因此,在设计和优化 InnoDB 数据库时,需要深入了解 page 的结构和管理方式。
假设每一行数据的大小为 1 kb,高度为三的 B+ 树可以存多少条数据?
- 每一页的大小为 16KB,每一条数据为 1KB,一页就可以存 16 条数据;
- 自增主键为 int 类型,占 4 个字节,一个指针在 InnoDB 中占 6 个字节,每一页最多有 16KB/10B = 1638 对数据。
- 高度为 3 的 B+ 树能够存储的数据就是:1638*1638*16=42928704 条数据。
MySQL 中的数据过多时,如何进行优化,提高查询效率?
- 数据库分区:将一个大表分成多个小表,每个小表称为分区,每个分区可以分别存储在不同的物理位置上。这样可以提高查询效率,因为只需在特定的分区中搜索数据,而不必搜索整个表。此外,通过分区还可以更有效地使用硬件资源,例如可以将经常查询的数据分区存储在更快的存储介质上。
- 索引优化:为经常查询的列创建索引,以便数据库可以更快地查找数据。但是,过多的索引可能会降低写入性能,因此需要权衡。
- 缓存优化:使用缓存来减少对数据库的访问次数,可以提高查询性能。可以使用缓存机制,例如Redis等。
- 查询优化:通过优化查询语句来提高性能,例如使用JOIN语句代替多个单独的查询,或者使用子查询来减少数据检索的次数。此外,尽可能避免使用通配符和LIKE语句,因为它们会降低查询性能。
- 硬件升级:如果数据库服务器的硬件性能不足,那么升级硬件,例如增加更多的内存、更快的硬盘或更快的 CPU,可以提高查询性能。
- 分库分表:最后,如果上面的方法都没有办法解决问题,可以将一个大型数据库拆分成多个小的数据库或表,以提高数据库的性能和可伸缩性。分库分表是最后的解决方案,也是无奈之举,因为分库分表后,同时需要解决很多问题,如事务的问题、全局唯一 ID 的处理、全局排序的处理等。
什么是最左匹配原则?
最左匹配原则是指在使用多列索引时,索引会先使用最左边的列进行匹配,然后再依次向右匹配其他列,直到匹配成功或者无法匹配为止。此时,如果进行
explain
时,会发现 Extra
的值为 using index condition
。当查询时,如果遵守最左匹配原则,就可以充分利用索引的优势。如果不遵守最左匹配原则,那么查询就会从中间或者右边的列开始匹配,这样就无法利用索引的优势了,会导致查询速度变慢。
例如,假设有一个包含三列的联合索引 (A, B, C),其中 A, B, C 均为整数类型。如果查询条件是
select * from table where A=1 AND C=2
,因为查询条件包含了索引的第一列 A,符合最左匹配原则,因此可以充分利用索引的优势,提高查询效率。如果查询条件是 select * from table where B=1 AND C=2
,因为查询条件不包含索引的第一列 A,不符合最左匹配原则,因此,这个查询无法使用A、B、C 的联合索引。当然,还有一种情况,比如查询条件为 select * from table where A > 5
,SQL 优化策略就会根据实际情况,检查表中 A 列的索引,找到满足条件的索引记录,并根据索引记录中的指针找到相应的数据行,但如果表中 A 列上通过索引的选择性很低(即不同值的数量很少),那么数据库可能会选择全表扫描而不是利用索引进行查询。什么是覆盖索引?
覆盖索引(Covering Index)是一种优化数据库查询性能的技术,它可以提高查询的效率,减少数据库的 I/O 操作,从而提高数据库的整体性能。
在数据库中,覆盖索引是一种包含了所有需要查询的字段的索引。当查询语句需要返回的数据都包含在覆盖索引中时,数据库引擎可以直接从索引中获取所有需要的数据,而无需再去查询数据表,从而避免了额外的磁盘 I/O 操作,提高了查询的速度。
例如,在一个包含了 id、name、age 和 address 四个字段的数据表中,如果我们需要查询 id 和 name 两个字段的数据,如果我们为 id 和 name 两个字段创建一个联合索引,在查询时只需要从索引中获取需要的数据,而不必再去查询数据表,就会走覆盖索引。这样可以大大提高查询的性能。此时,如果进行
explain
时,会发现 Extra
的值为 using index
。哪些场景下会导致索引失效?
- 对索引列进行函数操作:如果在查询语句中对索引列进行函数操作,如使用函数对索引列进行计算、字符串操作或日期操作等,就会导致索引失效。
- 使用 LIKE 操作符进行模糊查询:如果在查询语句中使用 LIKE 操作符进行模糊查询,如使用 % 或 _ 等通配符,MySQL 无法使用索引进行匹配,因此索引失效。
- 对索引列进行类型转换:如果在查询过程中对字段进行类型转换,则有可能导致索引失效,比如将字符串类型转换为数字类型,MySQL 在执行的过程中,则会因为代价较大,不走索引。
- 使用 OR 连接多个条件:如果在查询语句中使用 OR 连接多个条件,MySQL 无法使用索引进行优化,索引失效。
- 表太小:对于非常小的表,使用索引可能比全表扫描更慢,因此 MySQL 可能会选择不使用索引。
- 数据分布不均匀:如果索引列的数据分布不均匀,即某些值的出现频率比其他值高得多,MySQL 可能会选择不使用索引。
- 使用 NOT 操作符:如果在查询语句中使用 NOT 操作符,MySQL 无法使用索引进行优化,索引失效。
- 使用 ORDER BY 子句:如果在非覆盖索引查询语句中使用 ORDER BY 子句,MySQL 可能会选择不使用索引,而使用临时表排序。
MySQL 有哪些存储引擎?它们之间的区别是什么?
MySQL 提供多种不同的存储引擎,每种存储引擎都有其独特的优势和适用场景。以下是 MySQL 常见的存储引擎和它们之间的区别:
- InnoDB: 这可能是 MySQL 最常用的存储引擎。InnoDB 提供了事务支持,行级锁定,以及外键约束,这使得它在需要高并发、安全性和完整性的应用中成为理想的选择。
- MyISAM: MyISAM 是 MySQL 的默认存储引擎,直到 5.5 版本被 InnoDB 替换。MyISAM 提供了全文索引,压缩,空间函数(GIS),等特性。但是,MyISAM 不支持事务和行级锁定,而且在崩溃时可能需要更多的恢复时间。
- Memory: Memory 存储引擎将数据存储在内存中,这使得数据访问速度非常快。然而,存储在 Memory 引擎中的数据在服务器关闭或崩溃时会丢失,因此它通常用于存储临时数据。
- CSV: CSV 存储引擎将数据存储在以逗号分隔的文件中。这使得数据可以通过标准的文件系统工具进行处理,但这种引擎不支持索引。
- Archive: Archive 存储引擎用于存储和检索大量的数据,如日志文件。它使用压缩技术来减少存储需求,但是不支持事务。
- Federated: Federated 存储引擎提供了将数据存储在远程 MySQL 服务器的能力。这使得复杂的分布式架构可以更容易地实现,但可能会有性能问题。
- Blackhole: Blackhole 存储引擎接受数据的写入,但不保存数据,所有的 SELECT 操作都会返回空。它通常用于复制和日志记录。
MySQL 的锁有哪些?
按照锁的颗粒度分:
- 行锁:锁住某行数据,粒度最小,并发效率较高。
- 表锁:锁住整张表,影响并发效率。
- 间隙锁:锁的是一个区间。
是否共享
- 共享锁:也就是读锁,事务加锁之后,其他事务可以读,不能写。
- 排他锁:也即是写锁,事务加锁之后,其他事务可以写,不能读。
其他分类
- 乐观锁:并没有物理意义上的锁,而是通过某个字段,如版本号来实现的。
- 悲观锁:在对数据进行修改之前,会先获得锁,等到事务执行完毕之后,释放锁,在此期间,其他事务如果想要修改数据,只能等待。
如何对慢 SQL 进行优化?
- 检查是否走了索引。
- 检查所使用的索引是否是最优索引。
- 检查数据库表中的数据是否过多了。
- 检查业务使用中,所查询的字段是否都是必要的。
- 检查数据库实例的性能配置是否需要提升,可以通过 CPU 使用率、内存利用率、连接数、I/O 几个方面进行衡量。
如何实现分库分表?
分库分表本质上是把原来存储在一个数据库中的数据,拆分到多个数据库,或者把存储在一张表的数据,拆分到多张表中。分库分表具体来说,可以分为两种方式,水平拆分和垂直拆分。
水平拆分:将数据分散到多张表中,涉及分区键。
- 分库:根据场景和需求,将数据拆分到不同数据库,数据库的结构一样,数据不一样。
- 分表:通过一致性哈希将数据拆分到多张表中,每张表的数据结构一样,数据不一样。
垂直拆分:将数据库字段进行拆分,涉及数据表重构。
- 分库:库的结构和数据都不一样,所有库的所有数据的并集为全量数据。
- 分表:每张表的结构和数据都不一样,通过某一列进行关联,所有数据的并集为全量数据。
什么是一致性哈希?使用一致性哈希进行分库分表后,如何解决数据倾斜问题?
一致性哈希是将存储数据和节点都映射到一张首位相连的环上,增加或删除一个节点时,只影响该节点在哈希环上顺时针相邻的后继节点。
为了解决数据倾斜问题,还需要引入虚拟节点,不再将真实节点映射到哈希环上,而是将虚拟节点映射到哈希环上,并将虚拟节点映射到真实节点上,形成两层映射。
存储拆分后如何解决唯一主键?
- UUID:简单,性能好,但没有顺序,而且有可能泄露 Mac 地址的信息。
- 数据库主键:实现简单,但和业务强依赖,存在性能瓶颈,拓展性比较低。
- redis、mongodb、zk 等中间件:增加了系统的复杂度和稳定性。
- 雪花算法
数据库的 ACID 是如何保证的?
ACID 是数据库事务的四个关键属性,它们分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这些属性可以保证数据库事务的可靠性和正确性。
- 原子性:原子性指的是一个事务的所有操作,要么全部成功,要么全部失败,不存中中间状态。原子性由锁和 undo log 来保证,undo log 中记录了事务的变化,在回滚时,需要先计算出回滚前的数据,再进行数据恢复,并释放相关的共享锁和排他锁。
- 隔离性:隔离性指的是一个事务的状态,在最终提交之前,对其他事务是不可兼得。隔离型保证了多个事务同时执行时,互相看不到对方的中间状态,因而避免了数据的丢失和冲突。隔离性是通过锁机制和多版本并发控制(MVCC)来保证的。
- 一致性:一致性指的是事务执行前后,数据库的状态总是从一个一致性的状态转变为另一个一致性的状态。一致性由程序代码和其他三大特性(原子性、隔离性、持久性)来保证。
- 持久性:持久性指的是,一旦事务提交成功,所做的修改将永久保存到数据库中,即使系统故障、崩溃或宕机也不会丢失。持久性由内存和 redo log 来保证的。MySQL 在修改数据的同时,会在内存缓冲区和 redo log 中同时记录这次操作(redo log 是顺序写入的,因此写入速度比较快),宕机时可以通过 redo log 将未写入磁盘的数据保存下来。
InnoDB 中,一条事务更新操作的执行过程是怎样的?
在介绍事务的执行过程之前,需要先介绍三个概念:
- redo log:InnoDB 存储引擎实现的日志,用于记录事务的执行过程。
- bin log:MySQL Server 层实现的日志,有三种格式类型(Statement、Row、Mixed),其中 Statement 为默认格式,记录相应的 SQL 语句,Row 格式记录行数据最终被修改的状态,Mixed 根据具体情况自动选择使用。
- buffer pool:InnoDB 存储引擎实现的缓存池,在内存中缓存了索引页、数据页、Undo 页、自适应哈希索引、锁信息等等。
下面是事务的执行过程:
- 事务开始:执行 BEGIN 或 START TRANSACTION 命令,开始一个新的事务。
- 写入 redo log:将操作记录写入 redo log 中,InnoDB 事务进入 prepare 状态。
- 执行更新操作:在执行更新操作时,会先检查相关的数据页是否在内存中,如果在内存中,直接在内存中进行修改,如果不在内存中,会先将数据拷贝至内存,再在内存中进行修改。需要注意的是,在进行修改之前,会先将修改前的数据记录在 undo log 中,便于回滚操作。
- 写入 buffer pool:InnoDB 使用 buffer pool 缓存磁盘上的数据,以提高读写性能。
- 写入 bin log:如果 bin log 的类型为 Row 或者 Mixed,则会将该操作的状态写入 bin log。
- 提交事务:执行 COMMIT 命令,将事务提交。在提交事务之前,InnoDB 会将 redo log 中的操作标记为 commit 。
- 写入磁盘:在提交事务后,InnoDB 将 buffer pool 中的数据写入磁盘中的数据文件中。此时,数据已经持久化到磁盘中,可以在数据库重启后恢复。
需要注意的是,InnoDB 在执行大量的事务操作时,为了避免频繁的写磁盘操作,会先将多个修改记录到 redo log 中,累积到一定阈值之后,一次性将其写入磁盘。
什么是 MVCC?
多版本并发控制(MVCC)是一种数据库管理系统中常用的并发控制技术。在读数据时,通过一种类似快照的方式,将数据保存下来,不同的事务会看到自己特定版本的数据和版本链,从而避免读写冲突。MVCC 只能在读已提交(Read Committed)和可重复读(Repeatable Read)两个隔离级别下工作。
为了实现 MVCC,聚簇索引中会有两个必要的隐藏列:
- trx_id:存储对某条聚簇索引进行修改时的事务 ID。
- roll_pointer:是一个指向数据行的指针,指向最新版本的数据。
在 MVCC 中,会在开始事务时创建 readview,readview 保存了事务读取数据时所需要的版本信息,排序成一个数组,如果要执行的事务 ID 比 readview 小(该事务已提交),则可以访问,如果要执行的事务 ID 在 readview 中,或者比 readview 大,则表示该事务未提交或者该事务在 readview 生成之后才出现的。
MySQL 有哪些隔离级别?
幻读(Phantom Read):幻读指的是在一个事务中执行两次相同的查询,但是两次查询查询的结果不一致。这种情况通常发生在一个事务中插入或删除了一些行,而另一个事务在此期间执行了两次相同的查询,由于第二个查询返回了新插入或删除的行,因此称为幻读。
脏读(Dirty Read):脏读指的是一个事务读取了另一个事务未提交的数据。在这种情况下,如果另一个事务回滚,则读取的数据就是无效的。
MySQL 有四个隔离级别,按照数据一致性和并发性能的权衡顺序,从低到高依次为:
- 读未提交(Read Uncommitted):最低的隔离级别,允许一个事务读取另一个事务未提交的数据。这种隔离级别会导致脏读、不可重复读和幻读等问题,一般不建议使用。
- 读已提交(Read Committed):Oracle 的默认隔离级别。允许一个事务只读取已经提交的数据。这种隔离级别可以避免脏读,但是可能会发生不可重复读和幻读等问题。
- 可重复读(Repeatable Read):MySQL 默认的隔离级别。独到的数据都是已提交的数据,并且能够保证一个事务多次读取同一数据时,得到的结果是一致的。这种隔离级别实现比较简单,性能相对较好,可以避免脏读和不可重复读,但是可能会发生幻读问题。
- 串形化(Serializable):最高的隔离级别,强制事务串行执行,避免脏读、不可重复读和幻读等问题。但是这种隔离级别会影响数据库的性能,一般只在必要时使用。
其中,隔离级别越高,事务之间的隔离程度越高,数据的一致性也就越高,但是并发性能也会受到一定的影响。因此,在选择隔离级别时需要根据应用程序的需求和性能瓶颈,进行权衡和选择。
MySQL 主从同步的过程是怎样的?
MySQL 主从同步的过程主要涉及三个线程:
- Master binlog dump thread:用于将主节点上的数据更改操作记录到二进制日志(binlog)中。
- Slave I/O thread:在从节点上运行的线程,用于连接主节点,并从主节点获取二进制日志文件。I/O 线程在启动时会请求主节点上的 binlog 线程,获取 binlog 文件的位置信息,并将请求的 binlog 内容写入从节点上的中继日志(relay log)文件中。
- Slave SQL thread:在从节点上运行的线程,用于读取中继日志文件中的内容,然后在从节点上执行这些 SQL 语句,以实现数据的同步。
除此之外,在同步的过程中,主节点和从节点都会维护和更新正在执行的事务的状态和位置信息。
同步的过程如下:
- 数据库在启动时会创建 binlog 日志文件,主节点在数据更新时会将所有变更记录到 binlog 中。
- 主节点的 log dump 线程在 binlog 文件发生变动时,将数据发送给从节点。
- 从节点的 I/O 线程接收到 binlog 日志后,将其写入 relay log 日志中。
- 从节点的 SQL 线程读取 relay log 日志文件中的内容,对数据进行重放,最终保证主从数据的一致性。
由于整个过程是异步的,为了保证数据库的一致性和可靠性,需要利用全同步复制或者半同步复制:
- 全同步复制:主节点将数据写入 binlog 后,强制同步日志到所有从节点,只有所有的从节点执行完成后,再将数据返回给客户端。
- 半同步复制:主节点将数据写入 binlog 后,将数据同步给从节点,主节点只要收到一个从节点的确认信息就认为写操作完成。
当然,这两种方式也不能完全保证数据的安全性和一致性,比如网络延迟或从节点压力较大时,可能造成数据不一致或延迟更新。