高性能MySQL
第一章 MySQL架构
并发控制
有多个查询需要同时修改数据,就会产生并发控制问题。
读写锁:
处理并发 读/写 访问的通常实现一个由两种锁类型组成的锁系统,即共享锁(shared lock| 读锁 | read lock)与排他锁(exclusive lock | 写锁 |write lock)。
锁的概念为:资源上的读锁是共享的,是相互不堵塞的。多个客户可以同时读取同一资源而互不干扰。写锁是排他的,一个写锁即会阻塞读锁也会阻塞其他的写锁。这样可以确保在特定的时间点只有一个客户能执行写入,并防止其他客户读取正在写入的资源。
锁的粒度:
提高共享资源并发性的方式就是让锁定对象更有选择性。理想的方式是只对需要修改的数据片段进行精确的锁定。
MySQL提供了多种存储引擎,而不是单一的通用解决方案。
表锁(table lock):
表锁是MySQL中最基本也是开销 最小的锁策略,它会锁定整张表。当客户端想对表进行写操作(插入,删除,更新等)时,需要先获得一个写锁,这会阻塞其他客户对该表的所有读写操作。只有没人执行写操作时,其他读取的客户才能获取读锁,读锁之间不会相互阻塞。
行级锁(row lock):
使用行级锁可以最大程度地支持并发处理(也带来了最大的锁开销)。每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
事务
事务就是一组SQL语言,作为一个工作单元以原子方式进行处理。(原子性)
ACID是衡量事务的四个特性:
原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency):事务前后数据的完整性必须保持一致。
隔离性(Isolation):事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
事务的隔离等级:
脏读(dirty read):指一个事务读取了另外一个事务未提交的数据。
不可重复读(nonrepeatable read):在一个事务内读取表中的某一行数据,多次读取结果不同。
虚读(幻读 | phantom row):是指在一个事务内读取到了别的事务插入的数据,导致前后读取数量总量不一致。
数据库的隔离级别:
√: 可能出现 ×: 不会出现
隔离级别 | 脏读 | 不可重复读 | 幻读 | 加锁读 |
Read uncommitted(未提交读) | √ | √ | √ | × |
Read committed(提交读) | × | √ | √ | × |
Repeatable read(可重复读) | × | × | √ | × |
Serializable(可串行化) | × | × | × | √ |
死锁
死锁是指两个或多个事务相互持有和请求相同资源上的锁,产生了循环依赖。
当多个事务试图以不同的顺序锁定资源时会导致死锁。当多个事务锁定相同的资源时,也可能发生死锁。
为了解决这个问题,数据库系统实现了各种死锁检测和锁超时机制。InnoDB目前处理死锁的方式是将持有最少行级排他锁的事务回滚。
事务日志
事务日志有助于提高事务的效率。
如果修改操作已经写入事务日志,那么即使系统在数据本身写入硬盘之前发生崩溃,存储引擎仍可以在重新启动时恢复更改。
MySQL中的事务
理解AUTOCOMMIT
在事务中混合使用存储引擎:
MySQL不在服务器层管理事务,事务是由下层的存储引擎实现的。在一个事务中混合使用多种存储引擎是不可靠的。
隐式锁定和显示锁定:
InnoDB使用两阶段锁定协议。在事务执行期间,随时都可以获取锁,但锁只有在提交或回滚后才会释放,并且所有的锁会同时释放。(即隐式锁定);
多版本并发控制(MVCC)
MVCC 可以说是行级锁的一个变种,但是他在很多情况下避免了加锁操作,根据其实现方式,不仅实现了非阻塞的读操作,写操作也只锁定必要的行。
MVCC 的工作原理是使用数据在某个时间点的快照来实现的。无论事务运行多长时间,都可以看到数据的一致视图,也意味着不同的事务可以在同一时间看到同一张表中的不同数据。
InnoDB 通过为每个事务在启动时分配一个事务ID来实现 MVCC。该ID在事务首次读取任何数据时分配。
事务执行回滚的方法:在该事务中修改记录时,将向Undo日志写入一条说明如何恢复该修改的Undo记录,并且事务的回滚指针指向该Undo日志记录。
所有Undo日志也都会写入Redo日志,因为Undo日志写入是服务器崩溃恢过程的一部分,并且是事务性的。
MVCC 仅适用于 REPEATABLE READ(可重复读) 和 READ COMMITTED(提交读) 隔离级别。READ UNCOMMITTED(未提交读)与MVCC不兼容,是因为查询不会读取适合其事务版本的行版本,而是不管怎么读都是最新版本。SERIALZABLE(可串行化)与MVCC不兼容,是因为读取会锁定它们返回的每一行。
复制
MySQL 提供了一种原生方式来将一个节点执行的写操作发到其他节点,即复制。
对于在生产环境中运行的任何数据,都应该使用复制并至少由三个以上的副本,并分布在不同的地区用于灾难恢复计划。
数据文件结构
在8.0版本,MySQL将表的元数据重新设计为一种数据字典,包括在表的 .ibd文件中。这使得表结构上的信息支持事务和原子级数据定义更改。
引入了字典对象缓存(基于最近最少使用(LRU)的内存缓存)来检索表定义和元数据。
InnoDB 引擎
InnoDB是MySQL的默认事务型存储引擎,他是为处理大量短期事务设计的。
- InnoDB是MySQL的默认事务型存储引擎
- InnoDB使用MySQL来实现高并发性。
- InnoDB表是基于聚簇索引构建的。
JSON文档支持
JSON类型在5.7版本被首次引入InnoDB,它实现了JSON文档的自动验证,并优化了存储以允许快速读取。