PART ONE:MYSQL的逻辑结构:
Mysql 插件式的存储引擎将查询处理和其他的系统任务以及数据存储提取分离
- 连接层:实现与数据库的连接,比如:JDBC
- 服务层:完成核心服务,缓存查询,sql 分析优化,是否使用索引都在这一层完成
- 引擎层:真正负责Mysql 中数据的存储和提取。不同的存储引擎有不一样的功能,Mysql 中主要使用的是 MyISAM /InnoDB
- 存储层:将数据运行在裸设备的文件系统上,并完成与存储引擎的交互
插件式的设计结构,就使得可以根据需求替换一些“组件”
PART TWO
MySQL 会解析sql 语句,进行优化,然后查询。
一:并发控制:
主要依靠锁
锁不仅控制并发,而且事务的隔离级别也依靠所来实现
MySQL 有自己的锁策略和锁粒度,不同的引擎可以实现自己的锁策略和锁粒度。
锁策略:有共享锁(读锁),排他锁(写锁)
锁粒度可以优化在一些特定场景下的执行效率,提高某些场景下的并发性。
表锁
行级锁:最大可能的提高了并发的性能,但是也是最大的锁开销
二:事务控制:
事务具有:ACID的特性
和锁粒度升级一样,依赖事务的安全性,也会增加系统的工作量,所以在不需要事务的查询类应用中,可以使用非事务引擎以获取更高的性能
隔离级别:
级别越高事务的安全性就越高,但是并发性越低
- read Uncommitted(读取未提交内容):
所有事务都可以看见其他事务未提交的执行结果,也成为脏读。一般不使用 - read cimmitted(读取已提交的数据):
是大多数数据库的默认隔离级别(不是mysql默认的隔离级别),一个事务只能看见已经提交的事务所作的修改 - repeatable Read(可重复读)
这是MySQL默认的隔离级别,确保同一事务的多个实例在并发读取数据能看见同样的数据行(确保事务间的独立性),但是存在的问题为:幻读。幻读是指:当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行(会有不同的结果集)。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。 - Serializable (可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
-
脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
-
不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
-
幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就有几列数据是未查询出来的,如果此时插入和另外一个事务插入的数据,就会报错
死锁:
多个事务对统一资源的竞争,innoDB 解决死锁的方式,将持有最少行级排他锁的事务进行回滚
PART THREE:Mysql
一:Mysql 中的事务
事务依靠锁机制
事务由存储引擎具体实现,Mysql的存储引擎:InnoDB ,MyISAM,一个是事务型一个是非事务性
MySQL 默认自动提交,语句执行完默认自动提交,也可以自己手动的设置数据库的Committed 方式。
显式锁/隐式锁:
InnoDB 采用两阶段锁定协议,在事务执行的过程中,只有committed 和rollback 的时候才会释放锁,InnoDB 会在需要的情况下自动加锁,这是隐式锁。一般不会在数据库中使用显示的锁(直接在语句中 lock tables)
多版本并发控制
Mysql 的大多数事务型存储引擎实现的都不是简单的行级锁。基于并发提升性能的考虑,他们一般都实现了多版本并发控制(MVCC)
不同的存储引擎对MVCC的实现是不一样的,普遍认为MVCC式行级锁的一个变种,但是他在很多情况下避免了加锁的操作,开销变小。虽然实现的机制有所不同,但是大部分都实现了非阻塞的读操作,写操作也只锁定必要的行。
InnoDB 的MVCC实现,通过每行记录后面保存两个隐藏的列来实现,一个列是行的创建时间,一个是行的过期时间(或删除时间)
Mysql 的重复读:其他事务的更新数据不会影响当前事务的查询但是会影响当前事务更新数据
保存的时间并不是真实的时间而是系统版本号,每开始一个事物,系统的版本号就会+1,并且此版本号会作为事务的版本号
二:repeatable read(可重复读) 的情况下MVCC是怎么实现的
- SELECT:
InnoDB 只会查找版本号早于当前版本号的数据行,这样查找的数据要么是当前事务自己修改的要么是之前的事务修改完成的。并且行的删除版本号要么未定义,要么大于当前的事务的版本号,保证在当前事务开始之前数据行是存在的。 - INSERT :
保存当前系统版本号作为行的版本号 - DELETE:
保存当前系统版本号为删除版本号 - UPDATE:
保存当前版本号为行的版本号,并保存当前系统版本号到原来的数据行作为删除时间标志
三:Mysql的存储引擎:
主要是InnoDB ,MyISAM
- InnoDB : 是当前流行的事务存储引擎,有点主要在于事务和并发处理。
InnoDB 将表数据由一个黑盒子管理,InnoDB 将每个表的数据由一系列数据文件组成。
InnoDB 采用MVCC来支持高并发,并且实现了四个隔离级别,默认级别是可重复读,并通过间隙锁来防止幻读对的出现 - MyISAM 是非事务型存储引擎,没有行级锁,只能对整张表加锁,在读取时会对整张表加共享锁,在写数据时会对整张表加排他锁。