一、MySQL结构

一、逻辑架构

逻辑架构图

最上层的服务不是MySQL独有,多数基于网络的C/S的工具或者服务都有类似架构。

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

第三层包含了存储引擎。存储引擎负责MySQL中数据的存储和提取。服务器通过API与存储引擎进行通信。这些API屏蔽了不同存储引擎的差异。存储引擎不会去解析SQL,不同存储引擎之间也不会会相互通信,只是简单地响应上层服务器的请求。存储引擎是基于表,而不是数据库。

MySQL体系架构

MySQL由以下几部分组成:

  • 连接池组件
  • 管理服务和工具组件
  • SQL接口组件
  • 查询分析器组件
  • 优化器组件
  • 缓存组件
  • 插件式存储引擎
  • 物理文件

1.连接管理与安全性
每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行。服务器负责缓存线程,因此不需要为每个新建连接创建或销毁线程。

当客户端连接到MySQL服务器时,服务器需要对其进行认证。认证基于用户名、原始主机信息和密码。若使用了安全套接字(SSL)方式连接,还可以使用X.509证书认证。连接成功后,服务器会继续验证该客户端是否具有执行某个特定查询的权限。

2.优化与执行
MySQL会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。用户可以通过关键字提示(hint)优化器,影响其决策过程。也可以请求优化器解释(explain)优化过程的各个因素。

优化器不关心使用的存储引擎类型,但存储引擎对于优化查询有影响。优化器会请求存储引擎提供容量或者某个具体操作的开销信息等。

二.并发控制
1.读写锁
读锁(也叫共享锁,shared lock),互不阻塞。多个用户在同一时候刻读取同一资源互不干扰。

写锁(也叫排他锁,exclusive lock),一个写锁会阻塞其他写锁与读锁,这样才能确保在同一时刻,只有一个用户能执行写入并防止其他用户读取正在写入的同一资源。

写锁比读锁有更高的优先级,因此一个写锁请求可能会插入到读锁队列前面。

2.锁粒度

锁策略,就是在锁的开销与数据的安全性之间寻求平衡,这种平衡会影响性能。每种MySQL存储引擎可以实现自己的锁策略和锁粒度。

表锁
开销小,会锁定整张表。一个用户在对表进行写操作前,需要先获得写锁,因此会阻塞其他用户对该表的所有读写操作。

行级锁
可以最大程度的支持并发处理,锁开销也最大。行级锁只在存储引擎层实现,服务器完全不了解存储引擎中的锁实现。InnoDB,XtraDB以及其他一些存储引擎实现了行级锁。

三、事务
事务就是一组原子性的SQL查询。该组操作要么全部执行成功,要么全部执行失败。

ACID表示原子性(atomicity)、一致性(consistency)、隔离性(isolation)】持久性(durability)。一个运行良好的事务处理系统必须具备执行标准特征。

原子性(atomicity)
一个事务的所有操作要么全部提交成功,要么全部失败回滚,不可能只执行其中一部分操作。

一致性(consistency)
数据库总是从一个一致性状态转换到另一个一致性状态。

隔离性(isolation)
通常一个事务所做的修改在提交前,对其他事务不可见。

持久性(durability)
一旦事务提交,其所做的修改会永久保存到数据库中。持久性也分多个不同级别。

1.隔离级别
较低级别的隔离通常可以执行更高的并发,系统开销也低。

四种隔离级别:
READ UNCOMMITTED(未提交读)

事务中的修改,即使没有提交,对其他事务可见。事务读取未提交的数据,称为脏读(Dirty Read)。一般很少使用。

READ COMMITTED(提交读)

提交读满足隔离性的简单定义:一个事务开始到提交之前,所做修改对其他事务不可见。这个级别有时候也叫不可重复读(Nonrepeatable Read),因为两次执行相同查询,可能得到不同结果。

REPEATABLE READ(可重复读)

可重复读解决了脏读的问题。保证了同一事务中多次读取同样记录的结果一致。但是无法解决幻读(Phantom Read)问题。幻读,是指当某个事务在读取某个范围内记录时,另一个事务在该范围内插入了新纪录,当之前的事务再次读取该范围的记录时,产生幻行(Phantom Row)。

InnoDB和XtraDB通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决幻读问题。

SERIALIZEABLE(可串行化)

最高隔离级别。通过强制事务串行化执行,避免幻读问题。简单来说,可串行化会在读取的每行数据加锁,所以可能导致大量的超时和锁争用问题。实际中很少应用这个级别。

2.死锁

死锁是指两个或多个事务在同一资源上的相互占用,并请求锁定对方占用的资源,从而导致恶性循环。当多个事务视图以不同顺序锁定资源时,可能出现死锁。多个事务同时锁定同一资源时,也会产生死锁。

例如,两个事务都对同一表执行了第一条update语句,同时锁定了该行数据,两个事务尝试去执行第二条update时,发现该行被对方锁定,然后两个事务都等待对方释放锁,同时又持有对方需要的锁,陷入死循环。

为了解决这种问题,数据库系统实现了各种死锁检查和死锁超时机制。InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。

锁的行为和顺序和存储引擎有关。以同样顺序执行语句,有点存储引擎会死锁,有点不会。原因是有些是因为真正的数据冲突,有些是由于存储引擎实现方式导致。
多数情况下只需要重新执行因死锁回滚的事务即可。

3.事务日志

事务日志帮助提高事务效率,使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,不用每次都将修改的数据本身持久到硬盘。

事务日志采用追加方式,因此写日志操作是磁盘上的一小块区域内的顺序I/O,不需要多个地方移动磁头,所以相对来说快得多。

事务日志持久以后,内存中被修改的数据在后台慢慢刷回磁盘。通常称之为预写式日志(Write-Ahead Logging),修改数据需要写两次磁盘)。

4.MySQL中的事务

MySQL提供两种事务型存储引擎:InnoDB和NDB Cluster。还有其他一些第三方存储引擎。

自动提交(AUTOCOMMIT)

MySQL默认自动提交。即若不显示开始一个事务,则每个查询都被当作一个事务执行提交操作。设置AUTOCOMMIT变量启用或禁用自动提交模式:

show variables like 'AUTOCOMMIT';
....
set AUTOCOMMIT =1;

禁用时,所有查询都在一个事务中,直到执行commit或者rollback。有一些命令在执行之前会强制commit提交当前事务,具体检查对于官方文档。

MySQL可以通过执行SET TRANSACTION LEVEL设置隔离级别。新的隔离级别会在下一个事务开始时生效。可以在配置文件中设置整个数据库的隔离级别,也可以只改变当前会话的隔离级别:

set session transaction isolation level read committed;

在事务中混合使用存储引擎
服务器层不管理事务,事务是由存储引擎实现。所以,在同一事务中,使用多种存储引擎是不可靠的。

如果在事务中混合使用了事务型和非事务型表,正常提交不会有问题,回滚操作会失败,因为非事务型表的变更无法撤销,会导致数据库处于不一致状态。

隐式和显式锁定

InnoDB采用两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随时可以锁定。锁只有在执行commit或rollback时才释放,并且所有锁在同一时刻释放。

前面描述的是隐式锁定,InnoDB会根据隔离级别在需要的时候自动加锁。
InnoDB支持通过语句显式锁定:

select ... lock in share mode
select ... for update

四、多版本并发控制
mvcc的实现,是通过保存数据在某个时间点的快照来实现的。典型的有乐观并发控制与悲观并发控制。

InnoDB的MVCC,是通过在每行记录后面保存两个隐藏列实现。一列保存行的创建时间,一列保存行的删除时间。列存储的值是系统版本号(system version number)。每开始一个新事务,系统版本号自动递增。事务开始时的系统版本号会作为事务的版本号。
在REPEATABLE READ级别下,MVCC具体操作:

SELECT:

1.InnoDB只查找行的系统版本号小于或等于事务的系统版本号的数据行,这样确保事务所读取的行,在事务开始时前已存在或事务自身插入或修改过。
2.行的删除版本要么未定义,要么大于当前事务版本号。确保事务读取到的行,在事务开始前未被删除。

INSERT:
为新插入的每行保存当前系统版本号为行版本号。

DELETE:
为删除的每行保存当前系统版本号为行删除版本号。

UPDATE:
插入一行新纪录,保存当前系统版本号为行版本号,保存当前系统版本号到原来的行作为行的删除版本号。(可以理解为先delete,后insert。)

这种方式,使大多数读操作不用加锁。缺点是需要额外空间。

MVCC只在可重复读与提交读两个隔离级别下工作。SERIALIZABLE会对所有读取行加锁。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容

  • 为了充分发挥MySQL的性能并顺利地使用,就必须理解其设计。MySQL的灵活性体现在很多方面。例如,你可以通过配置...
    李文文丶阅读 1,167评论 0 4
  • 最上层的服务井不是MySQL所独有的, 大多数基于网络的客户端/服务器的工具或者 服务都有类似的架构。 比如连接处...
    好好学习Sun阅读 269评论 0 0
  • 一、概述 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种...
    忘忧谷主阅读 590评论 0 3
  • 亲爱的你,在这快节奏的生活里,你有多久,没有停下来休息过了?我们每一天都身在焦虑的漩涡里,忙碌而又枯燥,想一想,最...
    青唐pur阅读 267评论 0 6
  • 儿子得了胃炎差不多有两个月了,孩子天天愁着个脸,我是天天揪着个心。上个星期基本上都好了,前天晚上又突然开始疼了...
    THY桃花颜阅读 271评论 3 2