高性能MYSQL部分摘要

高性能MYSQL读书笔记

第1章 MySQL架构与历史

1.1链接管理

每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查 询只会在这个单独的线程中执行,该线程只能轮流在某个CPU核心或者 CPU中运行。

1.2并发控制

1.2.1读写锁

在处理并发读或者写时,可以通过实现一个由两种类型的锁组成的锁系统来解决 问题。这两种类型的锁通常被称为共享锁(shared lock)和排他锁 (exclusive lock),也叫读锁(read lock)和写锁(write lock)。读锁是共享的,或者说是相互不阻塞的。多个客户在同一时刻可以同时读取同一个资源,而互不干扰。写锁则是排他的,也就是说一个写锁会阻塞其他的 写锁和读锁

1.2.2锁粒度

理想的方式是,只对会修改的数据片进行精确的锁定

加锁也需要消耗资源。锁的各种操作,包括获得锁、检查锁 是否已经解除、释放锁等,都会增加系统的开销

表锁是MySQL中最基本的锁策略,并且是开销最小的策略。

行级锁可以最大程度地支持并发处理(同时也带来了最大的锁开销

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

服务器会为诸如ALTER TABLE 之类 的语句使用表锁,而忽略存储引擎的锁机制

1.3事务

原子性(atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务 中的所有操作要么全部提交成功,要么全部失败回滚

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

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

持久性(durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。

1.3.1隔离级别(可重复读是MySQL的默认事务隔离级别)

READ UNCOMMITTED 级别,事务中的修改,即使没有提交, 对其他事务也都是可见的

事务可以读取未提交的数据,这也被称为脏读(Dirty Read)

READ COMMITTED 也叫做不可重复读,满足前面提到的隔离性的简单定 义:一个事务开始时,只能“看见”已经提交的事务所做的修改

不可重复读两次执行同样的查询,可能会得到不 一样的结果

**REPEATABLE READ(可重复读)可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)**的问题

幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围 的记录时,会产生幻行(Phantom Row)

InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题

**SERIALIZABLE(可串行化)**会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

1.3.2死锁

死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象

事务1START TRANSACTION;
	UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4 '; 
	UPDATE StockPrice SET close = 19.80 WHERE stock_id = 3 ; 
	COMMIT; 
事务2	START TRANSACTION; 
		UPDATE StockPrice SET high = 20.12 WHERE stock_id = 3; 
		UPDATE StockPrice SET high = 47.20 WHERE stock_id = 4; 
	COMMIT;
两个事务都等待对方释放锁, 同时又持有对方需要的锁

InnoDB目前处理死 锁的方法是,将持有最少行级排他锁的事务进行回滚(这是相对比较简单的死锁回滚算法)。

1.3.3事务日志

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

1.3.4mysql中的事务

在事务执行过程中,随时都可以执行锁定,锁只有在执行COMMIT 或者ROLLBACK 的时候才会释放,并且所有的锁是在同一时刻被释放。前面描述的锁定都是隐式锁定

InnoDB也支持通过特定的语句进行显式锁定,这些语句不属于SQL规范 (3) :

SELECT ... LOCK IN SHARE MODE 

SELECT ... FOR UPDATE 

1.4 多版本并发控制

MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC)。

可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行

InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或 删除时间)。当然存储的并不是实际的时间值,而是系统版本号(system version number)

优点:保存这两个额外系统版本号,使大多数读操作都可以不用加锁

不足之处:是每行记录都需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作

MVCC只在REPEATABLE READ 和READ COMMITTED 两个隔离级别下工作,SERIALIZABLE 则会对所有读取的行都加锁

1.5 MySQL的存储引擎

1.5.5 选择合适的引擎

事务:InnoDB(或者XtraDB)

备份:如果需要在线热备份,那么选择InnoDB就是基本的要求

崩溃恢复:MyISAM崩溃后发生损坏的概率比InnoDB要高很多,而且恢复速度也要慢

1.5.6 转换表的引擎三种方法
  1. ALTER TABLE
ALTER TABLE mytable ENGINE=InnoDB;如果转换表的存储引擎,将会失去和原引擎相关的所有特性

​ 2.导出与导入

mysqldump 工具将数据导出到文件,然后修改文件中CREATE TABLE 语句的存储引擎选项,注意同时修改表名同时要注意mysqldump默认会自动在CREATE TABLE 语句前加上DROP TABLE 语句

​ 3.创建与查询(CREATESELECT)第三种转换的技术综合了第一种方法的高效和第二种方法的安全

mysql> CREATE TABLE innodb_table LIKE myisam_table; 
mysql> ALTER TABLE innodb_table ENGINE=InnoDB; 
mysql> INSERT INTO innodb_table SELECT * FROM myisam_table;

第2章 MySQL基准测试

2.1 为什么需要基准测试

因为基准测试是唯一方便有效的、可以学习系统在给定的工作负载下会发生什么的方法

2.2 基准测试的策略

集成式(full-stack):针对整个系统的整体测试

单组件式(single-component):单独测试MySQL

2.2.1 测试何种指标

吞吐量 :吞吐量指的是单位时间内的事务处理数要针对在线事务处理 (OLTP)的吞吐量,常用的测试单位是每秒事务数(TPS)

响应时间或者延迟 :这个指标用于测试任务所需的整体时间

并发性 :

可扩展性:

2.3 基准测试方法
2.4 基准测试工具
集成式测试工具

ab是一个Apache HTTP服务器基准测试工具 http_load JMeter

单组件式测试工具

mysqlslap测试时可以执行并发连接数,并指定SQL语句

MySQL Benchmark Suite(sql-bench) 主要用于测试服务器执行查询的速度。结果会显示哪种类型的操作在服务器上执行得更快

第4章 Schema与数据类型优化

4.1 选择优化的数据类型

更小的通常更好

简单就好

尽量避免NULL :可为NULL 的列会使用更多的存储空间,在MySQL里也需要特殊处理

4.1.1 整数类型

TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT 。分别使用8,16,24,32,64位存储空间

整数类型有可选的UNSIGNED 属性,表示不允许负值,这大致可以使正数的上限提高一倍

4.1.2 实数类型

FLOATDOUBLE 类型支持使用标准的浮点运算进行近似计算,浮点类型在存储同样范围的值时,通常比DECIMAL使用更少的空间

DECIMAL类型用于存储精确的小数

4.1.3 字符串类型

VARCHAR 类型用于存储可变长字符串,是最常见的字符串数据类型。它比定长类型更节省空间,因为它仅使用必要的空间,VARCHAR 需要使用1或2个额外字节记录字符串的长度,如果列的最大长度小于或等于255字节,则只使用1个字节表示,否则使用2个字节

VARCHAR 合适的:字符串列的最大长度比平均长度大很多;列的更新很少,所以碎片不是问题;使用了像UTF-8这样复杂的字符集,每个字符都使用不同的字节数进行存储

CHAR 类型是定长的:MySQL总是根据定义的字符串长度分配足够的空间,采用空格进行填充

CHAR 适合存储很短的字符串,或者所有值都接近同一个长度。例如CHAR 非常适合存储密码的MD5 值,因为这是一个定长的值。对于经常变更的数据,CHAR 也比VARCHAR 更好,因为定长的CHAR 类型不容易产生碎片

使用VARCHAR(5) 和VARCHAR(200) 存储’hello’ 的空间开销是一样的。那么使用更短的列有什么优势吗?

更长的列会消耗更多的内存,因为MySQL通常会分配固定大小的内存块来保存内部值

4.1.4 日期和时间类型

DATETIME精度为秒。它把日期和时间封装到格式为YYYYMMDDHHMMSS的整数中, 与时区无关。使用8个字节的存储空间

TIMESTAMP只使用4个字节的存储空间

除了特殊行为之外,通常也应该尽量使用TIMESTAMP,因为它比DATETIME 空间效率更高

4.1.5 位数据类型

BIT可以使用BIT 列在一列中存储一个或多个true/false值

SET 如果需要保存很多true/false值,可以考虑合并这些列到一个SET 数据类型

4.1.6 选择标识符(identifier)

整数类型:整数通常是标识列最好的选择,因为它们很快并且可以使用AUTO_INCREMENT 。

4.1.7 特殊类型数据

某些类型的数据并不直接与内置类型一致。

低于秒级精度的时间戳就是一个例子

另一个例子是一个IPv4地址。人们经常使用VARCHAR(15) 列来存储IP地址。然而,它们实际上是32位无符号整数,不是字符串。用小数 点将地址分成四段的表示方法只是为了让人们阅读容易。所以应该用无 符号整数存储IP地址。MySQL提供INET_ATON() 和INET_NTOA() 函数在这两种表示方法之间转换

4.2 MySQL schema设计中的陷阱

太多的列现客户使用了非常宽的表(数千个字段),然而只有一小部分列会实际用到,这时转换的代价就非常高。如果计划使用数千个字段,必须意识到服务器的性能运行特征会有一些不同

太多的关联一个粗略的经验法则,如果希望查询执行得快速且并发性好, 单个查询最好在12个表以内做关联

全能的枚举注意防止过度使用枚举(ENUM )。下面是我们见过的一个例子:

CREATE TABLE … (

country enum(’’,‘0’,‘1’,‘2’,…,‘31’)

4.3 范式和反范式

在范式化的数据库中,每个事实数据会出现并且只出现一次。相反,在反范式化的数据库中,信息是冗余的,可能会存储在多个地方

4.3.1 范式的优点和缺点
优点

经常会被建议对schema进行范式化设计,尤其是写密集的场景

1.范式化的更新操作通常比反范式化要快。

2.当数据较好地范式化时,就只有很少或者没有重复数据,所以只需要修改更少的数据。

3.范式化的表通常更小,可以更好地放在内存里,所以执行操作会更快。

4.很少有多余的数据意味着检索列表数据时更少需要DISTINCT或 者GROUP BY 语句。还是前面的例子:在非范式化的结构中必须使 用DISTINCT 或者GROUP BY 才能获得一份唯一的部门列表,但是如 果部门(DEPARTMENT )是一张单独的表,则只需要简单的查询这张表就行了

缺点

范式化设计的schema的缺点是通常需要关联。稍微复杂一些的查询语句在符合范式的schema上都可能需要至少一次关联

4.3.2 反范式的优点和缺点
优点

反范式化的schema因为所有数据都在一张表中,可以很好地避免关联

单独的表也能使用更有效的索引策略

4.5 加快ALTER TABLE操作的速度

MySQL执行大部分修改表结构操作的方法是用新的结构创建一个空表,从旧表中查出所有数据插入新表,然后删除旧表

修改表结构:

一种是先在一台不提供服务的机器上执行ALTER TABLE 操作,然后和提供服务的主库进行切换;

另外一种技巧是“影子拷贝”。影子拷贝的技巧是用要求的表结构创建一张和源表无关的新表,然后通过重命名和删表操作交换两张表;

第5章 创建高性能的索引

索引(在MySQL中也叫做“键(key)”)是存储引擎用于快速找到记录的一种数据结构

5.1 索引基础

B-Tree索引 :B-Tree索引能够加快访问数据的速度,因为存储引擎不再需要进行全表扫描来获取需要的数据

哈希索引哈希索引(hash index)基于哈希表实现,只有精确匹配索引所有列的查询才有效

5.2 索引的优点

\1. 索引大大减少了服务器需要扫描的数据量。

\2. 索引可以帮助服务器避免排序和临时表。

\3. 索引可以将随机I/O变为顺序I/O。

5.3 高性能的索引策略

第10章 复制

10.1 复制概述

MySQL支持两种复制方式:基于行的复制和基于语句的复制

两种方式都是通过在主库上记录二进制日志 、在备库重放日志的方式来实现异步的数据复制。这意味着,在同一时间点备库上的数据可能与主库存在不一致,并且无法保证主备之间的延迟

10.1.1 复制解决的问题

数据分布

负载均衡:DNS轮询(将一个机器名指向多个IP地址)LVS

备份

高可用性和故障切换

10.1.2 复制如何工作

\1. 在主库上把数据更改记录到二进制日志(Binary Log)中(这些记录被称为二进制日志事件)。

\2. 备库将主库上的日志复制到自己的中继日志(Relay Log)中。

\3. 备库读取中继日志中的事件,将其重放到备库数据之上。

10.2 配置复制

\1. 在每台 (3) 服务器上创建复制账号。

\2. 配置主库和备库。

\3. 通知备库连接到主库并从主库复制数据

10.2.1 创建复制账号

mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON .

-> TO repl@‘192.168.0.%’ IDENTIFIED BY ‘p4ssword’,;

10.2.2 配置主库和备库

主库

log_bin = mysql-bin

server_id = 10

备库

log_bin = mysql-bin

server_id = 2 (必要)

relay_log = /var/lib/mysql/mysql-relay-bin| Chapter 10:Chapter 10: Replication Replicationlog_slave_updates = 1

read_only = 1

10.2.3 启动复制

CHANGE MASTER TO

mysql> START SLAVE;

mysql> SHOW SLAVE STATUS\G

mysql> SHOW PROCESSLIST\G

10.2.4 从另一个服务器开始复制

需要有三个条件来让主库和备库保持同步:

在某个时间点的主库的数据快照。

主库当前的二进制日志文件,和获得数据快照时在该二进制日志文件中的偏移量,我们把这两个值称为日志文件坐标(logfilecoordinates)。通过这两个值可以确定二进制日志的位置。可以通过SHOW MASTER STATUS命令来获取这些值。

从快照时间到现在的二进制日志。

使用冷备份

使用热备份

使用mysqldump

使用快照或备份

使用Percona Xtrabackup

R TO

mysql> START SLAVE;

mysql> SHOW SLAVE STATUS\G

mysql> SHOW PROCESSLIST\G

10.2.4 从另一个服务器开始复制

需要有三个条件来让主库和备库保持同步:

在某个时间点的主库的数据快照。

主库当前的二进制日志文件,和获得数据快照时在该二进制日志文件中的偏移量,我们把这两个值称为日志文件坐标(logfilecoordinates)。通过这两个值可以确定二进制日志的位置。可以通过SHOW MASTER STATUS命令来获取这些值。

从快照时间到现在的二进制日志。

使用冷备份

使用热备份

使用mysqldump

使用快照或备份

使用Percona Xtrabackup

使用另外的备库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值