高性能MySQL读书笔记(第一章MySQL架构与历史)
MySQL逻辑架构
先上图
服务器负责客户端认证和连接以及查询优化;
存储引擎负责数据的存储与提取;
MySQL最与众不同的特性是它的的存储引擎架构,将查询处理及系统任务与数据存储/提取相分离,MySQL服务器与存储引擎通过api方式通信。用户可以根据实际应用场景,选择最优的存储引擎,这也体现了MySQL的灵活。
并发控制
什么是并发?
多个进程或者线程同时对一个资源进程操作,导致数据与预期不一致或错乱。书中通过Unix系统email box为例,两个进程同时对一个邮箱投递邮件,会导致原本首尾衔接的邮件出现错位。
引入锁的概念解决并发问题
两种类型的锁
共享锁(读锁):读锁不阻塞其他读锁操作。
排它锁(写锁):写锁会阻塞其他的写锁和读锁。
MySQL锁的内部管理是透明的,也就是客户端不感知。
锁粒度
表锁和行级锁
事务
事务是一组原子性的sql操作,是一个独立的工作单元,要么全部执行完成,要不执行失败回滚所有操作。
提到事务,必须了解4个标准特性(ACID)
- 原子性(atomicity)
- 一致性(consistency)
说说一致性的理解,在一个事务执行前,数据库处于一个一致的状态A,假如该事务执行成功,数据库会进入另外一个一致性的状态B。事务执行后,要么成功进入状态B,要么失败回滚到状态A,不存在处于一个A和B之间的状态。 - 隔离性(isolation)
一个事务提交前所做的修改,对于其他事务一般是不可见的。隔离性,由数据库的隔离级别来决定。 - 持久性(durability)
事务一旦提交,所做的修改将永久保存到数据库中。
4种隔离级别
定义:隔离级别定义了一个事务所做的修改,哪些在事务内和事务间可见,哪些是不可见的。
- Read Uncommitted(未提交读)
事务所做的修改,在提交前对于其他事务可见,会造成读取到未提交的数据,也就是脏读。 - Read Committed(提交读)
事务所做的修改,在提交前对于其他事务不可见,可避免脏读。但是会引入新的问题不可重复读。
那么什么是不可重复读?事务A开始,读取一块数据,多次读取的结果集可能不一致。原因也很好理解,因为这个级别的隔离,事务所做的修改仅仅对其他事务不可见,但是自身事务是可见的,如果读取数据A,然后自身事务修改了数据A,再次读取是就会造成两次读取的结果集不一致。 - Repeatable Read(可重复读) mysql默认的隔离级别
该级别保证了在同一个事务中,多次读取统一的记录的结果集是一致的,也就是解决了不可重复读的问题。但无法避免另外一个问题幻读。
那么什么是幻读?这个比较难理解,简单理解就是,此级别保证了多次读取一块数据集的结果一致性,但有时候会因为其他事务的操作导致读取结果不一致,与预期不一致,就像产生了幻觉,所有成为幻读。
那么问题来了,此隔离级别不是已经保证了多次读取的一致性吗?难道是骗人的???
结果肯定不是的,我也不是很理解,简单说下自己的理解,如有不妥还望指正! 此类隔离级别,保证了自己修改对自身事务可见,在多次读取同一块数据时会进行一些额外的处理来保证数据的一致性,但是该事务不能保证其他事务(已提交的事务)对该数据块的修改,因为该事务读取这块数据后,锁会释放,其他事务就可以进行修改,然后当该事务再次读取时就会出现幻读。这是简单的理解,后面有介绍间隙锁可以有助于理解幻读。 - Serializable(可串行化)
一句话:强制事务串行执行,不存在并发。
另附刘大的《数据库村的旺财和小强》, 传送,通俗易懂,有趣有料!
多版本并发控制(MVCC)
出现的原因:
因为加锁在并发是存在阻塞,效率较低。所以提出里MVCC,通过减少加锁操作来提升数据库性能。
实现的思路
通过保存数据在某个时间点的快照来实现。
理解:将一个数据在事务处理前后都保存快照,根据事务的开始时间,来找到对于时间点版本的数据,然后处理。避免了加锁操作,但是增加了存储的数据量,所有是一个以空间换时间的实现方式。
MySQL存储引擎
默认事务型存储引擎InnoDB,没有特殊需求95%的情况推荐使用!
优点
- 采用MVCC支持高并发
默认隔离级别是可重复读,并且通过间隙锁策略防止幻读。间隙锁使得InnoDB不仅仅锁定查询设计的行,还会对于索引中的间隙进行锁定,以防止幻影行的插入。
- 数据存储格式可以跨平台
- 支持热备份