文章目录

  • 高性能mysql
  • 一、Mysql架构及历史
  • 1.1 连接管理与安全性
  • 1.2 优化与执行
  • 二、并发控制
  • 2.1 读写锁
  • 2.2 锁颗粒度
  • 三、事务
  • 3.1 ACID
  • 3.2 隔离级别
  • 3.3 死锁
  • 3.4 事务日志
  • checkpoint机制(内存中被修改的数据啥时候同步到磁盘)
  • 3.5、mysql中的事务
  • 3.6 多版本并发控制(行锁的变种,目的:提高并发)
  • 例子
  • 四、 MySQL的存储引擎


高性能mysql

一、Mysql架构及历史

高性能mysql试读 高性能 mysql_存储引擎

存储引擎负责数据的存储和读取,mysql服务器通过API和存储引擎通信,存储引擎有几十个底层函数,如开始一个事务,根据主键读取一条记录等,存储引擎不会解析SQL(InnoDB外键除外),不同存储引擎间不会通信,只是简单响应上层服务器的请求。

mysql可以使用多个存储引擎,表的引擎可能会不同。

1.1 连接管理与安全性

每个客户连接都会在服务器进程中拥有一个线程,这个线程的查询只会在这个单独的线程中执行,该线程只能轮流在某个cpu核心或cpu中执行,服务器负责缓存线程,不需要为每个新建连接创建或销毁线程。

1.2 优化与执行

MySQL负责解析查询,创建解析树,然后对解析树进行各种优化,包括重写查询,决定表的读取顺序以及选择合适的索引,用户可以用hint关键字提示优化器影响优化器决策,可以请求优化器解释优化过程的各个因素,知道服务器是如何进行优化决策的。
优化器不关心使用的是什么存储引擎,优化器会请求存储引擎提供有多少数据或某个操作的开销信息、表数据的统计信息等。
对于select语句,在解析查询之前,会先检查缓存,如果能找到对应查询,就不再执行查询解析、优化和执行过程。

二、并发控制

2.1 读写锁

共享锁(读锁)share lock和排他锁(写死锁)exclusive lock

2.2 锁颗粒度

高性能mysql试读 高性能 mysql_高性能mysql试读_02


开销:加锁速度、死锁、粒度、并发性能

表锁:开销小,加锁快;不会出现死锁;锁定粒度大,并发度最低,服务层也会使用表锁,如Alter table

行锁:开销大,加锁慢;会出现死锁;锁定粒度小,并发度高,存储引擎实现,服务层没有实现。

页锁:开销和加锁速度介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般

三、事务

InnoDB支持、MyISAM不支持

3.1 ACID

  • 原子性(atomicity)一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。
  • 一致性(consistency)数据库总是从一个一致性的状态转换到另外一个一致性的状态。
  • 隔离性(isolation)通常,一个事务所做的修改在最终提交以前,对其他事务是不可见的。当然这里涉及到隔离级别的问题,不是所有的隔离级别都满足。
  • 持久性(durability)一旦事务提交,则其所作的修改就会永久保存到数据库中。

3.2 隔离级别

四种,每种规定了事务中所作的修改,较低的隔离可以执行更高的并发、开销也更低

  • READ UNCOMMITTED未提交读,事务中的修改即使没有提交,对其他事务也是可见的;事务读取未提交的数据:脏读;很少使用
  • READ COMMITTED提交读,大多数数据库的默认隔离级别,非MySQL;事务从开始到结束只看见已提交的事务所作的修改,本身所做的修改对其他事务不可见;不可重复读:两次执行同样的查询,结果可能不一样(其他事务的修改)
  • REPEATABLE READ可重复读:通过多版本并发控制(MVCC)控制,MySQL默认,解决了脏读,同一事务多次读同样结果;幻读:当某个事务在读取某个范围内的记录时、另一个事务在该范围内插入新的记录,当前事务再次读取该范围记录、幻行
  • SERIALIZABLE:可串行化,最高,强制事务串行执行,避免幻读问题,读取每行数据时加锁(可导致大量超时和锁争用),很少使用

mysql默认存储引擎:可重复读。

高性能mysql试读 高性能 mysql_隔离级别_03

3.3 死锁

  • 两个多个事务在同一个资源上相互占用并请求锁定对方占用的资源;
  • 多个事务试图以不同的顺序锁定资源,可能产生死锁;

InnoDB的处理方法:将持有最小行排他锁的事务回滚

3.4 事务日志

事务日志:存储引擎在修改表的数据的时候只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到硬盘。
事务日志是追加写入,是磁盘上一块区域的顺序IO,所以速度快很多
事务日志持久以后,内存中被修改的数据可以慢慢的刷回磁盘,成为预写日志。

checkpoint机制(内存中被修改的数据啥时候同步到磁盘)

高性能mysql试读 高性能 mysql_隔离级别_04

3.5、mysql中的事务

MySQL中的事务:存储引擎实现
MySQL两种事务型存储引擎:InnoDB、NDB Cluster

  • 自动提交AUTOCOMMIT; 默认采用自动提交模式,如果不显式开始一个事务,则每个查询都被当做一个事务执行提交操作,可通过AUTOCOMMIT变量来启用=1 =ON 、禁用=0 =OFF(all查询都在一个事务中直到显式commit rollback)事务结束同时开始新的事务,修改这个变量对非事务型表没有任何影响;
  • MySQL可以通过set transaction isolation level设置隔离级别,新的级别在下一个事务开始时生效,配置文件设置整个库的,也可只改变当前会话的隔离级别set session transaction isolation level read committed;
    建议:不管何时都不要显示执行LOCK TABLES ,不管使用的是什么存储引擎,因为对事务有影响。

3.6 多版本并发控制(行锁的变种,目的:提高并发)

  • 多版本并发控制是行锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销很低。虽然实现机制有所不同,但是大都实现了非阻塞的读操作,写操作也只锁定必要的行。
  • MVCC:每个连接到数据库的读,在某个瞬间看到的是数据库的快照,写操作在提交之前对外不可见,有乐观悲观两种,在读已提交和可重复读两个隔离级别下工作。

InnoDB的MVCC:每行记录保存两个隐藏的列来实现,一个保存了行的创建时间,一个保存行的过期时间(或者删除时间),即系统版本号,每开始一个新的事务,系统版本号会自动递增,事务开始时刻的系统版本号会作为事务的版本号。

例子
  • 1、插入数据:记录的版本号即当前事务的版本号,执行一条数据语句:insert into testmvcc values(1,“test”);
  • 高性能mysql试读 高性能 mysql_高性能mysql试读_05

  • 2、在更新的时候,采用的是先标记旧的那行记录为已删除,并且删除版本号为事务版本号,然后插入一行新的记录的方式。
    比如update table set name=“new_value” where id=1;
  • 高性能mysql试读 高性能 mysql_高性能mysql试读_06

  • 3、删除操作的时候,就把食物版本号作为删除版本号,比如delete from table where id=1;
  • 高性能mysql试读 高性能 mysql_隔离级别_07

  • 上面的三个操作应该是在不同的事务中
  • 4、查询操作:
    从上面的描述中可以看出,在查询的时候要符合以下两个条件的记录才会被事务查询出来:
    (1)删除版本号未指定或者大于当前事务版本号,即查询事务开启后确保读取的行未被删除。(即上述事务id为2的事务查询时,依然能读取到事务id为3所删除的数据行)。
    (2)创建版本号小于或者等于当前版本号,也就是说记录说在当前事务中(等于的情况)或者在当前事务启动之前的其他事务进行的insert。

四、 MySQL的存储引擎

  • 1、MyISAM(不支持事务和行锁、支持表锁和全文索引)
    不支持事务,但是整个操作是原子性的
    不支持外键,支持表锁
    一个MyISAM表有三个文件:索引文件,表结构文件,数据文件
    自动存储表的总行数,执行select count() from table时只要简单的读出保存好的行数即可
    采用非聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。
    支持全文索引和空间索引
  • 2、InnoDB
    除非有非常特别的原因需要使用其他的存储引擎,否则就应该优先考虑InnoDB引擎。
    支持事务、隔离级别、行锁和外键约束,因此可以支持写并发