读高性能MySQL(第4版)笔记01_MySQL架构(上)
1. 逻辑架构
1.1. 大多数基于网络的客户端/服务器工具或服务器都有类似的服务
1.1.1. 连接处理
1.1.2. 身份验证
1.1.3. 确保安全性
1.2. 核心层
1.2.1. 查询解析、分析、优化、以及所有的内置函数
1.2.2. 跨存储引擎的功能
1.2.2.1. 存储过程
1.2.2.2. 触发器
1.2.2.3. 视图
1.3. 存储引擎层
1.3.1. 存储引擎负责MySQL中数据的存储和提取
1.3.2. 和GNU/Linux下的各种文件系统一样,每种存储引擎都有其优势和劣势
1.3.3. 优化器并不关心表使用的是什么存储引擎,但存储引擎对于查询优化是有影响的
2. 查询缓存
2.1. query cache
2.2. 随着并发性的增加,查询缓存成为一个让人诟病的瓶颈
2.3. MySQL 5.7.20版本开始,查询缓存已经被官方标注为被弃用的特性
2.4. 在8.0版本中被完全移除
2.5. 缓存被频繁请求的结果集依然是一个很好的实践
2.5.1. 一个流行的设计模式是在memcached或Redis中缓存数据
3. 并发控制
3.1. 只要有多个查询需要同时修改数据,就会产生并发控制问题
3.2. 并发控制的级别
3.2.1. 服务器级别
3.2.2. 存储引擎级别
3.3. 读写锁
3.3.1. 从电子表格中读取数据不会有什么麻烦,即使很多人同时读取也不会有问题
3.3.2. 读锁(read lock)
3.3.2.1. 共享锁(shared lock)
3.3.2.2. 资源上的读锁是共享的,或者说是相互不阻塞的
3.3.3. 写锁(write lock)
3.3.3.1. 排他锁(exclusive lock)
3.3.3.2. 写锁则是排他的,也就是说,一个写锁既会阻塞读锁也会阻塞其他的写锁
3.3.3.3. 只有这样才能确保在特定的时间点只有一个客户端能执行写入,并防止其他客户端读取正在写入的资源
3.3.3.3.1. 这是出于安全策略的考虑
3.3.4. 处理并发读/写访问的系统通常实现一个由两种锁类型组成的锁系统
3.3.5. 在实际的数据库系统中,每时每刻都在发生锁定
3.3.6. 如果数据库服务器以可接受的方式执行,锁的管理速度足够快,那么不会引起客户端的感知
3.3.7. 锁是数据库实现一致性保证的方法
3.4. 锁的粒度
3.4.1. 一种提高共享资源并发性的方式就是让锁定对象更有选择性
3.4.2. 尽量只锁定包含需要修改的部分数据,而不是所有的资源
3.4.3. 只对需要修改的数据片段进行精确的锁定
3.4.4. 让锁定的数据量最小化,理论上就能保证在给定资源上同时进行更改操作,只要被修改的数据彼此不冲突即可
3.4.5. 如果系统花费大量的时间来管理锁,而不是存取数据,那么系统的性能可能会受影响
3.5. 锁策略
3.5.1. 锁定策略是锁开销和数据安全性之间的平衡,这种平衡会影响性能
3.5.2. 表锁(table lock)
3.5.2.1. MySQL中最基本也是开销最小的锁策略
3.5.2.2. 它会锁定整张表
3.5.2.2.1. 只有没有人执行写操作时,其他读取的客户端才能获得读锁,读锁之间不会相互阻塞
3.5.2.3. 写锁队列和读锁队列是分开的,但写锁队列的优先级绝对高于读队列
3.5.3. 行级锁(row lock)
3.5.3.1. 行级锁是在存储引擎而不是服务器中实现的
3.5.3.2. 可以最大程度地支持并发处理(也带来了最大的锁开销)
3.5.3.3. 允许多人同时编辑不同的行,而不会阻塞彼此
3.5.3.4. 一般都是在表中施加行级锁(row level lock),为了在锁比较多的情况下尽可能地提供更好的性能,锁的实现方式非常复杂
3.5.3.5. 服务器可以执行更多的并发写操作
3.5.3.6. 代价是需要承担更多开销
3.5.3.6.1. 跟踪谁拥有这些行级锁
3.5.3.6.2. 已经锁定了多长时间
3.5.3.6.3. 行级锁的类型
3.5.3.6.4. 何时该清理不再需要的行级锁
4. 事务
4.1. 事务就是一组SQL语句,作为一个工作单元以原子方式进行处理
4.2. 作为事务的一组语句,要么全部执行成功,要么全部执行失败
4.3. 存在高度复杂且缓慢的两阶段提交系统的典型原因
4.3.1. 为了应对各种失败场景
4.3.1.1. 连接可能会断开
4.3.1.2. 会超时
4.3.1.3. 数据库服务器在操作执行过程中会崩溃
4.4. ACID
4.4.1. 原子性(atomicity)
4.4.1.1. 一个事务必须被视为一个不可分割的工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚
4.4.2. 一致性(consistency)
4.4.2.1. 数据库总是从一个一致性状态转换到下一个一致性状态
4.4.3. 隔离性(isolation)
4.4.3.1. 一个事务所做的修改在最终提交以前,对其他事务是不可见的,这就是隔离性带来的结果
4.4.4. 持久性(durability)
4.4.4.1. 一旦提交,事务所做的修改就会被永久保存到数据库中
4.4.4.2. 不可能有100%的持久性保障
4.4.4.3. 如果数据库本身就能做到真正的持久性,那么备份又怎么能增加持久性?
4.4.5. ACID事务和InnoDB引擎提供的保证是MySQL中最强大、最成熟的特性之一
4.4.6. 除非系统通过严格的ACID测试,否则空谈事务的概念是不够的
4.5. 隔离级别
4.5.1. READ UNCOMMITTED(未提交读)
4.5.1.1. 在事务中可以查看其他事务中还没有提交的修改
4.5.1.2. 从性能上来说,READ UNCOMMITTED不会比其他级别好太多,却缺乏其他级别的很多好处
4.5.1.3. 在实际应用中一般很少使用
4.5.1.4. 读取未提交的数据,也称为脏读(dirty read)
4.5.2. READ COMMITTED(提交读)
4.5.2.1. 大多数数据库系统的默认隔离级别是READ COMMITTED
4.5.2.1.1. MySQL不是
4.5.2.2. 一个事务可以看到其他事务在它开始之后提交的修改
4.5.2.3. 在该事务提交之前,其所做的任何修改对其他事务都是不可见的
4.5.2.4. 允许不可重复读(nonrepeatable read)
4.5.2.4.1. 这意味着同一事务中两次执行相同语句,可能会看到不同的数据结果
4.5.3. REPEATABLE READ(可重复读)
4.5.3.1. MySQL默认的事务隔离级别
4.5.3.2. 保证了在同一个事务中多次读取相同行数据的结果是一样的
4.5.3.3. 无法解决另外一个幻读(phantom read)
4.5.3.4. 幻读指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(phantom row)
4.5.3.5. InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题
4.5.4. SERIALIZABLE(可串行化)
4.5.4.1. 最高的隔离级别
4.5.4.2. 通过强制事务按序执行,使不同事务之间不可能产生冲突,从而解决了幻读问题
4.5.4.3. 实际应用中很少用到这个隔离级别,除非需要严格确保数据安全且可以接受并发性能下降的结果
4.5.5. 隔离级别之间的利与弊
5. 死锁
5.1. 两个或多个事务相互持有和请求相同资源上的锁,产生了循环依赖
5.2. InnoDB存储引擎,检测到循环依赖后会立即返回一个错误信息
5.2.1. 死锁将表现为非常缓慢的查询
5.3. 一旦发生死锁,如果不回滚其中一个事务(部分或全部),就无法打破死锁
5.4. InnoDB目前处理死锁的方式是将持有最少行级排他锁的事务回滚
5.4.1. 这是一种最容易回滚的近似算法
5.5. 死锁的产生有双重原因
5.5.1. 真正的数据冲突,这种情况通常很难避免
5.5.2. 完全是由于存储引擎的实现方式导致的
热门相关:峡谷正能量 异世修真邪君 异世修真邪君 拒嫁豪门,前妻太抢手 本法官萌萌哒