本文来自于拜读《高性能MySQL(第三版)》时的读书笔记
作者:安明哲
转载时请注明部分内容来自《高性能MySQL(第三版)》

MySQL的逻辑构架

MySQL服务器逻辑架构
  • 最上层:链接处理,授权认证,安全等处理

  • 第二层:查询解析、分析、优化、缓存以及内置函数(如:日期,时间,数学和加密函数)

  • 第三层:包含了存储引擎,存储引擎负责数据的存储和提取。

链接管理和安全性

每一个客户端链接都在MySQL服务器进程中拥有一个多线程,在CPU中轮询运行,服务器会负责缓存线程,因此不需要为每一个新建的链接创建或者销毁线程。

MySQL5.5以后支持线程池插件,可以使用池中少量的线程来服务大量的连接。

客户端连接到MySQL之后,服务器会对其进行认证,认证基于用户名,密码和原始主机信息,如何使用了SSL连接,还可以使用证书认证。一旦连接成功,服务器会继续验证客户端的权限。

通常我们通过一个用户名和密码外加一个数据库的地址连接数据库,连接数据库的指令可能如下:

mysql -u username -h 192.168.1.100 -p *****

当我们链接MySQL-Server时,他可能会检查我们的用户名密码,除此之外还会检查我们的主机地址,通过主机地址判断是否允许我们登录,比如大部分小型站点会把MySQL和站点文档放置在一个服务器,而且MySQL拒绝了localhost之外的所有连接(不允许远程连接),其次我们还可以在MySQL内设置用户的权限,比如仅允许select(只读)。

优化与执行

MySQL会解析查询,并创建内部数据结构,然后进行各种优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。

对于SELECT语句,MySQL内部会有一个Query Cache,如果这个缓存内能够找到对应的查询,MySQL则会省去解析和优化工作,直接返回结果。

并发控制

MySQL共有两个层面的并发控制,服务器层存储引擎层

读写锁

当有多个连接同时修改一个数据库的某一个表的某一行的时候,会发生什么结果是不确定的。

这有点类似于多线程编程下的线程同步和死锁,事实上MySQL问题的本质似乎也就在这里。

解决这类问题的方法就是并发控制,MySQL在处理这类并发操作的时候可以实现一个由两种类型的锁组成的索系统来解决问题。这两种类型的锁一般被称为共享锁排它锁

共享锁是互不阻塞的,也就是多个用户可以同时读取一个资源,所以也叫做读锁。

排它锁是一个写锁会阻塞其他写入和读取操作,只有这样才能保证同一时间只会存在呢一个连接在想数据库内写入,所以也被称作写锁

粒度锁

一种提高共享资源并发性的方式就是让锁定得对象更具有选择性。尽量只锁定需要修改的部分数据,而不是所有资源。更理想的方式是,只会对要修改的数据片进行精确的锁定。

那么,理论上锁定的资源越小,锁定范围越精确,那么并发性能就会越高。但是事实上,创建一个数据锁也会造成系统的开销,如果系统通过大量的时间来管理锁,而不是存取数据,系统的性能反而会降低。

表锁

粒度锁的精确度是根据需求来决定的,很多时候我们都是在寻找精度和锁开销之间的一个平衡点。

表锁是MySQL中基本的锁策略,并且是开销最小的策略。当用户在对一张表进行写操作之前,首先获得写锁,于是,它阻塞了其他链接的读取和写入操作,只有写锁接触的时候,其他链接才能获得读锁。
不仅如此,MySQL还设置了锁的优先级,在操作列队中MySQL可能会把写入操作插入到读取操作之前。

那么,可以想象一下MySQL的后台实现,可能表锁的是这样是实现的(仅仅是本人猜想):

//下面的代码类似于伪代码,没有参考MySQL源码
//仅仅是本人为了为了理解MySQL表锁的臆测:
struct table_lock
{
/*一个表锁的结构体*/
char* table_name;
char* host;
};
//实例化一个链接
int* instance = getInstance();
//当执行读取操作的时候,可能需要传递一个table_name
instance->readTable(table_name)
{
//读取操作时候首先要获取表锁的所有权
table_lock.name = table_name;
table_lock.host = instance;
}
行级锁

行级锁可以最大程度的支持并发处理(同时也带来了最大的锁开销)。行级锁只在存储引擎中实现。

行级锁比表锁更加精确,他把锁的对象精确到了对象的某一行,但也就意味着需要创建更多的锁。

事务

事务其实就是一个独立的工作单元。如果数据库引擎能够完成事务中的每一项操作,那么全组的SQL语句都会被执行,如果任何一条语句因为崩溃或者其他原因无法执行,那么所有语句都不执行。

最简单的例子就是我们银行的转账系统,一个转账操作实际上是从用户账户表里减去对A的账户余额进行修改,同时再去修改B的账户余额,最后再在记录表被记录下这一条操作。SQL语句大致如下:

START TRANSACTION;
SELECT balance FROM checking WHERE customer_id = 1010001;
UPDATE checking SET balance = balance-200.00 WHERE customer_id = 1010001;
UPDATE checking SET balance = balance+200.00 WHERE customer_id = 1010002;
INSERT INTO record VALUES('1010001', '1010002', 200.00);
COMMIT;

这个时候如果执行到第三条语句的时候发现1010002这个账户已经被冻结了,无法接受转账,这个时候按照正常的逻辑,数据库内部10010001这个用户平白无故的就少去了200元,但是10010002并没有收到。
使用事务就完美的解决了这个问题,如果一条语句执行失败,没关系,最终没有commit之前,MySQL是不会进行写入操作的。

ACID

那么有一个专业的名词来描绘这种需求,他叫做ACID:
A---atomicity(原子性):一个事务必须被视为一个不可分割最小工作单元,事务中的操作只要有一个失败则全部回滚(可以理解为,一件事情,要么全做,有一点调点不具备那么全部都不做。)

C---Consistency(一致性):在一个转账事务中,A账户的减少必定对应着B账户的增加,这个状态转换的过程必须保持一致,那么这就是事务的一致性。

I---Isolation(隔离性):通常来说,一个事物所做的修改在最终提交之前,对其他事务是不可兼得。也就是说,事务内部的操作是不会被外部所看到的,只有最终提交之后,我们才能在银行系统中看到两个账户金额的变化(这个时候如何还有一个事务在执行同样的转账操作,那么们是相互隔离的,这看起来并不严谨,事实这里还设计一个隔离级别的问题,这个以后再谈)。

D---durability(持久性):一旦失误提交,所有的修改会永久的保存在数据库中,即使系统崩溃,服务器被损坏,只要硬盘还在,数据就依旧存在。

事务的ACID看起来很简单,但是在应用逻辑中要实现这一点非常难,因为还有相当一部分涉及到用户体验的考虑,你必须保证数据同步的问题,保证数据的一致性和持久性同时还要让用户觉察不到这么复杂的工作。而且,事务所做的操作正如锁一样,需要更多的系统资源,你还需要更强的CPU、更大的内存和更多的磁盘空间。

文/一点简单(简书作者)
原文链接:http://www.jianshu.com/p/5cb7383f33dd
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

1121高性能MySQL之运行机制的更多相关文章

  1. MySQL运行机制原理&架构

    1.MySQL知识普及: MySQL是一个开放源代码的关系数据库管理系统. MySQL架构可以在多种不同场景中应用并发挥良好作用.主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统 ...

  2. MySQL架构原理之运行机制

    所谓运行机制即MySQL内部就如生产车间如何进行生产的.如下图: 1.建立连接,通过客户端/服务器通信协议与MySQL建立连接.MySQL客户端与服务端的通信方式是"半双工".对于 ...

  3. 高性能Mysql主从架构的复制原理及配置详解

    温习<高性能MySQL>的复制篇. 1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台 ...

  4. 转:高性能Mysql主从架构的复制原理及配置详解

    温习<高性能MySQL>的复制篇. 1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台 ...

  5. 高性能Mysql主从架构的复制原理及配置详解(转)

    温习<高性能MySQL>的复制篇. 1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台 ...

  6. 《高性能Mysql》讲聚簇索引

    <高性能Mysql>原文 聚簇索引如下图为聚簇所有的存储方式,聚簇实际不是一种索引,而是一种数据的存储方式,InnoDB的聚簇事假在同一个结构中保存了B-Tree索引和数据行. 当表有聚簇 ...

  7. 【高性能Mysql 】读书笔记(一)

    第1章 Mysql架构与历史 MYSQL最重要.最与众不同的特性是它的存储引擎架构,这种架构的设计将查询处理( Query Processing)及其他系统任务( Server Task)和数据的存储 ...

  8. 好书推荐之Mysql三剑客 :《高性能Mysql》、《Mysql技术内幕》、《数据库索引设计与优化》

    Mysql三剑客系列书籍: 大佬推荐 首先推荐<高性能 MySQL>,这本书是 MySQL 领域的经典之作,拥有广泛的影响力.不但适合数据库管理员(DBA)阅读,也适合开发人员参考学习.不 ...

  9. PHP的运行机制与原理(底层) [转]

    说到php的运行机制还要先给大家介绍php的模块,PHP总共有三个模块:内核.Zend引擎.以及扩展层:PHP内核用来处理请求.文件流.错误处理等相关操作:Zend引擎(ZE)用以将源文件转换成机器语 ...

随机推荐

  1. 磁盘配额-----quota

    为什么要使用磁盘配额:为了限制普通用户使用普通磁盘的空间与创建文件的个数等. 不至于个别人的浪费影响所有人的使用. 需要安装quota的软件包. mount -o usrquota,grpquota ...

  2. Ganglia安装扩容

    现有的环境中Hbase集群的机器需要安装ganglia,遂采取了以下步骤. 查看机器的信息, uname –a cat /etc/issue 查看当前环境是x86的,安装的是red hat 6.4 之 ...

  3. java设计模式之装饰模式

    发现设计模式的学习越来越让自己学习的东西太少了,应该多接触一些东西,多出去走一走. 装饰模式概念: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活(大话设计模式) 在不 ...

  4. ATM模拟程序

    一个很简单的ATM模拟程序 #include <stdio.h> void chaxun(int a3){ int b; b=a3; printf("您的余额为:%d\n&quo ...

  5. Java中的移位运算符

    java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,num >& ...

  6. Thread对象的yield(),wait(),notify(),notifyall()

    Thread类中的主要方法: join()方法:让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等到此线程完成之后才可以继续执行. setDaemon():设置线程为后台线程,这样即使Ja ...

  7. jmeter 函数助手里的P,property的使用

    1.函数助手里的 p及property的使用 ${__P(init,2)} , ${__property(init,start,200)} 可以自行定义变量名称,及变量的默认值 P 变量名为init, ...

  8. [No000064]python 变量命名规范

    python源码和其他一些书籍,命名各种个性,没有一个比较统一的命名规范.于是总结了一些,供参考. 模块名: 模块应该使用尽可能短的.全小写命名,可以在模块命名时使用下划线以增强可读性.同样包的命名也 ...

  9. 理解Java中字符流与字节流的区别

    1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序 ...

  10. 手势-webview与scrollView重复手势处理

    // called when the recognition of one of gestureRecognizer or otherGestureRecognizer would be blocke ...