Mysql架构

1. 逻辑架构

Mysql逻辑架构

  • 最上层(客户端)不是MySQL特有的,所有基于网络的C/S的网络应用程序都应该包括连接处理、认证、安全管理等
  • 中间层是MySQL的核心,包括查询解析、分析、优化和缓存以及所有的内置函数(日期、时间、数学和加密函数)等.同时它还提供跨存储引擎的功能: 存储过程、触发器、视图等
  • 最下层是存储引擎,它负责存取数据.服务器通过storage engine API可以和各种存储引擎进行交互

2.并发控制

MySQL提供两个级别的并发控制:服务器级(the server level)和存储引擎级(the storage engine level).

加锁是实现并发控制的基本方法,常见的有两种类型的锁

  • 共享锁(shared lock), 或称 读锁(read lock)
  • 排他锁(exclusive lock), 或称 写锁(write lock), 写锁比读锁有更高的优先级

MySQL中锁的策略(粒度):

  • 表级锁(table lock):MySQL独立于存储引擎提供表锁,例如,对于ALTER TABLE语句,服务器提供表锁(table-level lock).
  • 行级锁(row lock):InnoDB和Falcon存储引擎提供行级锁,此外,BDB支持页级锁.InnoDB的并发控制机制.

另外,值得一提的是,MySQL的一些存储引擎(如InnoDB、BDB)除了使用封锁机制外,还同时结合MVCC机制,即多版本两阶段封锁协议(Multiversion two-phrase locking protocal),来实现事务的并发控制,从而使得只读事务不用等待锁,提高了事务的并发性.

3.事务

事务的ACID特性

  • 原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行.
  • 一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态.这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的.
  • 隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行.这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然.
  • 持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持.

四种事务隔离级别

隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read) 加锁读
未提交读(Read uncommitted) 可能 可能 可能 不可能
已提交读(Read committed) 不可能 可能 可能 不可能
可重复读(Repeatable read) 不可能 不可能 可能 不可能
可串行化(Serializable) 不可能 不可能 不可能 可能
  • 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
  • 提交读(Read Committed):只能读取到已经提交的数据.Oracle等多数数据库默认都是该级别 (不重复读)
  • 可重复读(Repeated Read):可重复读.在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别.在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读. InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC, Multiversion Concurrency Control)解决了欢读问题.可重复读是MySQL的默认事务隔离级别.
  • 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

死锁

死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象. InnoDB目前处理死锁的方法是, 将持有最少行级排他锁的事务进行回滚(只是相对比较简单的死锁回滚算法).

4.多版本并发控制

MVCC 的实现,是通过保存数据在某个时间的点的快照来实现的.典型的有乐观(optimistic)并发控制和悲观(pessimistic)并发控制, 通过InnoDB的简化版来说明MVCC是如何工作的.

InnoDB的MVCC, 是通过在每行记录后面保存两个隐藏的列来实现.这两个列, 一个保存了行的创建时间, 一个保存行的过期时间(或删除时间),实际存储是是系统版本号.每开始一个新的事务,系统版本号都会自动递增.事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较.

SELECT InnoDB 会根据一下两个条件检查每行记录:

  • InnoDB只查找版本早于当前事务版本的行数据(也就是,行的系统版本号小于或者等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的
  • 行的删除版本要么未定义,要么大于当前事务版本号.这可以确保事务读取到的行,在事务开始前未被删除

INSERT InnoDB为新插入的每一行保存当前系统版本号作为行版本号

DELETE InnoDB为删除的每一行保存当前系统版本号作为行删除标识

UPDATE InnoDB为插入一行新纪录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识

MVCC只在 Read committed 和 Repeatable read 两个隔离级别下工作,其它两个隔离级别都和MVCC不兼容.

5.间隙锁(Next-Key锁)

间隙锁只会阻塞insert操作,对于delete和update操作是不会阻塞的

当我们使用范围条件而不是相等条件来检索数据,并请求共享或排它锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,就叫做"间隙(GAP)",InnoDB也会对这个间隙加锁,这种锁机制就是所谓的间隙锁.(Next-Key锁)

比如id>100,但数据的id只有101,但也会对102,103等间隙加锁.

InnoDB使用间隙锁的目的,一方面是为了防止幻读,以满足相关隔离级别的要求.对于上面的例子,要是不使用间隙锁,如果其他事务插入了id大于100的新记录,就会产生幻读.另一方面,是为了满足其恢复和复制的需要.

很显然,范围条件检索并锁定记录,这时的并发插入会造成严重的锁等待.因此,实际开发中,并发插入较多的应用,要尽量优化逻辑,尽量使用相等条件也访问更新数据,避免使用范围条件.

注意: 如果相等条件请求是给一个不存在的记录加锁,InnoDB也会使用间隙锁!

6.存储引擎

InnoDB InnoDB是一个高性能的事务存储引擎 存储表和索引有两种方式:

  • 共享表空间存储: 这种方式下,表的定义位于.frm文件中,数据和索引保存在innodb_data_home_dir和innodb_data_file_path指定的表空间中
  • 多表空间存储: 表的定义仍位于.frm文件,但是,每个InnoDB表和它的索引在它自己的文件(.idb)中,每个表有它自己的表空间

InnoDB采用MVCC来支持高明发, 并且实现了四个标准的隔离级别. 默认级别是 REPEATABLE READ(可重复度),并且通过间隙锁(next-key locking)策略防止幻读的出现.

MyISAM 特性

  • 锁与并发性: MyISAM只有表级锁,不支持行级锁.所以不适合于大量的写操作,但是它支持并发插入(concurrent inserts),这是一个非常重要且有用的特性
  • 自动修复: MySQL支持自动检查和修复MyISAM表
  • 手动修复: 你可以使用CHECK TABLE检查表的状态,并用REPAIR TABLE修复表
  • 索引: 你可以为BLOB和TEXT的前500个字符创建索引.而且,MyISAM还支持全文索引,但仅限于CHAR、VARCHAR、和TEXT列
  • 延迟键写(Delayed key writes): 如果创建MyISAM表时指定DELAY_KEY_WRITE,MySQL在查询结束时,不会将改变的索引数据写入磁盘,而将修改保存在key buffer中.只有要改变缓存或者关闭表时,才会把索引数据刷入磁盘

MyISAM最典型的性能问题还是表锁的问题, 如果发现所有查询都长期处于"Locked"状态,那毫无疑问表锁就是罪魁祸首.

其它存储引擎

  • Archive: 只支持INSERT 和 SELECT 操作
  • Blackhole: 没有实现任何存储机制, 丢弃所有插入数据, 只在一些特殊的复制架构和日志审核时发挥作用
  • CSV: 处理CSV文件,把CSV文件当作表处理
  • Federated、Memory、Merge、NDB等

results matching ""

    No results matching ""