高性能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文档的自动验证,并优化了存储以允许快速读取。