数据库相关的知识,看了《高性能MySQL》和《数据库系统实现》两本。两本书综合看效果更好。 《高性能MySQL》从使用的角度入手,《数据库系统实现》从原理的角度入手。以前学习数据库相关的知识时有个执念,一定要弄明白它是怎么实现的,就直接买了一个《MySQL内核:Innodb存储引擎》,结果看不懂,束之高阁。
数据库的知识,个人觉得如下的顺序比较合理。
《数据库系统实现》在第二章就单独用一章的篇幅讲解磁盘的存储原理。这是因为计算机内置组件中具备持久存储能力的只有硬盘,软件屈从于硬件。因此理解磁盘的存储特点才能理解软件设计背后的逻辑。磁盘存储有如下的特点:
特性A:相比CPU的延迟,磁盘延迟非常非常大。 在《性能之巅》中有做过对比,对于3.3GHz的CPU, 一个指令周期为0.3ns;机械硬盘一次I/O的延迟为1~10ms。这个差距有多大,如果一个CPU指令周期为1s, 那么机械硬盘一次I/O的延迟为1~12个月。真是等到花儿都谢了。
特性B:磁盘是块设备,每次写入都是按块来的。通常一个块为512byte。即使用硬盘,得注意不能用轮船只运输一个土豆到美国
。
上述的特性不仅影响了数据库的设计,更是深刻影响了操作系统的设计,例如page cache
数据库的操作基本上就是更高阶的读写: select 和 delete/update 是我们使用数据库频率最高的操作了。 所以,数据库解决的核心问题就是如何组织数据实现高性能的读写。
###事务
高性能没法忽略掉并发,在并发读写场景下,就会出现数据一致性的问题。所以事务
就用来解决数据一致性的问题了。
默认每条SQL语句都是一个事务, 可以手动设置提交点改变这一规则
在MySQL中,事务的隔离级别有4种。这4种其实不用死记硬背,可以从应用场景推导出来。
事物A修改了记录a, 没有提交;事务B读取表,读取到了该事务。 这就是未提交读
。 如果我们自己设计数据库,在原数据上修改字段,如果没有其他手段的控制,并发情况下就会出现这种情况。由于读取到了脏数据,也称为脏读。这里我们也可以将事务换一个熟悉的概念:线程来理解
针对上面未提交读
的问题,如果将改动保存在事务的作用域内部,那么未提交的数据就不会影响其他事务。 这种隔离级别就是提交读。也叫不可重复读。因为失误内部两次执行可能得到不一样的结果。
提交读面临的不可重复读的问题,在可重复读
隔离级别下可以避免。它能保证一个事务多次读取同一条记录不会改变。当然,如果事务内部改变了该记录,另说。这个级别带来的另一个问题就是[幻读]。 这个很好理解: 2个事务。事务A 读取记录不存在就写入;事务B写入记录。 事务A有可能出现写入失败的情况。
将事务顺序执行。性能最低的做法。
通常查询数据有两种典型的场景: 等值查询
和区间查询
。 即select * from table where field=a
或者 select * from table where field between a and b
。 如果没有索引,唯一的做法就是全表扫描。这是一种大海捞针的做法。 程序员一般关注两个点: 问题在哪和怎么优化。 对于等值查询,最好的优化方式就是hash了。对于区间查询,不是hash算法的用武之地,因为它有个隐藏的逻辑: 排序。 通常,具备排序功能的数据结构有: 排序后的数组,链表。 跳跃表。AVL树,红黑树,B树,B+树。
为什么选择B+树?
性能就是响应时间。 性能问题的排查思路是top-down的方式:
性能问题需要更多是操作系统相关的知识。
这个是MySQL的杀手锏。如果没有复制功能,MySQL不可能这么流行。 复制引申出来的特性: 读写分离,负载均衡,高可用,故障切换, 备份, 测试升级。都是滥大街的概念。
复制的实现方式:基于行的复制和基于日志的复制。
可扩展性就是通过增加资源来提升系统容量的能力。比如MySQL通过读写分离,每新增一个Slave节点,数据库层面的读并发能力有所提升。当然由于系统分层,每个层级都支持可扩展性,整个系统才具备可扩展性。
数据库层级的扩展常用策略就是分库分表这些策略了。
另外,可扩展性跟系统性能是两回事。 比如Hive性能较低,但是不影响其可扩展性。
高可用本质上就是更少的宕机时间。 如果从计算机的视角来看待人,人的可用性一般只有50%,按每天8小时工作制,人的可用性只有33%。
利用top-down的思路, 实现高可用,只有两种办法: 提升平均失效时间间隔
, 简而言之,就是让系统两次宕机中间的时间间隔越长越好;降低平均恢复时间
, 简而言之,就是出了故障修复时间越短越好。 所以,高可用更多的是架构层面的东西, 比如MySQL的互为主备,负载均衡。
备份是个容易被忽略的话题。属于那种平时不待见,关键时刻需要扛雷。 备份的作用基本有三个: 灾难恢复,审计,测试。
《高性能MySQL》是一本兼顾深度和广度的书,没有那么多的原理性细节,适合开发阅读。如果想更深入学习,估计《数据库系统实现》是一本比较适合的书。