一、Mysql的逻辑架构
a.大致将Mysql分为3层:
1.mysql客户端,提供一些基本服务,比如连接处理、授权、安全等.
2.第二层为mysql提供的一些核心处理内容,比如查询解析、分析、优化等.
3.第三层则包含了mysql的存储引擎,用于存储和提取存放在mysql中的内容,服务器通过存储引擎API和存储引擎进行通信,存储引擎不会进行SQL解析(InnoDB是个例外,它会解析外键定义,因为MySQL服务器自身没有实现它),也不会互相通信,只是简单的响应服务器的请求.
b.连接管理和安全
每个客户连接在服务器上都有自己的线程,每个连接所属的查询都会在指定的某个单独线程中完成,这些线程轮流的运行在某个cpu上,服务器负责缓存线程,因此不必为每个新连接重建或撤销线程.
当客户端连接到服务器时,服务器要对其进行认证,认证基于用户名、主机、口令,一旦连接成功,客户端就会验证该客户端是否具有执行某个具体查询.
c.优化与执行
MySQL会解析查询,并创建一个内部数据结构(解析书),然后进行各种优化.其中包括重新查询、决定查询的读写顺序、以及选择使用的索引等.用户可以通过特殊的关键字给以优化器提示,影响它的决策过程.另外还可以请求服务器给出优化的各种说明,使用户可以知道服务器是如何进行决策的.
优化器并不关心某个表使用哪种存储引擎,但存储引擎会对服务器的查询优化有影响.优化器会请求存储引擎为某种具体操作提供性能与开销方面的信息以及表内部的统计信息.
在解析查询以前,服务器会询问查询缓存,它只能保持selelct语句和相应的结果,如果能在缓存中找到要执行的查询,服务器就不必从新解析、优化、查询.
二、并发控制
无论何时,只要不止一个查询同时修改数据库,都会产生并发控制的问题.
a.读锁和写锁
读锁和写锁又分别叫做共享锁和排他锁.
某一资源上的读锁是共享的或者互不阻塞的,在同一时间里多个用户可以读取同一资源而互不干扰;写锁是排他的,一个写锁会阻塞其他的读锁和写锁.
b.锁粒度
任何时间里,在给定的资源上,被加锁数据量越小就允许更多的并发操作,只要相互之间互不冲突即可.问题是加锁也会消耗系统资源,每一种锁操作,如获得锁、检查锁是否已解除、解除锁都会增加系统的开销.
锁策略就是在锁开销和数据安全之间寻求一种平衡,这种平衡也能影响系统性能,每种MySQL存储引擎都可以实现独有的锁策略和锁粒度。以下是两种重要的锁策略
表锁:表锁是MySQL开销最小的锁策略,它将整个表加锁,当有一个用户进行写操作时,用户会获得一个写锁,写锁会禁止其他用户任何的读写操作,只有无人做写操作时用户才能获得读锁,读锁之间互不冲突.写锁比读锁据用更高的优先级,即使有读操作用户排列在队列中,新申请的写操锁仍然会排在队列的前面(写锁会被安置在读锁之前,而读锁不能排在写锁之前).
行级锁:行级锁支持最大的并发处理,同时也带来最大的性能开销,行级锁由存储引擎实现而不是MySQL服务器实现
三、事务
事务是一组原子性的SQL查询语句,也可以看着一个工作单元.事务内的语句要么全部执行要么全部不执行.
ACID:
原子性(Atomicity):一个事务必须被视作一个单独的内部不可分的工作单元,以确保一个事务要么全部执行要么全部回滚.
一致性(Consistency):数据库总是从一种一致性状态转换到另一种一致性状态,即任何事务处理过程中作的数据改变都不会影响到数据库的内容.
隔离性(Isolation):某个事务的处理结果只有在完成之后才对其他事务可见.
持久性(Durabilit):一旦一个事务提交,事务所做的数据改变将是永久的.
a.隔离级
SQL标准定义了4类隔离级,包括了一些具体规则,用来限定事务内外哪些改变是可见的哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销.
1.READ UNCOMMITED(读取未提交内容):很少实际应用
2.READ COMMITED(读取提交内容):大多数系统默认的隔离级,但不是MySQL默认的
3.REPEATEABLE READ(可重读):MySQL的默认隔离级
4.SERIALIZABLE(可串行化):
b.死锁
死锁是指两个或多个事务在同一资源上互相占有并请求加锁导致的恶性循环,多个事务以不同的顺序加锁同一资源是就会产生死锁 .
为了解决这种问题,数据库实现了多种死锁检测和死锁超时机制.对于更复杂的系统,例如InnoDB存储引擎能够预知循环相关性,并立刻返回错误(比较好),其他的解决方法是让查询达到一个锁等待超时时间,然后再放弃争用(不够好),目前InnooDB的处理死锁的方法是回滚具有最少排他行级锁的事务(一种对最易回滚事务的估算).
c.事务日志
事务日志可以使事务处理更加高效.和每次数据一改变就更新数据表的数据不同,存储引擎可以先更新数据在内存中的拷贝,这非常快,然后存储引擎会将数据改变记录到事务日志,事务日志位于磁盘上,因此具有持久性,这相对较快,因为追加日志导致的写操作只涉及到了磁盘上很小的顺序IO,而替代了写磁盘中表所需要的大量随机IO.最后系统会在某个时间把数据更新到磁盘上的表中.大多存储引擎使用了此技术,也就是通常所说的预写式日志,利用2此磁盘操作将数据写入磁盘.
d.MySQL中的事务
MySQL中默认操作是AUTOCOMMIT型的,这意味着除非显示的开始一个事务,否则它将每一个查询视作一个单独的事务自动执行.可以通过设置变量启用和禁用AUTOCOMMIT
SHOW VARIABLES LIKE 'AUTOCOMMIT';//查看autocommit的值
SET AUTOCOMMIT = 1;//修改autocommti的值
MySQL允许用户通过命令 SET SESSION TRANSATION ISOLATION LEVEL设置隔离级,新的隔离级将在下一个事物开始时生效.用户也可以在配置文件中为整个服务器设置隔离级;使用下列命令只会为当前事务设置隔离级
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITED;
在事务中混合使用事务性表和非事务性表,如果事务回滚,那么在非事务性表上所做的修改将无法取消.
一个事务在任何时候都可以获得锁,但只有在commit或rollback的时候才会释放锁,它会同时释放掉所有锁,一般情况下InnoDB的锁定都是隐式锁,InnoDB会根据用户的隔离级别自动出来锁定.InnoDB也支持显示锁定,如下所示:
SELECT ... LOCK IN SHARE MODE
SELECT ... FOR UPDATE
MySQL也支持LOCK TABLES 和 UNLOCK TABLES命令,这些命令由MySQL服务器实现,而不是存储引擎.LOCK TABLE命令和事务处理之间的交互是比较复杂的,在某些服务器版本上可能出现一些不可预料的行为,因此,除非是在一个事务中使用LOCK TABLES,同时AUTOCOMMIT模式是被禁止的,否则无论使用何种存储引擎都不要使用LOCK TABLES 命令.
四.多版本并发控制
大多数MySQL的事务性存储引擎,不是简单的使用行加锁机制,而是选用一种叫做多版本并发控制(MVCC)的技术,和行加锁机制关联使用,以应对更多的并发处理问题.以下简单描述InnoDB的简化版的行为方式来说明MVCC的工作原理:
InnoDB通过为每个数据行添加两个隐含值的方式来实现MVCC,这两个隐含值记录了行数据的创建时间和过期时间,每一行都存储了事件发生时的系统版本号用来替代事件发生时的实际时间.每一次开始一个事务,系统版本号会自动增加.每个事务都会保存它在开始时的"当前系统版本"的记录,而每个查询都会根据事务的版本号,检查每行数据的版本号.下面是事务隔离级别设置在REPEATABLE READ时,MVCC的实际操作:
SELECT
InnoDB检查每行数据,确保它们符合两个标准:1.InnoDB只查找版本早于(<=)当前事务版本号的数据,这确保了当前事务读取的数据都是在事务开始前已经存在的,或者是由当前事务创建或修改的;2.数据行的删除版本必须是未定义的,或是大于事务版本的,这保证了事务读取的行在事务开始时是未被删除的.只用通过了上述两个测试才会被当做查询结果返回.
INSERT
InnoDB为每个行记录当前版本号
DELETE
InnoDB为每个删除行记录删除版本号,作为删除标识.
UPDATE
InnoDB为每个需要更新的行建立一个新的行拷贝,并且为新的行拷贝记录当前的系统版本号,同时也为更新前的旧行记录系统的版本号作为旧的删除版本标识.
MVCC只工作在REPEATABLE READ和READ COMMITED两个隔离级
五.MySQL的存储引擎
在文件系统中,MySQL会把每个数据库保存为数据目录下的一个子目录.当创建一个数据表时,MySQL会在一个和表名同名的,以.frm为后缀的文件中存储表的定义.每种存储引擎对表的数据和索引的存储方式有所不同,当表的定义是由MySQL服务器独立处理.
要获知每张表适用何种存储引擎,可以适用命令SHOW TABLE STATUS
SHOW TABLE STATUS LIKE 'table_name';
a.MyISAM引擎
MySQL的默认存储引擎,在性能和可用特征之间,MyISAM提供一种良好的平衡,这些特征包括全文检索、压缩、空间函数.MyISAM不支持事务和行级锁.
存储:
一般来说,MyISAM将每个表存储成两个文件:数据文件和索引文件.两个文件的扩展名分别为.MYD和.MYI,MyISAM的数据文件是平台通用的.
MyISAM表可以包含动态行和静态行(固定长度行),MySQL会根据表定义决定使用何种行数据.MyISAM表的可容纳的行总数一般只限于数据库服务器的磁盘空间大小,以及操作系统允许创建的最大文件大小.
MyISAM特性:
加锁和并发:MyISAM对整张表进行加锁,而不是行.读取程序在读取数据时在所有表上都可以获得共享锁,而写入程序可以获得排他锁.用户在允许select查询时可以在同一张表中插入新行.
自动修复:MySQL支持对MyISAM表的自动检测和自动修复
手工修复:用户可以使用命令CHECK TABLE table_name 和 REPAIR TABLE table_name 检测表错误并修复表错误,当服务器离线时可以使用命令行工具myisamchk检测和修复表.
索引特性:在MyISAM表中,用户可以基于BLOB或TEXT类型列的前500个字符创建相关索引.MyISAM支持全文索引,它可以根据个别单词为复杂的的搜索选项创建相关索引.
延迟更新索引:使用表创建选项DELAY_KEY_WRITE创建表时,在查询结束后不会将索引的改变写入磁盘,而是在内存中的键缓存区缓存索引改变数据,它只会在清理缓存数据或关闭表时才将索引数据转储到磁盘.对于数据经常改变并且使用频繁的表,这种模式大大提高了表的处理能力,不过如果服务器或系统崩溃索引必将损坏,并需要修复
压缩MyISAM表:某些表一旦被创建和填写数据之后,数据将永不改变.这种类型的表非常适合选用压缩的MyISAM表.使用myisampack实用工具可以对表进行压缩,压缩表占有的空间很小使之可以提高更好的处理性能.压缩表也可以拥有索引,但这些索引也是只读的.
b.InnoDB存储引擎
InnoDB专为事务处理设计的一款存储引擎,特别是用于处理大量短期事务,短期事务是指一般能正常完成不需回滚的事务.
InnoDB将数据存储在一个或几个数据文件之中,这种数据文件一般称之为表空间,表空间本质上是一种"黑盒",在"黑盒"内,InnoDB自我管理一切数据.
InnoDB使用MVCC机制获取高并发性能,并且实现了所有四个标准隔离级别,它的默认隔离级是REPEATABLE READ,在这个隔离级上,它使用了间隙锁策略防止幻读的产生,不仅对查询中读取的行进行加锁,而且还对索引结构中的间隙进行加锁,防止幻影插入.
InnoDB表是基于聚族索引建立的,InnoDB的索引结构非常不同于其他大多数MySQL存储引擎,因此它提供了一种非常快速的主键查找性能.不过它的非主键索引也会包含主键列,如果主键定义特别大,其他索引也将和大,如果想在表上定义和多索引则尽量将主键定义小一些,InnoDB不会压缩处理
InnoDB不会根据排序建立索引,而MyISAM支持,因此,当InnoDB加载数据和创建索引时会比MyISAM慢很多,任何改变InnoDB表结构的操作会导致整个表的重建包括重建所有索引.
除了高并发处理能力之外,InnoDB另外一个广为人知的特性是它的外键约束,这个特性是MySQL服务器自身都未能提供的
c.表转换
有几种方法可以将表从一种存储引擎转换成另外一种.
1.ALTER TABLE
ALTER TABLE table_name ENGINE = InnoDB;
这种语法适合所有存储引擎,不过这里有一个陷阱:这种转换会耗费大量时间.MySQL要执行一个旧表到新标的逐行复制.
2.DUMP和IMPORT
3.CREATE和SELECT