1.1 MySQL逻辑架构
第一层服务并非MySQL独有,大多数基于网络的客户端、服务端的工具或者服务都有类似的框架。
第二层为MySQL的核心服务功能,查询解析、分析、优化、缓存以及内置函数,并且包括存储过程、触发器、视图等。
第三层为存储引擎,主要负责MySQL中数据的存储和提取。
1.1.1 连接管理与安全性
每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,且轮流使用CPU。服务器负责缓存线程,无需为每个连接创建或者销毁线程。
当客户端连接到MySQL服务器时,服务器会对其进行验证。如果使用了安全套字节(SSL)连接方式,还可以使用X.509证书认证。验证成功后,服务器会继续验证该客户端是否具有某个特定查询的权限。
1.1.2 优化与执行
MySQL会解析查询,并创建内部数据结构,并对其进行优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。用户可以通过关键词 hint 提示优化器,影响它的决策过程。也可以请求优化器解释(explain)优化过程的各个因素,提供一个参考基准。
优化器并不关心使用的是什么存储引擎,但存储引擎对于优化查询是有影响的。
1.2 并发控制
服务器层与存储引擎层
1.2.1 读写锁
解决并发问题的方法就是并发控制。再处理并发读或者写时,可以通过实现一个由两种类型的锁组成的系统来解决问题。两种类型的锁通常被称为供共享锁(shared lock)和 排他锁(exclusive lock),也叫读锁(read lock)和 写锁(write lock)。
读锁是共享的,同一时刻可以同时读取同一个资源,互不干扰。
写锁是排他的,一个写锁会堵塞其他的写锁和读锁。只有这样,才能确保在给定时间里,只有一个用户能执行写入,防止其他用户读取正在写入的统一资源。
1.2.2 锁粒度
一种提高共享资源并发性的方式就是让锁定对象更有选择性,尽量只锁定需要修改的部分数据,而不是所有的资源。
表锁(table lock)
表锁是MySQL中最基本的锁策略,并且是开销最小的策略。
行级锁(row lock)
行级锁可以最大程度的支持并发处理,并且带来最大的开销。行级锁旨在存储引擎层实现。
1.3 事物
事物就是一组原子性的SQL查询。要不全部执行成功,要么全部执行失败。
一个运行良好的事务处理系统,必须具备ACID特征。
原子性(atomicity)
一个事务必须被视为一个不可分割的最小工作单元,不能只执行其中的一部分操作。
一致性(consistency)
数据库总是从一个一致性的状态转换到另一个一致性的状态。
隔离性(isolation)
持久性(durability)
1.3.1 隔离级别
四个隔离级别
1.READ UNCOMMITTED(未提交读)
事务中的修改,即使没提交,其他事务也是可见的。事务可以读取未提交的数据,这种被称为脏读(Dirty Read)。
2.READ COMMITTED(提交读)
只能看到已提交的事务所做的修改,其他事务均不可见。
3.REPEATABLE READ(可重复读)
保证了同一个事物中多次读取同样的记录的结果是一致的。但是无法解决幻读(Phantom Read)
幻读,指当某个事务在读取某个范围的内容时,另外一个事务又在该范围插入了新的纪录。
4.SERIALIZABLE(可串行化)
使事务强制串行,避免幻读问题。会在读取的每一行数据上都加锁。
1.3.2 死锁
多个事务同时在同一资源上互相占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。大多数情况下只需要重新执行因死锁回滚的事务即可。
1.3.3 事务日志
事务日志可以帮助提高事务的效率。使用事务日志,存储引擎在修改标的数据时只需要修改其内存拷贝,再把该修改行行为记录到持久的硬盘上的事务日志中,而不是每次都将修改的数据本身持久到磁盘。事务日志采用的是追加的方式,因此写日志的操作是磁盘上一小块区域内的顺序I/O,因此会快很多。
如果数据的修改已经记录到事务日志并持久化,但数据本身还没有写会磁盘,此时系统崩溃,存储引擎在重启时能够自动回复这部分修改的数据。
1.3.4 MySQL中事务
提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster
自动提交(AUTOCOMMIT)
MySQL默认采用自动提交模式,每个查询都被当作一个事务。
可以通过命令查看并且进行设置,1或者ON表示启动,0或者OFF表示禁用。
mysql> SHOW VARIABLES LIKE 'AUTOCOMMIT';
mysql> SET AUTOCOMMIT = 1;
通过命令也可以设置隔离级别:
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
在事务中混合使用存储引擎
MySQL服务器不管理事务,事务是由下层的存储引擎实现的。当在同一个事务中,使用多种存储引擎是不可靠的。
当事务回滚时,非事务型的变更无法撤销,会导致数据库处于不一致的状态,而且难修复。
隐式和现式锁定
InnoDB采用的是两阶段锁定协议( two-phase locking protocol)。在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放。
1.4 多版本并发控制
MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC)。
可以认为MVCC是行级锁的一个变种,但是他在很多情况下避免了加锁操作。因此开销更低。
InnoDB的MVCC是如何工作的
通过在每行记录后面保存两个隐藏的列来实现,分别为创建时间和过期时间,实际是系统版本号。
Select
1.查询早于当前事务版本号的数据行,这个可以确保事务读取的行,要么是在事务开始前已经存在,要么是开始之前未被删除。
2.行的删除版本要么未定义,要么大于当前事务版本号。
Insert
保存当前系统版本号为行版本号
Delete
保存当前系统版本号为行删除标识
Update
保存当前系统版本号为行版本号,同时修改当前系统版本号为行删除标识