MySQL架构
MySQL逻辑架构
1.基本说明
如图所示为,其中大致可以分为三层。
第一层:连接/线程处理,该部分主要是来处理连接,授权认证,安全等。
第二层:缓存,解释器,优化器,该部分是mysql比较核心的的功能模块,包含查询解析,分析,优化,缓存以及所有的内置函数,存储过程,触发器,视图等。
第三层:存储引擎,主要负责mysql中数据的存储和提取,服务通过API和存储引擎进行通信,优势就是屏蔽了各存储引擎之间的差异。
2.架构优势分析
该种利用API区屏蔽个存储引擎之间差异的架构模式,使mysql能跟据不同业务场景,不同数据标准等要求能灵活的选用不同的存储引擎从而最大限度的提升存储性能。
并发控制
1.概述
当多个连接在同一时刻对同一数据进行修改就会引发并发控制问题。mysql在两个层面来解决并发控制问题,一个是服务层另一个是存储引擎层。
2.读写锁
读锁:也叫共享锁,当多个连接对同一个数据进行读取的时候是互不影响的;
写锁:也叫排差锁,一个写锁会阻塞其它写锁和读锁。
3.锁的粒度
锁定粒度一般指锁具体锁住的范围大小,对于锁来说锁住的范围越小则数据库并发性能就会越高,当然锁的各种操作也是十分耗费cpu资源的,例如获取锁,检查锁,释放锁等。
在日常使用中正确的根据业务来选择锁粒度,也就是在锁的开销(性能)和数据安全(安全)之间寻求平衡
3.1表锁
表锁是一种开销比较小的锁策略,类似于当修改某张表中的数据时,将该张表加锁,此时其它连接无法操作该张表。
3.2行级锁
行级锁可以最大程度上的支持并发处理,但同时也带来了最大的锁的开销。行级锁均在存储引擎中实现,不同的存储引擎对自己的锁机制实现都不一样。
事务
1.概述
事务在数据库中是一个十分重要的概念,在一个事务中的语句不论何时都只有两种情况,要么全部成功,要么全部失败。
2.ACID
一个良好的事务系统要具备
A(atomicity)
原子性:一个事务是被视为一个最小的不可分割的工作单元,要么全部提交成功,要么全部提交失败回滚。
C(consistency)
一致性:只要事务没有提交成功,事务中所作的修改就不能真正的存储到数据库中。
I(isolation)
隔离性:通常来说,一个事务还未提交对于其它正在执行的事务来说是不可见的。
D(durability)
持久性:一旦事务提交成功该事务中操作的数据就应该持久化到数据库中。
现实情况下一个数据库系统要具备ACID所有特性是非常困难以及复杂的,几乎是一个不可能完成的任务。
跟锁的粒度越小锁的开销就会越大一样,要完全解决事务的安全性就要付出很大的代价,所以对于事务ACID的把控也是一种性能和安全上的权衡。
3.隔离级别
3.1概述
与隔离性对应的实现是隔离级别,SQL规范中定义了四种隔离级别,较低级别的隔离性通常可以执行更高的并发,系统开销也更低。
3.2四种隔离级别
READ UNCOMMITTED(未提交读)
该级别中当A事务正在执行还未提交时,其它事务是可以看到A事务修改的内容的,该种级别下会导致很多问题例如脏读,不可重复度,幻读问题。
READ COMMITTED(提交读)
该级别下A事务正在执行还未提交时,对于其它事务来说是看不到A事务修改的内容的,这个级别也叫不可重复读,因为两次执行同样的查询可能会得到不一样的结果。(大多数数据库都是该隔离级别)
REPEATABLE READ(可重复读)
该级别中解决了提交读中的不可重复读的问题,使的在一个事务中多次读取同样记录结果是一致的。但是还是可能会产生幻读的问题,对于幻读MySQL采用多版本控制(mvcc)来解决。(mysql默认隔离级别)
SERIALIZABLE(可串行化)
是隔离级别中最高的一种,它是通过强制事务串行化执行,简单来说就是对读取的每一行数据都加锁,所以会导致大量超时和锁竞争等问题。一般不采用该级别除非非常要确保数据一致性而且可以接受没有并发情况下。
3.3死锁
多个连接互相锁着对方需要的资源而去等待对方锁住的资源的现象,导致两个连接都堵塞不能继续往下走。InnoDB引擎实现了各种死锁检测和死锁超时机制来检查死锁问题并外部干预解决。
锁的行为和顺序和存储引擎有关,同样的顺序执行的SQL在不同的存储引擎上有的可能会产生死锁有的可能就不会,除非一些是真正的因为数据冲突这种情况是难以避免的,所以某些死锁也可能是由于存储引擎实现方式导致的。
3.4事务日志
问题并外部干预解决。
锁的行为和顺序和存储引擎有关,同样的顺序执行的SQL在不同的存储引擎上有的可能会产生死锁有的可能就不会,除非一些是真正的因为数据冲突这种情况是难以避免的,所以某些死锁也可能是由于存储引擎实现方式导致的。
3.4事务日志
数据库通过事务日志可以大大提高事务的执行效率,事务日志实质上就是将提交的事务以日志的格式追加到磁盘中某个特定的连续区域,然后内存中修改的数据在慢慢在后台刷新到磁盘中。这样可以避免在提交事务时磁头不断寻找位置I/O操作导致性能浪费,事务日志则是一块固定的区域,不需要频繁移动磁头,如果因为某些原因导致内存中修改的数据还没有写入磁盘,在下次启动之后也能通过事务日志来恢复,避免数据丢失问题。此种方式称为预写式日志,修改时需写两次磁盘。