《高性能MySQL》(第三版)之一:MySQL架构与基础
★MySQL的逻辑架构:
分为三层结构:
- 连接处理、授权认证、安全等内容,非mysql独有。
- Mysql核心功能,比如查询解析、分析、优化、缓存以及所有内置函数,还有跨存储引擎的功能(比如存储过程、触发器、视图)
- 存储引擎,负责数据的存储和提取。服务器和存储引擎【二三层】之间是通过API进行通信的,这些API屏蔽了各个存储引擎之间的差异,这些差异对上层的查询过程透明。不同的存储引擎之间不会互相通信,只简单响应上层服务器的请求。
优化执行
Mysql先解析查询,然后创建内部数据结构(解析树),再进行优化(重写查询、决定表顺序、选择合适索引等)。
查询解析 、 优化 、 执行 的整个过程。
★并发控制
两方面进行控制,一:服务器层 二: 存储引擎层
读写锁:
读锁---共享锁,共享的,不相互阻塞
写锁---排他锁,排他的,
锁粒度:
锁的数据量越少,系统的并发度越高。加锁也会消耗资源,增加系统开销。锁粒度就是在锁的开销 和 数据安全性之间寻求平衡。
Mysql的每种存储引擎都有自己的锁策略和锁粒度。
- 表锁 mysql的最基本锁策略,开销也最小。它会锁定整张表。一个用户在进行增删改的操作时会先获得写锁,这会阻塞其它用户的对该表的读写操作。
- 行级锁,(只在存储引擎层实现,mysql的服务器层没有实现)。可以最大限度的支持并发处理,同时也带来了最大的锁开销、
★事务
ACID 原子性、一致性、隔离性、持久性
原子性:要么全成功,要么全失败,一个事务被视为不可分割的最小单元
一致性:数据库总是从一个一致性的状态转到另外一个一致性的状态。
隔离性:一个事务所做的修改在最终提交之前,对其他事务不可见。
持久性:一旦事务提交,其所做的修改会永久保存到数据库
关于隔离性,就必须要提到隔离级别:
4种隔离级别: 级别从低到高
- 读未提交
事务中的修改,即使没有提交,也对其它事务可见。 导致脏读【即事务可以读取未提交的数据】的问题。 性能一般,还没别的级别的长处,很少使用。
- 读已提交
大多数数据库的默认隔离级别,也叫不可重复读,执行两次同样的查询可能得到的结果不一致。原因是一个事务从开始到提交之前,所做的任何修改都对其他事务不可见。
- 可重复读
解决了脏读的问题,保证了一个事务中多次读取同样的记录结果是一致的,但是会有幻读【即当某个事务在读取某个范围内的记录时,别的事务又在该范围内插入了新记录,当当前事务再次在该范围读取时会产生幻行】问题。InnoDB 通过多版本并发控制MVCC解决了幻读问题。
Mysql的默认隔离级别:可重复读
- 串行化
级别最高,强制事务串行执行,避免了幻读问题。即在读取的每一行数据上都加锁。
死锁问题:
多个事务在同一资源上相互占用,并请求锁定对方占用的资源,导致互相等待对方释放、恶性循环。
解决思路:
1、死锁检测,检测到就会立即返回错误
2、死锁超时机制,当查询时间达到锁等待的超时设定时间后,主动放弃锁请求。
InnoDB的目前处理死锁方式:将持有最少行级排他锁的事务进行回滚(相对简单)。
原因:
- 数据冲突,无解……
- 存储引擎的实现方式导致的
Mysql中的事务
Mysql中支持事务的存储引擎:InnoDB 和 NDB Cluster
Mysql中默认自动提交。有些命令执行前会默认提交当前活动事务(eg: alter table)
Mysql中服务器层不管理事务,事务是由下层的存储引擎实现。所以在同一个事务中使用多种存储引擎不可靠。
★MVCC多版本并发控制
MVCC是一种变相的行级锁,多数情况下避免了加锁操作,开销更低。实现了非阻塞读,写也只锁定必要的行。
版本号。每开始一个新的事务,版本号都会递增。
MVCC只在读已提交 和 可重复读 这两个隔离级别下工作,其他两个不行,因为他们总是读取最新的数据行而不是符合当前版本的数据行。
★MySQL的存储引擎
InnoDB ,mysql的默认存储引擎。优先考虑选择InnoDB
InnoDB的数据存储在表空间中,数据和索引可以分别存放在单独文件中。采用MVCC支持高并发,实现了四个标准的隔离级别,默认可重复读,通过间隙锁策略防止出现幻读问题。【间隙锁是InnoDB不仅锁定查询涉及的行,还能锁定索引的间隙,防止幻影行的插入】。
InnoDB基于聚簇索引,针对主键查询性能很强。二级索引(非主建索引)中必须包含主键列,所以如果主键很大,其他所引都会很大,所以如果表上索引较多,建议主键尽可能的小。
MyISAM 不支持事务和行级锁,崩溃后无法安全恢复。 使用表级锁
MyISAM 压缩表,适用于导入数据后不会再修改,减少磁盘空间占用,减少磁盘I/O ,提升查询性能.
MyISAM最大的问题还是表级锁导致的性能问题。
其他存储引擎暂不细说。