mysql 逻辑架构
最上层并不是mysql独有的,大多数基于网络的客户端/服务器的工具或者服务器都有类似的架构。比如连接处理,授权认证,安全等等
第二次是mysql 核心服务功能都在这一层,包括查询解析、分析、优化、缓存以及所有的内置函数(日期,时间,数学和加密函数),所有跨存储引擎的功能都在这一层实现:存储过程,触发器,视图等。
第三次包含了存储引擎。存储引擎负责mysql 中的存储和提起。服务器通过api 在粗糙女引擎进行通信。这些接口屏蔽了不同存储引擎之间的差异,是的差异对于上层的查询过程通明。事务是通过存储引擎实现的。
连接管理与安全性
每个客户端都会在服务进程中拥有一个线程,这个连接的查询只会在这个单独的线程汇总执行,该线程只能轮流在某个cpu核心或者cpu中运行。服务器会负责缓存线程,因此不需要为每个新建的连接创建或者销毁线程。
优化与执行
mysql 会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写查询,决定的表的读取顺序,以及选择合适的索引等。用户可以通过特殊的关键字提示(hint)优化器,影响的决策过程。也可以请求优化器解释explain 优化过程的各个因素,使用户知道服务器是如何惊醒优化的。
并发控制
无论合适,只要有多个查询需要再同一时刻修改数据,都会产生并发控制的问题。
读写锁
读锁,又称为共享锁 写锁,也称为排他锁
锁的粒度
表锁,锁的范围最大,开销最小。
行锁,锁的范围最小,最大程度支持并发,同时也带来了最大的锁开销。行锁时在mysql 存储引擎侧实现的。
事务
事务就是一组原子性的sql 查询,或者说一个独立的工作单元。
经典案例:假设一个银行的数据库有二张表,支票(checking)表和存储(savings)表。现在要从用户jane 的支票账户转移200 美元到她存储账号,那么至少需要三个步骤:
1、检查支票账户的余额高于200美元
2、从支票账户的余额中减去200 美元
3、在存储账户的余额中增加200 美元
上述三个步骤的操作必须打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤。
事务特性(ACID)
-
原子性: 一个事务必须视为一个不可分割的最小工作单元,整个事务的所有操作要么全部提交成功,要么全部失败回滚。
-
一致性:数据库总是从一个一致性的状态转换到另外一个一致性的状态。
-
隔离性: 一个事务所做的修改在最终提交前,对其他的事务是不可见的。
-
持久性:一旦事务提交,则其所做的修改就会永久的保存到数据库中。
事务隔离级别
- READ UNCOMMITTED(读未提交)
在READ UNCOMMITTED 级别,事务中的修改,即使没有提交,对其他事务也是可见的。事务可以读取未提交的数据,这也称之为脏读。
- READ COMMITTED (读已提交)
读其他事务已经提交的数据。但是同一个事务执行同样的查询,可能得到不一样的结果(不可重复读)
- REPEATABLE READ (可从复读)
REPEATABLE READ 解决了脏读问题。该级别保证了在同一个事务中多次读取同样的计量结果是一致的。但是理论上,可重复读还是无法解决另外一个幻读问题。
- SERIALIZABLE(可串行化)
SERIALIZABLE 最高隔离级别。它通过强制事务串行执行,避免了前面说的幻读问题。
死锁问题
死锁是指二个或者多个事务在同一资源上相互占用,并请求锁定对方占用的而资源,从而导致恶性循环的现象。
-
当多个事务试图以不同的顺序锁定资源,就可能会产生死锁
-
多个事务同时锁定同一资源时,也会产生死锁
为了解决这种问题,数据库系统实现了各种死锁检测和死锁超时机制。越复杂的系统,比如InnoDb 存储引擎,越能检测到死锁的循环依赖,并立即返回个错误。这种解决方式很有效,否则死锁会导致出现慢查询。InnoDB 目前处理死锁的方法是:将持有最少行级排他锁的事务进行回滚。
死锁发生后,只有部分或者完全回滚其中一个事务,才能打破死锁。对于事务性的系统,这是无法避免的,所以程序再设计是必须考虑如何处理死锁。大多数情况只需要重新执行因死锁回滚的事务即可。
事务日志
事务日志可以帮助提供事务效率。使用事务日志,存储引擎子啊修改表的数据是只需要修改其内存拷贝,再讲该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘中。事务日志采用的是追加的方式,因此写日志的操作是磁盘上一小块区域内顺序IO,而不像随机IO需要再磁盘的多个地方移动磁头,所以采用事务日志的方式相对来说快得多。事务日志持久后,内存中被修改的数据在后台可以慢慢刷会磁盘。目前大多数的存储引擎都是这样实现的,我们通常称之为预写式日志,修改数据需要写二次磁盘。
mysql 中的事务
mysql 提供二种事务性存储引擎,InnoDb 和NDB Cluster。另外还有一些第三方的存储引擎也支持事务。
自动提交
mysql 默认采用自动提交的模式。也就是锁,如果不是显式第开始一个事务,则每个查询都被当做一个事务执行提交操作。另外还有一些命令,在执行之前会强制执行commit 提交当前活动的事务。在数据库定义语言中(DDL),如果是会导致大量数据库改变的操作,比如alter table,另外还有lock tables 等其他语句也会导致同样的效果
在事务中混合使用存储引擎
mysql f服务器层不管理事务,事务是由下层存储引擎实现的。所以同一个事务中,使用多种存储引擎是不可靠的。
隐式和显式锁定
InnoDb 采用的二阶段协议。在事务执行过程中,随时都可以执行锁定,锁只有在执行commit 或者rollback 时才会释放,并且所有的锁在同一时刻释放。前面描述的锁都是隐式锁定,InnoDb 会根据跟李级别在需要的时候加锁。另外InnoDB也支持通过特定的语句进行显示锁定,这些语句不数据sql 规范。
-
select ... lock in share mode
-
select ... for update