《高性能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 条评论
登录 后参与评论

相关文章

来自专栏社区的朋友们

Kafka 设计原理

跟 RabbitMQ 、RocketMQ 等目前流行的开源消息中间件相比,Kakfa 具有高吞吐、低延迟等特点,在大数据、日志收集等应用场景下被广泛使用。

1.9K0
来自专栏about云

Kafka权威指南 —— 1.2 初识Kafka

什么是Kafka Apache Kafka是一个基于分布式日志提交机制设计的发布订阅系统。数据在kafka中持久化,用户可以随时按需读取。另外数据以分布式的方...

3926
来自专栏程序员互动联盟

【专业技术】Linux设备驱动第七篇:高级字符驱动操作之阻塞IO

我们之前介绍过简单的read,write操作,那么会有一个问题:当驱动无法立即响应请求该怎么办?比如一个进程调用read读取数据,当没有数据可读时该怎么办,是立...

3107
来自专栏Hongten

java多线程系列_线程简介(1)

    线程是程序运行的基本执行单元。当操作系统(不包括单线程的操作系统,如微软早期的DOS)在执行一个程序时,会在系统中建立一个进程,而在这个进程中,必须至少...

912
来自专栏北京马哥教育

最全服务器模型详解——从单线程阻塞到多线程非阻塞

前言的前言 服务器模型涉及到线程模式和IO模式,搞清楚这些就能针对各种场景有的放矢。该系列分成三部分: 单线程/多线程阻塞I/O模型 单线程非阻塞I/O模型...

3485
来自专栏.NET开发那点事

检测WCF服务是否在线(动态执行WCF服务)

  在我们的系统里有多个wcf支撑。但是有的时候会莫名的停止,于是今天写了一个服务,定时去检测其他wcf服务是否在线。那么最简单的办法自然是引用其他wcf服务让...

2047
来自专栏互联网杂技

数据库事务的四大特性以及事务的隔离级别详解

  原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果...

814
来自专栏Python中文社区

Python操作分布式流处理系统Kafka

專 欄 ❈强哥,Python中文社区专栏作者,曾供职于摩根士丹利(Morgan Stanley)和eBay。❈ 什么是Kafka Kafka是一个分布式流处理...

30610
来自专栏linux驱动个人学习

Linux下的进程类别(内核线程、轻量级进程和用户进程)--Linux进程的管理与调度(四)

虽然我们在区分Linux进程类别, 但是我还是想说Linux下只有一种类型的进程,那就是task_struct,当然我也想说linux其实也没有线程的概念, 只...

1012
来自专栏Java技术

数据库的隔离级别与事务的特性

1.Read Uncommited(未提交读):没有提交就可以读取到数据(发出了insert,但没有commit就可以读取到);

674

扫码关注云+社区