前言:
// MySQL 并发、异步IO、进程劫持
最近在看高性能 MySQL,记录写学习笔记:
高性能 MySQL 学习笔记(一) 架构与历史
笔记核心内容:MySQL 服务器基础架构、各种存储引擎之间的主要区别,以及这些区别的重要性;
一、MySQL 逻辑架构
如图:
第一层架构图:
也就是最上层的服务并不是 MySQL 独有的,大多数基于网络的客户端/服务器的工具或者服务器都有类似的架构,比如链接处理,授权认证,安全等等 ;
// 每个客户端连接都会在服务器进程中拥有一个线程这连接查询只会在单独的线程中执行,线程只能轮流在某个 CPU 核心或者 CPU 中运行。
// 客户端(应用)连接到 MySQL 时,MySQL 服务会对其连接做一些列的身份认证(例如用户名密码、权限控制等)
// 这也回答了许多开发人员在使用数据库时,盲目的开关连接,甚至不关闭连接给 MySQL 服务器带来的损耗;
第二层架构:
MySQL 核心服务和功能都在这一层,包括查询解释,分析,优化,缓存以及所有的内置函数(例如,日期,时间,数学和加密函数),
所有跨存储引擎的功能都在这一层实现:存储过程,触发器,视图等。
// 查询解释:理解解析,将 SQL 的语句转换成 MySQL 内部数据结构(解析树)
// 分析:对语法的分析,是否存在语法错误;
// 优化:这是一个非常重的课题,还没有深入到这里来,大体了解意思为:将需要执行的 SQL 语句进行优化处理,如 where 条件后的顺序等;
// 内置函数:注意是内置,也可以自定义;但是不建议在 MySQL 上做这些操作,记住数据库只是用来存储数据的,数据库的性能空间留给 CRUD
// 后面章节对 MySQL 优化器单独分析
第三层架构:
包含了存储引擎,存储引擎负责MySql中数据的存储和提取,和GNU/Linux写的各个文件系统一样,每个存储引擎都有它的优势和劣势,
服务器通过API与存储引擎进行通信,这些接口屏蔽了不同存储引擎之间的差异,使得这些差异对于上层的查询过程透明,
存储引擎 API 包含十几个底层函数,用于执行诸如 '开始一个事务'或者'根据主键提取一行记录‘等操作,
但存储引擎并不会去解析 SQL,不同存储引擎之间也不会相互通信,而只是简单的响应上层服务器的请求。
二、MySQL 并发控制
并发:多条语句同时执行时,就会出现并发问题;
控制并发且不出现数据错误等问题,就取决于数据库系统如何在锁上如何设计的了。
MySQL 只一种可以支持到行级锁的数据库。MySQL 锁分为:表锁、行锁;
// update t_users set login_count = 0 where 1 = 1; # 产生一个表级锁
// update t_users set age = 18 where id = 9527; # 产生一个行级锁
每种 MySQL 存储引擎都可以实现自己的锁策略和锁粒度。
// 锁策略:所谓的锁策略,就是在锁的开销和数据的安全性之间寻求平衡,这种平衡直接与性能挂钩;
// 锁粒度:一种提高共享资源并发性的方式,让锁定的对象更有选择性。
// 锁定的数据量越小,则系统支撑的并发数量越高。
三、死锁
死锁是指两个或者多个事务(注意哈,一个单条的 update 语句其实本质上也是一个事务)在同一资源上互相占用,
并请求锁定对方占用的资源,从而导致的恶性死循环的现象。
// 不过注解,理解为两个人在互相等待;
MySQL 数据库在死锁现象上,实现了各种死锁检测和死锁超时的机制,
比如 InnerDB 存储引擎,它能检测到死锁的循环依赖,并立即返回一个错误。
四、存储引擎
存储引擎重点学习两个(InnerDB、MyISAM):
// 其他存储引擎用的很少,MySQL 官方也提供了一些 API,有很多爱好者在此基础上自己实现了许多存储引擎,
喜欢深挖的,可以去看看;
InnerDB:
事务型存储引擎,作为 MySQL 默认的存储引擎,应该说是在 MySQL 4.0 + 以后的版本推出来的。
他被设计用来处理大量的短期事务,短期事务大部分情况是正常提交的,很少会被回滚。
InnoDB的性能和自动崩溃恢复特性,使得他在非事务型存储的需求中也很流行,
除非有非常特别的原因需要使用其他的存储引擎,否则应该有限考虑InnoDB引擎。
InnoDB 的数据存储在表空间,表空间由InnoDB管理的一个黑盒子,由一系列的数据文件组成。
InnoDB 可以将每个表的数据和索引存放在单独的文件中。
InnoDB 也可以使用裸设备作为表空间的存储介质,但现在的文件系统是的裸设备不再是必要的选择。
InnoDB 采用 MVCC 支持高并发,并且实现了四个标准的隔离级别。
其默认级别是 REPEATABLE READ,并且通过间隙锁策略防止幻读的出现,
间隙锁是的InnoDB不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻行的插入。
InnoDB内部做了很多就花,包含从磁盘读取数据时采用的可预测性预读,
能够自动在内存中创建hash索引以加速读操作的自适应哈希索引,以及能够加速插入操作的插入缓存等。
作为事务型的存储引擎,InnoDB通过一些机制和工具支持真正的热备份,
Oracle 提供的MySql Enterprise Backup , Percona提供的开源的XtraBackup都可以做到这一点。
MySQL 的其他存储引擎不支持热备份,要获取一致性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可能意味着停止读取。
MyISAM:
MyISAM 的锁级别,不像 InnerDB 支持到行级锁,它只支持到表级锁,同时 MyISAM 不支持事务,
没有了解过的同学,不要在你执行了 Back 操作后一脸懵逼的问,明明回滚了为什么数据还是被提交了。
很早看过一篇关于 MySQL 存储引擎的如何做选择的文章,笔者对 InnerDB 和 MyISAM 分别做了读写的性能对比,
毫无疑问,MyISAM 的读写操作是高于 InnerDB 的,但是 MyISAM 也有很多的弊端,所以在选择时,应根据业务的需要作出决策,
否则出了问题,也会是坑了队友。如一些日志表,就可以直接选择 MyISAM。
MyISAM 不支持热备份,但是可以手工或者自动执行检查和修复操作,但这里说的修复和事务恢复以及崩溃恢复是不同的概念。执
行表的修复可能导致一些数据丢失,而且 修复操作是非常慢的。
五、如何选择合适的存储引擎
总结一句话:除非需要用到某些 InnerDB 不具备的特性,并且没有其他办法可以代替,否则应该优先选择 InnerDB 存储引擎;
// 不是非常特殊的情况,不要混合使用多种存储引擎;
不要轻易相信“MyISAM 比 InnerDB 快”之类的经验之谈,这个结论往往不是绝对的。
在很多我们已知的场景中,InnerDB 的速度都可以让 MyISAM 望尘莫及了,尤其是使用到聚簇索引,
或者需要访问的数据可以放入内存应用。