高性能MySQL(第四版)阅读整理
第一章
1.MySQL的最上层客户端所包含的服务不是MySQL所独有的,大多数基于网络的客户端/服务器工具或服务器都有类似的服务,包括连接处理、身份验证、确保安全等。、
MySQL逻辑架构
2.所有跨存储引擎的功能在MySQL核心层(下图框起来的)实现:存储过程、触发器、视图等。
3.存储引擎不会去解析SQL,不同的存储引擎之间也不会互相通信,只是简单地相应服务器的请求
4.服务器维护了一个缓存区,用于存放已就绪的线程,因此不需要为每个新的连接创建或者销毁进程
5.当客户端连接到MySQL服务器时,需要进行身份验证,连接成功后服务器会继续验证该客户端是否具有其发出的每个查询的权限
6.MySQL解析查询以创建内部数据结构(解析树),优化器并不关心表使用的是什么存储引擎,但存储引擎对于查询优化是有影响的。随着并发性的增加,查询缓存成为一个让人诟病的瓶颈。从MySQL5.7.20版本开始,被官方逐渐弃用和移除。
并发控制
7.并发控制这一经典问题的解决方案相当简单。通常使用共享锁(shared lock)和排它锁(exclusive lock),也叫读锁和写锁。一个写锁既会阻塞读锁也会阻塞其他的写锁。
8.表锁:table lock是MySQL中最基本且开销最小的锁策略。
行级锁:row lock可以最大程度地支持并发处理,当然其锁开销也是最大的。
锁的实现是在存储引擎中而非服务器,服务器通常不清楚锁的实现方式
事务
9.事务是一组满足ACID特性的SQL语句,是一个一原子方式进行处理的工作单元,不可分割。这组语句要么全部执行成功,要么全部执行失败。
事务的ACID特性分别为:A原子性(atomicity)、C一致性(consistency)、I隔离性(isolation)、D持久性(durability),除非系统通过严格的ACID测试,否则空谈事务概念是不够的。
数据库总是从一个一致性状态转换到下一个一致性状态。一旦提交,事务所做的修改就会被永久保存到数据库中。此时即使系统崩溃,数据也不会丢失。
可以用START TRANSACTION语句启动事务,用COMMIT提交事务将修改的数据持久保留,用ROLLBACK撤销所有的修改。
然而不可能存在100%的持久性保障(如果数据库本身就能做到真正的持久性,那么备份又怎能增加持久性呢)
10.隔离级别通常采用ANSI SQL通用标准,该通用标准的目标是定义在事务内外可见和不可见的更改的规则。较低的隔离级别通常允许更高的 并发性,并且开销越低
该通用标准定义了四种隔离级别:
1.READ UNCOMMITTED(未提交读)
从性能上来说,READ UNCOMMITTED不会比其他级别好太多,却缺乏其他级别的很多好处,除非有非常必要的理由,在实际应用中一般很少使用。
读取未提交的数据,也称为脏读(dirty read)。
2.READ COMMITTED(提交读)
大多数数据库系统的默认隔离级别是READ COMMITTED(但MySQL不是)。一个事务可以看到其他事务在它开始之后提交的修改,但在该事务提交之前,其所做的任何修改对其他事务都是不可见的。这个级别仍然允许不可重复读(nonrepeatable read),这意味着同一事务中两次执行相同语句,可能会看到不同的数据结果。
3.REPEATABLE READ(可重复读)
解决了READ COMMITTED级别的不可重复读问题。但该级别会产生幻读,所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(phantom row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。
4.SERIALIZABLE(可串行化)
是最高的隔离级别。通过强制事务按序执行,使不同事务之间不可能产生冲突,从而解决了前面说的幻读问题。实际应用中很少用到这个隔离级别,除非需要严格确保数据安全且可以接受并发性能下降的结果。
11.死锁。为了解决这个问题,数据库系统实现了各种死锁检测和锁超时机制。InnoDB目前处理死锁的方式是将持有最少行级排他锁的事务回滚(这是一种最容易回滚的近似算法)。
一旦发生死锁,如果不回滚其中一个事务(部分或全部),就无法打破死锁。对于事务型的系统,这是无法避免的。大多数情况下只需要重新从头开始执行被回滚的事务即可,除非又遇到另一个死锁。
12.事务日志:存储引擎只需要更改内存中的数据副本,而不用每次修改磁盘中的表,这会非常快。然后再把更改的记录写入事务日志中,事务日志会被持久化保存在硬盘上。因为事务日志采用的是追加写操作,只是在硬盘中一小块区域内的顺序I/O,所以写入事务日志是一种相对较快的操作。最后会有一个后台进程在某个时间去更新硬盘中的表。因此,大多数使用这种技术(write-ahead logging,预写式日志)的存储引擎修改数据最终需要写入磁盘两次。
13.MySQL中的事务:存储引擎是驱动如何从硬盘中存储和检索数据的软件。
默认情况下,单个INSERT、UPDATE或DELETE语句会被隐式包装在一个事务中并在执行成功后立即提交,这称为自动提交(AUTOCOMMIT)模式。通过禁用此模式,可以在事务中执行一系列语句,并在结束时执行COMMIT提交事务或ROLLBACK回滚事务。
此外,当启用AUTOCOMMIT时,也可以使用关键字BEGIN或者START TRANSACTION来开始一个多语句的事务。
MySQL可以通过执行SET TRANSACTION ISOLATION LEVEL命令来设置隔离级别。建议最好在服务器级别设置最常用的隔离,并且只在显式情况下修改。
在同一个事务中,混合使用多种存储引擎是不可靠的,不惜一切代价避免在应用中混合使用存储引擎是非常重要的。
InnoDB使用两阶段锁定协议(two-phase locking protocol)。在事务执行期间,随时都可以获取锁,但锁只有在提交或回滚后才会释放,并且所有的锁会同时释放。InnoDB会根据隔离级别自动处理锁。
MySQL还支持LOCK TABLES和UNLOCK TABLES命令,这些命令在服务器级别而不在存储引擎中实现。如果需要事务,应该使用支持事务的存储引擎。因为InnoDB支持行级锁,所以没必要使用LOCK TABLES。
-
多版本并发控制(MVCC,Multiversion Concurrency Control),可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。根据其实现方式,不仅实现了非阻塞的读操作,写操作也只锁定必要的行。其工作原理是使用数据在某个时间点的快照来实现的。这意味着,无论事务运行多长时间,都可以看到数据的一致视图,也意味着不同的事务可以在同一时间看到同一张表中的不同数据