- Mysql 是单进程多线程的结构
- 这些内部线程包括 MySQL 自己用来刷脏,读写数据等操作的系统线程,也包括处理用户 SQL 的线程(姑且叫做用户线程)。
- 用户线程有一个特殊的地方:程序端发送到 MySQL 端的 SQL,只会由一个用户线程来执行(one-thread-per-connection),所以 MySQL 在处理复杂查询的时候,会出现“一核有难,多核围观”的尴尬现象。
连接器(Connection)
- 连接器负责跟客户端建立连接(TCP握手)、获取权限、维持和管理连接。
- 连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。(一个用户权限修改后,只有再新建的连接才会使用新的权限设置)
- wait_timeout参数用于控制链接器的断开时间
连接池
MySQL连接池(Connection Pool)是一种用于管理和维护数据库连接的技术。它允许应用程序在需要访问数据库时,直接从连接池中获取一个现有的连接,而不是创建一个新的连接。这种做法可以减少连接创建和关闭的开销,提高应用程序的性能和响应速度。
连接池通常用于高并发的应用场景,如Web应用、企业应用等。以下是MySQL连接池的一些主要特点:
- 资源重用:连接池中的连接可以在多个请求之间重复使用,降低了创建和关闭连接的开销。
- 并发控制:连接池可以限制同时访问数据库的连接数,避免过多的连接导致数据库服务器负担过重。
- 连接有效性检查:连接池会定期检查连接的有效性,将失效的连接移除并替换为新的连接。
- 等待和超时:当连接池中没有可用连接时,请求可以选择等待,直到有可用连接。同时,可以设置等待超时时间,避免长时间无法获取连接的情况。
- 负载均衡:部分连接池支持负载均衡,可以根据数据库服务器的负载情况自动选择合适的服务器进行连接。
在Java语言中,常用的MySQL连接池实现包括HikariCP、Apache DBCP、C3P0等。
不使用数据库连接池的步骤:
- TCP建立连接的三次握手
- MySQL认证的三次握手
- 真正的SQL执行
- MySQL的关闭
- TCP的四次握手关闭
使用数据库连接池的步骤:
第一次访问的时候,需要建立连接。 但是之后的访问,均会复用之前创建的连接,直接执行SQL语句。
- 一般DB连接池的设计都会有test on idle,test on borrow的机制。客服端定时向服务器发select 1这样的指令,服务器返回后服务器和客户端双方就都会知道彼此还在。这样服务器就可以把链接空闲最大时间设的比较短。即便双方真的断开了,客户端test on borrow失败后也可以直接重连,新建一个连接。
- 如果直接连db,test机制重连机制需要自己搞。为了尽量维持链接,服务器需要把超时设长。这就意味着客户端直接关掉,服务器端要等到比较长的时间才能释放链接。如果触及到服务器限制最大链接数,新链接就建立不了。
分析器,优化器,执行器
- 分析器(Parser):分析器的主要任务是解析SQL查询语句。在这个阶段,分析器首先会进行词法分析,将SQL查询字符串分解成词法单元(tokens)。接着,分析器会进行语法分析,根据词法单元构建抽象语法树(AST)。在分析过程中,分析器还会检查SQL语句的语法正确性,如括号匹配、关键字使用等。
- 优化器(Optimizer):优化器负责为SQL查询生成最优的执行计划。执行计划是一个包含多个操作(如连接、排序、聚合等)的树形结构。优化器会根据查询条件、数据库统计信息(如表的大小、索引信息等)和启发式规则,选择合适的执行算法、访问路径和连接顺序。在这个阶段,优化器可能会对查询进行重写,以减少计算量和数据传输。
- 执行器(Executor):执行器负责根据优化器生成的执行计划,实际执行SQL查询。执行器会从存储引擎中请求数据,然后按执行计划中的操作顺序和方法对数据进行处理。在执行过程中,执行器还会检查用户对数据的访问权限,如读、写、更新等。最后,执行器会将查询结果返回给客户端。
存储引擎
存储引擎决定了MySQL如何存储和操作数据。存储引擎是MySQL的一个可插拔组件,允许用户根据不同的应用场景选择合适的存储引擎。常见的存储引擎包括:
- InnoDB:InnoDB是MySQL的默认存储引擎,提供了事务支持、行锁定、外键约束等功能。InnoDB采用聚簇索引(Clustered Index)来组织数据,能够提供较好的读写性能。
- MyISAM:MyISAM是MySQL早期的存储引擎,它不支持事务和行锁定,但是在某些只读或者读写分离的场景下,MyISAM可能提供更好的性能。MyISAM使用非聚簇索引(Non-Clustered Index)来组织数据。
InnoDB
InnoDB是MySQL数据库的一个存储引擎,从MySQL 5.5版本开始成为默认的存储引擎。InnoDB提供了许多关键特性,使其成为许多应用场景的理想选择,特别是对事务处理、并发控制和数据一致性要求较高的场景。以下是InnoDB存储引擎的一些主要特点:
- 事务支持(Transaction Support):InnoDB支持ACID事务,这意味着在执行多个操作时,可以确保数据的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。事务支持使得InnoDB适合用于需要执行多步操作并确保数据一致性的应用场景。
- 行级锁定(Row-Level Locking):InnoDB支持行级锁定,这意味着在执行数据修改操作时,只有被修改的数据行被锁定,而不是整个表。这种锁定策略可以有效减少锁争用,提高并发性能。InnoDB还支持多种隔离级别(如READ COMMITTED、REPEATABLE READ等),以满足不同的并发控制需求。
- 多版本并发控制(MVCC):InnoDB通过多版本并发控制(MVCC)来实现高并发性能。在MVCC模型中,每个事务都有自己的快照(snapshot),可以在事务过程中看到一个一致的数据视图。这种模型允许多个读事务同时进行,而不需要等待锁定资源,从而提高了并发性能。
- 聚簇索引(Clustered Index):InnoDB使用聚簇索引(也称为聚集索引)来组织表数据。在聚簇索引中,数据行与主键索引紧密结合,按主键顺序存储。这种索引结构在主键查找和范围查询场景下具有较好的性能。需要注意的是,InnoDB表必须具有主键(显式或隐式)。
- 数据一致性和恢复:InnoDB通过一种称为“写前日志”(Write-Ahead Logging, WAL)的技术确保数据的一致性和恢复能力。在写前日志中,对数据的修改首先被记录到日志中,然后再应用到实际的数据页。在系统故障或意外关闭的情况下,可以通过重放日志来恢复数据。
- 外键约束(Foreign Key Constraints):InnoDB支持外键约束,这使得在关联表之间维护数据的引用完整性变得更加容易。外键约束可以确保在插入、更新或删除数据时,相关表中的数据保持一致性。
- Innodb 创建表后生成的文件有
- frm:创建表的语句(MySQL 8.0 版本,则已经允许把表结构定义放在系统数据表中了)
- idb:表里面的数据+索引文件
- InnoDB 的数据是按数据页为单位来读写的。当需要读一条记录的时候,并不是将这个记录本身从磁盘
- 读出来,而是以页为单位,将其整体读入内存。在 InnoDB 中,每个数据页的大小默认是 16KB。
MyISAM
MyISAM是MySQL中一个较早的存储引擎,虽然其并不支持事务处理和行级锁定等先进特性,但在某些特定场景下,MyISAM依然具有一定的优势。以下是MyISAM存储引擎的主要特点:
- 非聚簇索引(Non-Clustered Index):与InnoDB的聚簇索引不同,MyISAM使用非聚簇索引来组织数据。在非聚簇索引中,主键索引和数据行分开存储,索引中的数据项包含了指向实际数据行的指针。这种索引结构在某些查询场景下可能具有更好的性能,但对于主键查找和范围查询可能不如聚簇索引高效。
- 表级锁定(Table-Level Locking):MyISAM使用表级锁定来控制并发访问。这意味着在执行数据修改操作时,整个表都会被锁定,其他写操作需要等待锁释放。表级锁定在读操作远多于写操作的场景下具有较好的性能,但在高并发写场景下可能导致锁争用和性能下降。
- 不支持事务(No Transaction Support):MyISAM不支持ACID事务,这意味着它不适用于需要确保数据原子性、一致性、隔离性和持久性的应用场景。然而,在某些只读或简单的写操作场景下,MyISAM的性能可能优于支持事务的存储引擎。
- 数据压缩(Data Compression):MyISAM支持表数据和索引的压缩,可以通过减少磁盘空间占用来提高查询性能。然而,压缩表只支持只读操作,不能进行数据的插入、更新或删除。
Myisam 创建表后生成的文件有
- frm:创建表的语句
- MYD:表里面的数据文件(myisam data)
- MYI:表里面的索引文件(myisam index)