《高性能MySQL》读书笔记(一) ——MySQL架构及重要属性概述

《高性能MySQL》读书笔记(一)——MySQL架构及重要属性概述

(原创内容,转载请注明来源,谢谢)

一、MySQL逻辑架构

1、三层架构

mysql逻辑分为三层设计:

第一层是基于网络的处理,如连接处理、授权认证、安全等,这个在基于网络的服务器、客户端中的各种软件都会有相应的实现。

第二层是mysql的核心功能部分,包括查询解析、分析、优化、缓存、以及所有的内置函数,所有跨存储引擎的功能也都在这一层实现,包括触发器、存储过程、视图等。

第三层是数据库的存储引擎,即通常提及mysql都会提到的mysiam、innodb等。存储引擎负责数据的存储和提取,不同的存储引擎适用于不同的场景,各有优缺点。服务器通过API与存储引擎进行通信,且不同的存储引擎,底层的函数名称与参数都是一样的,这也使得大部分情况下存储引擎对于数据库使用者是透明的(除了事务、锁等特殊操作,不同的存储引擎会有所不同)。

mysql三层架构如下图所示:

2、连接管理

每个客户端都用一个进程和mysql服务器进行连接,这个连接只在单独进程中进行,该进程只能轮流cpu的核心。另外,服务器会缓存线程,不用为每一个连接新建线程。

客户端连接时,mysql服务器会进行登陆验证,验证完毕后还有继续验证用户具备哪些权限(如对每个表的读、写权限等)。

3、优化与执行

mysql会解析查询语句,并且创建内部数据结构,对其进行优化,包括重写查询、决定表的读取顺序、选择合适的索引(每次查询只能用一个或一组索引)。对于select语句,查询之前,会先检查查询缓存,如果有缓存,则直接返回,不用解析、优化、执行的过程。

二、并发控制与锁

1、读写锁与锁粒度

锁分为读锁(又称为共享锁)和写锁(又称为排它锁)。读锁是共享的,即多个客户端可以在同一个时刻读同一个资源,并不会互相影响;写锁是排他的,对于同一个资源,一个进程在写的时候,另一个进程无法写,也无法读。

锁的粒度越细,越能精确控制锁的范围。如对整个表的锁,与对当行的锁,效果就不一样。锁表则如果仅操作某一行,其他行也会被锁住,这样耗费资源,但是只有一个锁,所以也只要维护一个锁;锁行,则只会锁住操作的那一行,其他行不影响,但是如果有多行操作,则需要维护多个锁,加大维护的开销。

mysql不同的存储引擎,对锁的策略不同,mysiam是表锁,innodb是行锁。但是,对于诸如alter table等ddl语句,mysql会直接使用表锁,而不管存储引擎采用的锁策略。

当两个事务之间采用不同的顺序操作某一条数据,则可能发生死锁,一个两个事务分别在等待对方释放对数据的锁,才能进行后续的操作。mysql的很多引擎会检测,如果语法分析发现会产生死锁,则不让执行;另外,如果真的进入死锁,则需要对其中一个事务进行回滚,以释放资源。

2、多版本并发控制(MVCC)

mysql大多数的支持事务的存储引擎,都不是简单的行锁,而会采用mvcc,以提升并发性能。

mvcc通过保存数据某个时间节点的快照实现的,不管事务需要执行多久,事务内部看到的内容总是一致的。根据事务开始时间不同,每个事务看到的表的数据可能不一样。根据不同的存储引擎,有乐观并发控制和悲观并发控制。

对于innodb,是通过每行后面保存两个隐藏的列来实现的,一个保存的是行的创建时间,一个保存的是过期时间(删除时间)。并且,不是保存具体的时间,而是用版本号的方式来进行保存。

每次开始一个新事务,事务的版本号都是增1,并且提交事务的时候,会先在数据库里进行查询,确认提交的时候数据库里的版本号和开始事务时的版本号一致,以确保事务执行期间,没有其他的进程或事务改动过该数据。

确认一致后,会在提交数据的同时,如果是update命令,会将数据库的版本号加1。这样,如果同期有其他的事务在进行,会提交失败,以确保数据一致性;如果是delete命令,则会将数据的过期时间加上标记;如果是新增,则版本号和当前事务版本号一致。

通过mvcc,可以避免大部分情况下的锁,特别是对于读,不需要加锁,性能较好。

三、事务

1、事务原则

具备事务的系统,都必须经过acid测试。

a(atomicity)是原子性,即要求事务是最小单元,要么其中内容全部成功,要么全部失败;c(consistency)是一致性,事务执行期间,从一个状态切到另一个状态,并不会造成数据库数据错乱;i(isolation)隔离性,事务提交之前,对其他事务、其他系统是不可见的;d(持久性),事务提交会保存到磁盘,即使系统奔溃,修改的数据也不会丢失。

2、隔离级别

针对事务,有四种级别的隔离方式,定义了事务的修改,对于事务内部和外部,哪些是可见的。

1)readuncommitted(未提交读),即事务未提交都可以读,这样级别几乎没有系统使用,对于未提交的事务都可以读,会严重影响事务的acid原则。

2)readcommitted(提交读),即事务提交之后,其他事务才可以读取,这个对于其他事务是没有影响的,基本符合acid,有一些系统采用此方式。但是mysql不是采用此方式。该方式下,一个事务执行期间,如果有需要两次读取同一行的数据,有可能是不一致的。

3)repeatableread(可重复读),这个是mysql的默认方式。即上述提到的mysql对于事务使用的快照的方式,在事务开始时记录当前状态,并且在整个事务期间,对于同一条数据,除非是该事务自身进行的修改,否则每次读取到的内容都是一致的。这样,可以避免事务执行期间其他事务修改了该数据,导致事务两次读取同一个数据不一致的情况。

4)serializable(可串行化),强制事务串行执行,严格性最高,为读取的每一行数据都会加上锁。但是这样也会带来比较大的开销。

如下图所示:

3、事务日志

事务日志提高事务的效率。在事务执行期间,mysql会将事务设计到的数据库操作,将结果存入内存中,而不是立即持久化到硬盘。对于事务里面的每条sql语句,采用追加的方式写入文件。

当事务结束后,再将内存中的数据,逐步写入磁盘中。这也称为预写式日志。

4、mysql的事务

mysql提供两个支持事务的存储引擎——innodb和ndb cluster。

对于普通的sql语句,mysql默认是自动提交,即不需要commit,输入语句就执行。但是,在一个事务中,如果要操作不同的表,而每个表的存储引擎不一致,则比较危险。如mysiam是不支持事务的,如果一个事务既操作innodb引擎的表,又操作mysiam的,则如果失败回滚,那对mysiam表的操作,会无法回滚。

innodb采用两阶段锁定协议进行数据锁定,在事务执行过程中,每个语句都可以显示的加锁,在事务执行完毕后会一次性释放所有事务期间的锁。

——written by linhxx 2017.09.11

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-09-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

2997
来自专栏张善友的专栏

Mix 10 上的asp.net mvc 2的相关Session

Beyond File | New Company: From Cheesy Sample to Social Platform Scott Hansel...

2767
来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2752
来自专栏魂祭心

原 canvas绘制clock

5074
来自专栏转载gongluck的CSDN博客

cocos2dx 打灰机

#include "GamePlane.h" #include "PlaneSprite.h" #include "BulletNode.h" #include...

7036
来自专栏java 成神之路

使用 NIO 实现 echo 服务器

5547
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.4K7
来自专栏落花落雨不落叶

canvas画简单电路图

83511
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4385
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

8538

扫码关注云+社区