1. 简介
MySQL, the most popular Open Source SQL database management system, is developed, distributed, and supported by Oracle Corporation.
The MySQL website (MySQL) provides the latest information about MySQL software.
- MySQL is a database management system.
- MySQL databases are relational.
- MySQL software is Open Source.
- The MySQL Database Server is very fast, reliable, scalable, and easy to use.
- MySQL Server works in client/server or embedded systems.
- https://dev.mysql.com/doc/refman/8.0/en/what-is-mysql.html
2. 基本概念
介绍 MySQL 的核心概念,例如数据库、表、行、列、索引等。
2.1 执行过程
2.2 存储引擎
2.2.1 Myisam
支持表锁,适合读密集的场景,不支持外键,不支持事务,索引与数据在不同的文件
2.2.2 Innodb
支持行、表锁,默认为行锁,适合并发场景,支持外键,支持事务,索引与数据同一文件
2.2.3 存储引擎比较
编号 | 区别 | InnoDB | MyISAM |
1 | 锁 | InnoDB 支持行级锁(row-level locking)和表级锁 | MyISAM 只有表级锁(table-level locking) |
2 | 索引 | (B+树,存具体数据,聚簇索引)其数据文件本身就是索引文件。相比MyISAM,其表数据文件本身就是按B+Tree组织的一个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引(或聚集索引)”。 | (B+树,存地址,非聚簇索引)B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。 |
3 | 事务 | InnoDB 提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。 | 强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。 |
4 | 外键 | InnoDB支持 | MyISAM不支持 |
5 | 崩溃恢复 | InnoDB支持 | MyISAM不支持 |
6 | MVCC | 应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 和 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现 | MyISAM不支持 |
7 | 文件 | 由数据库的结构文件和(数据+索引)两部分构成:test_innodb_lock.frm, test_innodb_lock.idb,叶子节点存储看数据,索引文件和数据文件合并了。聚集索引:数据和索引聚集在一起了,主键索引和其他索引之间的区别:其他索引存储的是主键,主键存的是data。为什么推荐整型数据自增?主要是在分裂的时候减少平衡操作。 | 由数据库的结构文件,数据,索引三部分构成:test_myisam.frm, test_myisam.MYD, test_myisam.MYI,非聚集索引数据文件和索引文件是分开的。 |
2.3 索引
2.3.1 聚簇索引和非聚簇索引
- 聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据(主键索引)
- 非聚簇索引:将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置(辅助索引)
聚簇索引的叶子节点就是数据节点,而非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。
2.3.2 最左前缀问题
MySQL的“最左前缀”原则主要是与索引的使用有关,特别是在复合索引(即包含多个列的索引)的上下文中。这个原则的核心思想是,当你查询一个复合索引时,MySQL可以高效地使用这个索引,但前提是查询条件使用了索引的最左侧的那些列。
举个例子,假设你有一个复合索引 (a, b, c)
:
- 查询条件只包含
a
:MySQL可以使用这个索引。 - 查询条件包含
a
和b
:MySQL可以使用这个索引。 - 查询条件包含
a
、b
和c
:MySQL可以使用这个索引。 - 查询条件只包含
b
或c
:MySQL不能高效地使用这个索引,因为它没有从索引的最左侧开始。 - 查询条件包含
b
和c
:同样,MySQL不能高效地使用这个索引,因为条件没有包含最左侧的列a
。
这个原则背后的原因是索引的结构。复合索引在物理上是按照最左侧的列进行排序的,所以只有当查询条件包含最左侧的列时,MySQL才能有效地利用索引来快速定位数据。
这个原则对于优化数据库查询性能非常重要,因为它可以帮助你理解如何创建和使用索引,以最大限度地提高查询速度。在设计数据库和编写查询时,应该考虑这个原则,确保索引能够有效地支持你的查询需求。
2.3.3 索引失效的场景
序号 | 场景 |
1 | 联合索引不满足最左匹配 |
2 | 使用了select * |
3 | 列参与了运算 |
4 | 使用了函数,如substr |
5 | 错误使用like |
6 | 类型存在隐式转换 |
7 | 使用OR操作:其中一个字段没有创建索引 |
8 | 两列做比较,eg. salary>age |
9 | 不等于比较 |
10 | is not null |
11 | not in和not exists如果是走普通索引失效 |
12 | order by可能导致索引失效 |
13 | 参数不同可能导致索引失效:DBMS存在自动优化 |
2.4 事务
2.4.1 ACID
- 原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
- 一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
- 隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
- 持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
2.4.2 并发带来的问题
编号 | 名称 | 解释 |
1 | 脏写 | 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后, |
2 | 脏读(读了还没有提交的数据) | 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中 |
3 | 不可重复读(已提交事务更改数据) | 在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。(同一个事务中多次读)(read_view在read committed隔离级别下,read_view会在别的事务commit后更新,因此在这个事务中可能会不一样) |
4 | 幻读(针对其他事务已提交新增加的数据) | 它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。 |
2.4.3 事务隔离级别
编号 | 名称 | 解释 |
1 | read uncommitted(读取未提交) | 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。 |
2 | read committed(读取已提交) | 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。 |
3 | repeatable read(可重复读) | 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。(默认的级别) |
4 | serializable(可串行化) | 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行 |
2.4.4 MVCC
MVCC,即多版本并发控制(Multi-Version Concurrency Control),是MySQL中实现高并发访问的一种重要机制。其核心原理是,通过在数据行上维护多个版本,并记录每个版本的时间戳,使得每个事务在执行时都能看到一个一致的数据快照。
在MVCC中,每个事务都有自己的视图,这个视图就是事务执行时看到的数据库快照。当事务开始时,系统会为其创建一个视图,并记录下当前数据库中所有数据行的时间戳。当事务需要读取数据时,系统会根据该事务的视图,选择最近的版本进行读取。而当事务需要写入数据时,系统会检查该事务的视图是否与当前数据库中的数据行产生冲突。如果存在冲突,则该事务需要等待其他事务完成后,再进行写入操作。
MVCC机制具有以下优点:
- 支持高并发访问:通过为每个事务提供独立的视图,使得多个事务可以同时读取同一份数据,从而提高了数据库的并发性能。
- 避免频繁加锁互斥:对一行数据的读和写两个操作默认是不会通过加锁互斥来保证隔离性,这有助于减少锁的开销和争用问题。
- 解决幻读问题:MySQL通过引入MVCC机制,使得大多数读操作都可以不用加锁,从而解决了幻读问题。
需要注意的是,虽然MVCC提高了并发性能,但并不意味着它完全避免了锁的使用。在某些情况下,如串行化隔离级别,为了确保数据的一致性,仍然需要使用锁。
总的来说,MVCC是MySQL中一种重要的并发控制机制,它通过维护数据的多个版本来实现事务的隔离性和并发性,从而提高了数据库的性能和可靠性。
InnoDB通过为每个事务在启动时分配一个事务ID来实现MVCC。该ID在事务首次读取任何数据时分配。在该事务中修改记录时,将向Undo日志写入一条说明如何恢复该更改的Undo记录,并且事务的回滚指针指向该Undo日志记录。这就是事务如何在需要时执行回滚的方法。当不同的会话读取聚簇主键索引记录时,InnoDB会将该记录的事务ID与该会话的读取视图进行比较。如果当前状态下的记录不应可见(更改它的事务尚未提交),那么Undo日志记录将被跟踪并应用,直到会话达到一个符合可见条件的事务ID。这个过程可以一直循环到完全删除这一行的Undo记录,然后向读取视图发出这一行不存在的信号。事务中的记录可以通过在记录的“info flags”中设置“deleted”位来删除。这在Undo日志中也被作为“删除标记”进行跟踪。
值得注意的是,所有Undo日志写入也都会写入Redo日志,因为Undo日志写入是服务器崩溃恢复过程的一部分,并且是事务性的。[插图]这些Redo日志和Undo日志的大小也是高并发事务工作机制中的重要影响因素。
2.4.5 MySQL事务实现
MySQL中的事务实现是通过存储引擎层的redo log、undo log和锁系统来保障的。
-
redo log(重做日志): 用于保证事务的持久性。事务对数据页的更改首先写入redo log中,然后再写入数据文件。
-
undo log(回滚日志): 用于保证事务的原子性和隔离性。未提交的事务在回滚时会使用undo log来撤销已经执行的更改。
-
锁系统: 用于保证事务的隔离性和一致性。锁是实现事务隔离级别的关键。
事务实现的简化过程如下:
-
开始事务:开始事务时,记录事务ID和回滚段的信息。
-
数据变更:执行更改数据的操作时,首先生成redo log,记录变更后的数据状态。然后在buffer pool中修改数据,并为修改的数据加锁。
-
提交事务:提交事务时,将redo log的状态更新为提交,并写入到磁盘。
-
回滚事务:如果事务未提交,在回滚时,通过undo log来撤销所有的更改。
示例代码(仅为理论模型,非实际MySQL代码):
START TRANSACTION;
UPDATE my_table SET column_name = 'new_value' WHERE id = 1;
-- 内部逻辑:
-- 1. 生成redo log,记录id=1的行更新后的状态。
-- 2. 修改buffer pool中的数据,并加锁。
COMMIT;
-- 内部逻辑:
-- 1. 将redo log的状态更新为提交。
-- 2. 将数据刷新到磁盘。
-- 如果事务未提交:
ROLLBACK;
-- 内部逻辑:
-- 1. 使用undo log来撤销所有的更改。
注意:实际的MySQL事务实现要复杂得多,涉及到多种情况和优化措施,如MVCC(多版本并发控制)、2PC(两阶段提交)、redo log的归档、binlog的同步等。
2.5 锁
行锁,表锁,意向锁
InnoDB⽀持⾏级锁(row-level locking)和表级锁,默认为⾏级锁
InnoDB按照不同的分类的锁:
共享/排它锁(Shared and Exclusive Locks):行级别锁,
意向锁(Intention Locks),表级别锁
间隙锁(Gap Locks),锁定一个区间
记录锁(Record Locks),锁定一个行记录
- 表级锁:(串行化)
Mysql中锁定 粒度最大的一种锁,对当前操作的整张表加锁,实现简单 ,资源消耗也比较少,加锁快,不会出现死锁 。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。
- 行级锁:(RR、RC)
Mysql中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。 InnoDB支持的行级锁,包括如下几种:
- 记录锁(Record Lock)
对索引项加锁,锁定符合条件的行。其他事务不能修改和删除加锁项;
- 间隙锁(Gap Lock)
对索引项之间的“间隙”加锁,锁定记录的范围,不包含索引项本身,其他事务不能在锁范围内插入数据。
- Next-key Lock
锁定索引项本身和索引范围。即Record Lock和Gap Lock的结合。可解决幻读问题。
InnoDB 支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,而意向锁就是其中的一种表锁。
- 共享锁( shared lock, S )
锁允许持有锁读取行的事务。加锁时将自己和子节点全加S锁,父节点直到表头全加IS锁
- 排他锁( exclusive lock, X )
锁允许持有锁修改行的事务。 加锁时将自己和子节点全加X锁,父节点直到表头全加IX锁
- 意向共享锁(intention shared lock, IS)
事务有意向对表中的某些行加共享锁(S锁)
- 意向排他锁(intention exclusive lock, IX)
事务有意向对表中的某些行加排他锁(X锁)
3. 实践应用
介绍如何使用 MySQL 创建数据库、表、插入数据、查询数据等。
3.1 基础用法
3.1.1 JOIN
- left join(左联接) 返回包括左表中的所有记录和右表中关联字段相等的记录
- right join(右联接) 返回包括右表中的所有记录和左表中关联字段相等的记录
- inner join(等值连接) 只返回两个表中关联字段相等的行
3.2 分库分表
3.2.1 垂直分表
3.2.2 水平分表
3.3 主从复制
3.3.1 主从复制过程
MySQl主从复制:
-
原理:将主服务器的binlog日志复制到从服务器上执行一遍,达到主从数据的一致状态。
-
过程:从库开启一个I/O线程,向主库请求Binlog日志。主节点开启一个binlog dump线程,检查自己的二进制日志,并发送给从节点;从库将接收到的数据保存到中继日志(Relay log)中,另外开启一个SQL线程,把Relay中的操作在自身机器上执行一遍。
-
优点:
-
作为备用数据库,并且不影响业务
-
可做读写分离,一个写库,一个或多个读库,在不同的服务器上,充分发挥服务器和数据库的性能,但要保证数据的一致性
-
binlog记录格式:statement、row、mixed
基于语句statement的复制、基于行row的复制、基于语句和行(mix)的复制。其中基于row的复制方式更能保证主从库数据的一致性,但日志量较大,在设置时考虑磁盘的空间问题。
MySQL 的二进制日志(binlog)是文件形式存在的。MySQL 的 binlog 记录了数据库的所有修改操作(如 INSERT、UPDATE、DELETE),以及数据定义语言(DDL)语句,但不记录 SELECT 和 SHOW 这类的语句。这些日志文件对于数据的备份、恢复和复制非常重要。
3.3.2 数据一致性问题
"主从复制有延时",这个延时期间读取从库,可能读到不一致的数据。
缓存记录写key法:
在cache里记录哪些记录发生过的写请求,来路由读主库还是读从库
异步复制:
在异步复制中,主库执行完操作后,写入binlog日志后,就返回客户端,这一动作就结束了,并不会验证从库有没有收到,完不完整,所以这样可能会造成数据的不一致。
半同步复制:
当主库每提交一个事务后,不会立即返回,而是等待其中一个从库接收到Binlog并成功写入Relay-log中才返回客户端,通过一份在主库的Binlog,另一份在其中一个从库的Relay-log,可以保证了数据的安全性和一致性。
全同步复制:
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
3.4 分布式事务
在MySQL中实现分布式事务是一个复杂的问题,因为MySQL本身并不直接支持跨多个独立数据库实例的分布式事务。然而,有几种方法和技术可以帮助你在MySQL环境中处理分布式事务的需求。以下是几种常见的实现MySQL分布式事务的方案:
3.4.1 两阶段提交(2PC)和三阶段提交(3PC):
- 这两种协议是经典的分布式事务解决方案。它们通过协调者(Coordinator)和参与者(Participant)之间的通信来确保事务的原子性。
- 在MySQL中,你可以使用存储过程或外部应用程序来模拟这些协议,但请注意,它们可能会受到网络延迟、故障转移和性能问题的影响。
3.4.2 使用分布式事务中间件
- 有一些中间件产品(如Seata、Narayana等)提供了对分布式事务的支持,它们可以集成到MySQL环境中。
- 这些中间件通常提供了事务的协调、日志记录和恢复机制,以确保跨多个数据库实例的事务一致性。
3.4.3 基于消息队列的事务
- 通过消息队列(如RabbitMQ、Kafka等)来协调分布式事务。
- 一个事务的发起者会发布消息到队列,其他参与者监听这些消息并执行相应的操作。如果所有操作都成功,则提交事务;否则,回滚事务。
- 这种方法需要仔细处理消息的可靠传递、顺序和幂等性。
3.4.4 使用XA事务
- MySQL支持XA事务,它允许一个全局事务跨越多个资源管理器(如多个数据库)。
- 你可以使用XA协议来启动、准备和提交或回滚分布式事务。但是,XA事务的性能可能不如本地事务,并且需要所有参与者都支持XA。
3.4.5 基于补偿事务的分布式事务
在这种方法中,每个操作都有一个对应的补偿操作。如果主操作失败,则执行补偿操作来撤销已经完成的操作。
- 这需要仔细设计每个操作和它的补偿操作,以确保数据的完整性和一致性。
3.4.6 使用分布式数据库解决方案
- 考虑使用像Google Spanner、Amazon Aurora等分布式数据库解决方案,它们内置了对分布式事务的支持。
- 这些解决方案通常提供了水平扩展性、高可用性和容错能力,但可能涉及到迁移数据和调整应用程序代码。
3.4.7 应用层重试逻辑
- 在应用层实现重试逻辑来处理分布式事务中的失败。
- 当某个操作失败时,应用程序可以重试该操作或执行其他补偿操作。
- 这种方法需要仔细处理重试策略、幂等性和事务边界。
4. 性能优化
4.1 索引优化
4.1.1 回表查询和覆盖索引
普通索引(唯一索引+联合索引+全文索引)需要扫描两遍索引树
(1)先通过普通索引定位到主键值id=5;
(2)在通过聚集索引定位到行记录;
这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。
覆盖索引:主键索引==聚簇索引==覆盖索引
如果where条件的列和返回的数据在一个索引中,那么不需要回查表,那么就叫覆盖索引。
实现覆盖索引:常见的方法是,将被查询的字段,建立到联合索引里去。
4.1.2 Explain与优化
explain关键字用于分析sql语句的执行情况,可以通过他进行sql语句的性能分析。
字段 | 应用 |
type:表示连接类型, | 从好到差的类型排序为: |
key:显示MySQL实际决定使用的键。 | |
key_len | 显示MySQL决定使用的键长度,长度越短越好 |
Extra:额外信息 | Using filesort:MySQL使用外部的索引排序,很慢需要优化。 |
4.2 读写分离
5. 常见问题解答
5.1 死锁
5.1.1 常见的死锁场景
5.1.1.1 多个事务尝试以不同的顺序锁定资源
假设有两个事务,T1和T2。T1先锁定资源A,然后尝试锁定资源B;而T2先锁定资源B,然后尝试锁定资源A。这时,T1等待T2释放资源B,而T2等待T1释放资源A,形成死锁。
5.1.1.2 间隙锁导致的死锁
在InnoDB存储引擎中,当使用范围条件查询并尝试锁定记录时,可能会使用间隙锁。如果多个事务尝试以不同的方式锁定相同的间隙,也可能导致死锁。
5.1.2 如何触发
要触发死锁,可以设计两个或多个并发运行的事务,它们按照上述方式尝试锁定资源。以下是一个简单的例子:
-- 事务T1
START TRANSACTION;
SELECT * FROM table1 WHERE id = 1 FOR UPDATE;
-- 等待一段时间
SELECT * FROM table2 WHERE id = 1 FOR UPDATE;
COMMIT;
-- 事务T2
START TRANSACTION;
SELECT * FROM table2 WHERE id = 1 FOR UPDATE;
-- 等待一段时间
SELECT * FROM table1 WHERE id = 1 FOR UPDATE;
COMMIT;
以上,开启两个窗口分别执行事务1,事务2,将会爆一下错误:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
5.1.3 如何解决
5.1.3.1 检查并优化查询和事务设计
- 确保事务尽可能短小,以减少锁持有的时间。
- 避免在事务中进行不必要的查询或操作。
- 如果可能,尝试以相同的顺序锁定资源。
5.1.3.2 使用锁超时
可以设置innodb_lock_wait_timeout
参数来控制事务等待锁的最长时间。如果超时,事务会被回滚,从而避免死锁。
5.1.3.3 检测并处理死锁
- 使用
SHOW ENGINE INNODB STATUS
命令来查看InnoDB存储引擎的状态,包括最近的死锁信息。 - 根据死锁信息,分析并优化相关的事务和查询。
- 在某些情况下,可以考虑使用
SET DEADLOCK_PRIORITY
来设置事务的死锁优先级,但这通常不是首选解决方案。
5.1.3.4 考虑使用乐观锁策略
在某些场景下,可以考虑使用乐观锁策略来避免死锁。乐观锁通常基于版本号或时间戳来实现,当数据被修改时,版本号或时间戳会增加。在更新数据时,会检查版本号或时间戳是否已更改,如果已更改,则更新失败。
5.2 数据库负载过高
数据库负载过高的排查可以通过以下步骤进行:
-
监控和诊断工具:使用数据库自带的监控工具或第三方性能监控工具来观察数据库状态。例如,MySQL的
SHOW STATUS
命令和performance_schema
模块1719。 -
慢查询日志:开启慢查询日志,找出执行时间长的查询语句,进行优化或重写1624。
-
进程列表:查看当前数据库的进程列表,识别长时间运行的查询或锁等待的事务1621。
-
资源使用情况:检查CPU、内存、磁盘I/O等资源的使用情况,确定是否有资源瓶颈1721。
-
查询优化:分析慢查询,优化SQL语句,比如使用更合适的索引,减少不必要的数据访问,优化JOIN操作等16181920。
-
索引优化:检查索引是否合理,是否存在缺失或冗余的索引,进行索引重建或重新设计161819。
-
架构优化:考虑是否需要通过读写分离、分库分表、分布式缓存等架构优化手段来提高性能1820。
-
硬件检查:确认硬件资源是否足够,比如磁盘速度是否跟得上,内存是否足够等18。
-
系统配置:检查数据库配置参数,如缓冲池大小、连接数限制等,根据需要进行调整18。
-
网络问题:排查网络延迟或不稳定是否对数据库性能有影响。
-
应用程序行为:分析应用程序的数据库访问模式,检查是否有不合理的使用习惯,如频繁的全表扫描、大量的小事务等20。
-
锁等待:检查是否有死锁或长时间的锁等待,优化事务处理逻辑16。
-
数据量和存储结构:考虑数据量的增长和存储结构的选择是否合适,比如是否需要归档旧数据或使用更合适的存储引擎20。
通过综合这些方法,可以有效地定位和解决数据库负载过高的问题。
6. 对比
6.1 MySQL VS. ClickHouse
6.1.1 OLTP和OLAP
OLTP(在线事务处理)和OLAP(在线分析处理)是两种数据处理系统
6.1.2 列式存储和行式存储
6.2 MySQL VS. TiDB
TiDB:高级分布式 SQL 数据库 (pingcap.com)
TiDB(/'taɪdiːbi:/,“Ti”代表 Titanium)是一个开源的分布式 SQL 数据库,支持混合事务和分析处理 (HTAP) 工作负载。它与MySQL兼容,具有水平可扩展性、强一致性和高可用性。TiDB 的目标是为用户提供涵盖 OLTP(Online Transactional Processing)、OLAP(Online Analytical Processing) 和 HTAP 服务的一站式数据库解决方案。TiDB 适用于各种需要高可用和与大规模数据强一致性的用例。
TiDB的架构如下:TiDB Architecture | PingCAP Docs
6.2.1 TiDB 服务器
TiDB 服务器是一个无状态的 SQL 层,将 MySQL 协议的连接端点暴露给外部。TiDB 服务器接收 SQL 请求,进行 SQL 解析和优化,最终生成分布式执行计划。它是水平扩展的,并通过负载均衡组件(如 TiProxy、Linux 虚拟服务器 (LVS)、HAProxy、ProxySQL 或 F5 等提供与外部的统一接口。它不存储数据,仅用于计算和 SQL 分析,将实际的数据读取请求传输到 TiKV 节点(或 TiFlash 节点)。
6.2.2 置放驱动程序 (PD) 服务器
PD 服务器是整个集群的元数据管理组件。它存储每个 TiKV 节点的实时数据分发元数据和整个 TiDB 集群的拓扑结构,提供 TiDB Dashboard 管理 UI,并为分布式事务分配事务 ID。PD 服务器是整个 TiDB 集群的“大脑”,因为它不仅存储集群的元数据,还会根据 TiKV 节点实时上报的数据分发状态,向特定的 TiKV 节点发送数据调度命令。此外,PD服务器至少由三个节点组成,并且具有高可用性。建议部署奇数个PD节点。
6.2.3 存储服务器
6.2.3.1 TiKV 服务器
TiKV 服务器负责存储数据。TiKV 是一款分布式事务键值存储引擎。
区域是存储数据的基本单位。每个区域存储特定密钥范围的数据,该范围是从 StartKey 到 EndKey 的左闭合和右开间隔。
每个 TiKV 节点都存在多个 Region。TiKV API 在键值对级别为分布式事务提供原生支持,默认支持快照隔离级别隔离。这是 TiDB 在 SQL 级别支持分布式事务的核心。处理完 SQL 语句后,TiDB 服务器会将 SQL 执行计划转换为对 TiKV API 的实际调用。因此,数据存储在 TiKV 中。TiKV 中的所有数据都自动维护在多个副本中(默认为 3 个副本),因此 TiKV 具有原生高可用并支持自动故障转移。
6.2.3.2 TiFlash 服务器
TiFlash 服务器是一种特殊类型的存储服务器。与普通的 TiKV 节点不同,TiFlash 是按列存储数据,主要是为了加速分析处理。