第一章 MYSQL的架构与历史
第一章 MYSQL的架构与历史
一、mysql系统架构
1.mysql三层逻辑架构:
1层:连接处理、授权认证、安全等
2层:大多数mysql核心功能在此层,包括查询解析、分析、优化、缓存以及内置函数、所有跨存储引擎功能(存储过程、触发器、视图)都在这一层
3层:包括了存储引擎、负责MYSQL中数据存储和提取
2.连接管理和安全性:
每个客户端连接在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,该线程只能轮流在某个CPU核心或者CPU中运行,服务器会负责缓存线程,因此不需要为每个新建的连接创建或者销毁线程
3.优化与执行:
mysql会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写查询,决定表的读取顺序,以及选择合适的索引,用户可以根据特殊关键字提示(hint)优化器,影响它的决策过程,也可以用
优化器解释器(explain)优化过程的各个因素,使用户知道服务器如何进行优化决策以及提供一个参考基准。
二.并发控制:
mysql在两个层面进行并发控制:服务器层和存储引擎层
1.读写锁:读写锁是解决多线程下的脏数据问题,读锁(read lock)是共享的、写锁(write lock)是排他的。
2.锁粒度:给定的资源上,锁定的数据量越小,则系统的并发程度越高。问题是加锁也会消耗资源,锁的各种操作(获得锁、检查锁、释放锁),都会增加系统开销。
3.锁策略:就是在锁的开销和数据安全性直接寻求平衡。大多数商业数据库系统没有提供更多选择,一般都是在表上施加行锁(row-level lock),而mysql则提供多种选择,每种mysql引擎都可以实现自己的锁策略和
锁粒度。mysql主要有两种重要的锁策略:表锁(table lock)、行级锁(row lock)
表锁:表锁是mysql最基本的锁策略,也是开销最小的策略。它会锁定整张表,一个用户对表进行CUD操作时,需要先获取写锁,这会阻塞其它用户对改表的读写操作。
行级锁:行级锁可以最大程度支持并发处理(同时也带来了最大的锁开销).
三.事务
事务就是一组原子性的SQL查询,或者说一个独立的工作单元。执行一组的语句,要么全成功,要么全失败。
1.ACID:原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability),一个运行良好的事务处理系统,必须具备这些标准特征
原子性:一个事务必须要被视为一个不可分割的最小工作单元,整个事务操作必须全成功或失败回滚。
一致性:数据库总是从一个一致性的状态转换到另一个一致性的状态。
隔离性:一个事务最终提交前,对其它事务时不可见的。
持久性:一旦事务提交,则所修改的数据会永久保存在数据库中,此时即使系统崩溃,修改的数据也不会丢失。
2.隔离级别:SQL标准中定义了四种隔离级别,每种级别都规定了一个事务所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的,较低级别的隔离通常可以执行更高的并发,系统开销更校
READ UNCOMMITTED(未提交读):事务中的修改,即使未提交,对其它事务也是可见的。事务读取未提交的数据,被称为脏读(Dirty read)
READ COMMITTED(提交读):一个事务从开始直到提交前,只能“看见”已经提交的事务所做的修改。这个级别的可能两次执行同样操作,得到不一样结果,被称为不可重复读(Nonrepeatable read)
REPEATABLE READ(可重复读):该级别保证了在同一个事务中多次读取通用的记录结果是一致的,但当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新数据,当之前事务再次读取该范围,会出现幻读(Phantom read)
SERIALIZABLE(可串行化):强制事务串行处理,在读取每一行数据上都加锁,可能会导致大量超时和锁争用的情况。
3.死锁:死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占有的资源,从而导致恶性循环。
4.事务日志:使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为持久化到硬盘上,目前大多数存储引擎都是这样实现的,我们称为预写式日志,修改日志需要写两次磁盘。
5.mysql中的事务:mysql提供了两种事务型存储引擎,InnoDB和NDB Cluster。
自动提交:mysql默认采用自动提交模式,如果不是显式开始一个事务,则每个查询都被当作一个事务提交。可以设置AUTOCOMMIT变量启用或者禁用自动提交模式
在事务中混合使用存储引擎:如果在事务中混合使用事务和非事务型的表(InnoDB和MyISAM),正常情况下没有问题,如果出现事务回滚,则非事务型的表无法撤销,mysql不会提醒也没有报错,这会导致数据不一致
隐式和显式锁定:InnoDB采用两阶段锁定协议,在事务执行过程中随时可以锁定,锁只有执行了commit或者rollback才会释放,InnoDB会根据事务隔离级别在需要的时候加锁。另外InnoDB也支持显式锁定,如:
select ...lock in share mode
select ...for update
mysql也支持LOCK TABLES 和 UNLOCK TABLES语句,这是服务器层实现的,和存储引擎无关,如果需要应用到事务,还是应该选择事务型存储引擎
四、多版本并发控制
mysql的大多数事务型存储引擎都不是简单的行级锁,基于并发性能考虑,一般都实现了多版本并发控制(MVCC),其它数据库(oracle、postgreSQL)也实现了MVCC,但各自实现机制不同。
1.MVCC:可以认为是行级锁的一个变种,但是它很多情况下避免了加锁操作,因此开销更低,实现了非阻塞的读操作,写操作也只锁定必要的行。
2.MVCC实现:通过保存数据在某个时间点的快照实现的,也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不同的。
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏列来实现的,这两个列,一个保存了行创建时间(版本号),一个保存行过期(删除)时间(版本号)。每开始一个事务,版本号会自动递增,事务开始时刻的
系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号比较。
3.MVCC具体操作:
SELECT:InnoDB会根据以下两个条件检查每行记录:
a.InnoDB只查找行版本号小于或等于当前事务版本的数据行,这样确保事务读取的行,要么是在事务开始前已存在,要么是事务自身插入或修改过的。
b.行的删除版本要么未定义,要么大于当前事务版本号,这样可以确保事务读取的行,在事务开始前未被删除。
INSERT:InnoDB为新插入每一行保存当前系统版本号为行版本号
DELETE:InnoDB为删除的每一行保存当前系统版本号为行版本号
UPDATE:InnoDB为插入一行新纪录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来行作为行删除标识
4.MVCC作用级别:MVCC只在REPEATABLE READ和READ COMMITTED两个隔离级别下工作,其它两个隔离级别和MVCC不兼容,因为READ UNCOMMITTED总是读取最新的数据行,而不符合当前事务版本的数据行,而SERIALIZABLE则对所有读取操作加锁。
五、MYSQL的存储引擎
1.InnoDB:mysql默认引擎,它被设计用来处理大量短期事务,短期事务大部分情况都是正常提交的,很少回滚。InnoDB的性能和自动崩溃修复功能,使得它在非事务存储的需求中也很流行。
2.MyISAM:mysql5.1以前的默认存储引擎,不支持行级锁和事务,崩溃后无法修复。可应用在表创建并导入数据后,不会进行修改的场景。