MySQL深入的学习笔记

MYSQL高级:

MySql架构演变,这个很重要,软件的环境是如何从单应用算法极致优化的方向,到分布式的进化,这个时代,就会淘汰好多单体应用的coder,比如我自己...哈哈哈哈
1.0时代:单机单库 单应用,单数据库.快速,方便.好维护. 并发量小,拓展性差,数据量大无法承受,数据库崩溃直接导致数据丢失.运算能力差
2.0主从复制: 一个主数据库,多辅助数据库,主库崩溃,从库立即顶上,保持可用性,进行读写分离,保证性能平均,也有缺点.数据量大的问题还是没有解决.主从复制数据是一样.写入的操作还是比较慢,因为只有一个主库可以写入,然后同步到从库.其余都是查的从库,大量insert 主从复制就不行了
3.0分库分表:将主从复制进行分布式,但每个主从各负责整体应用数据库的一部分.比如A表300条数据,可在三个分布式进行存储,A分布100条,B分布100条,C分布100条,也可将A表直接存在一个分布下.B表存在另一个分布下.提高整体应用存储能力,但也有一个新的问题.这些数据库如何保持一致性?如何通讯?
4.0云数据库 不再有本地数据库,将数据库做为服务, 我们使用服务接口,云服务商来决定数据如何存储和存储在哪.这是一个趋势,云生态替我们解决了很多成本问题.
MySql架构:

在这里插入图片描述

也就是一条sql语句的执行流程
客户层:
	客户连接器:JDBC等连接的.
服务层:
	 连接池:与客户层连接的直接层次.提供线程池等,使用线程池会将性能提升3倍.读写会提升60倍.
	 管理工具:控制和管理数据库的工具
	 SQL接口:DML,DDL等接受sql语句
	 parser 解析器:解析SQL语句的模组,分为语法分析和词法分析,先解析词,后解析语法.
	 optimizer 查询优化器:解析后,交给优化器,负责提供执行计划,选出最佳的计划来进行执行.
	 	优化器的例子:
	 		1select根据where进行选取筛选.
	 		2select根据字段进行属性投影,选出需要的字段,不全拿
	 		3:把上面两步合起来展示
	缓存:将表、查询、引擎进行缓存,如果缓存符合,那么不用直接去文件存储去获取了就
存储引擎层:
	关键词:可插拔 可以修改源码达到自己的目的(太高大了)
	服务层与文件系统衔接的层,根据不同的存储引擎有着不同的存储机制.
系统文件层:
	存储数据、日志、配置.是数据库数据的最终归宿
	日志:
		错误日志
			默认开启.show variables like %log_err% 查询错误文件的存储位置..
		通用查询日志
			记录查询语句.使用show variables like '%general%'
		二进制日志
			记录更改的操作. 不记录select的所有操作.记录语句发生时间,执行时长.
			show variables like '%log_bin%'
			show variables like '%bin_log%' 更高级的二进制日志
			show binary logs; 查看日志文件
		慢查询日志:
			记录所有执行时间超时(默认10s)的查询sql.
			show varables like '%slow)query%'
			show varables like '%long_query_time%'
			set long_query_time = 5 设置超时时间.
	配置文件:
	数据文件:
		数据的存储
		db.opt 字符集和校验规则
		frm meta信息 每个表都一个frm
		myd myisam专用 存储data
		myi myisam 存储索引
		ibd、ibdata  innoDb的存储data和索引 ibd独享表空间  ibdata共享表空间
		ibdata1: 原始数据、undo
		show varables like '%datadir%' 来查看数据存储的文件夹

mysql的详细执行流程:

在这里插入图片描述

1:客户端连接
	通信机制:
		全双工:发数据时也接收数据
		半双工:某一时间点发或着接,不能同时
		单工:只能发或者接,不能两者都行
	show full processlist 查看当前连接的线程信息
	id:线程ID,可以kill掉他
	user:用户
	host:客户端主机
	db:操作哪个库
	time:连接时间
	command:当前用户正在执行的操作,query执行语句啦.createDB建库啦,execute 执行stmt啦
	state:当前用户的状态 updating 正在修改 starting正在执行请求 closing table正在存储 Locked 锁住状态 Sending Data 正在select
	info:当前执行的语句
2:查询缓存
	缓存之前的查询结果,如果命中直接返回.只缓存sql语句和结果.只有sql完全相同才会命中缓存.
	show variables like %query_cache%
	show status like Qcahce%
	不能缓存的情况
		sql语句添加sql_no_cache
		结果大于query_cache_limit
		不确定的参数 now()
3:解析器->解析树->预处理->新解析树
4:查询优化器->执行计划
	等价变换策略 将一些条件进行更直观转换
	联合索引调整条件位置
	函数优化
		inno DB min函数只找索引最左边
		inno DB max函数只找索引最右边
		myisam引擎 count(*) 不需要计算,直接返回
		limit 提前停止查询 拿到limit够的量就不继续遍历了(查询其实就是遍历存在磁盘的数据,只不过用特定的语法查询,就是sql)
		in 会先排序,然后二分法查找数据,先把in里的参数排序,然后二分法快速查找
5:查询执行引擎->存储引擎->存储文件
	1.如果开启查询缓存了,那么第一次查询放入缓存,第二次查询时就先去查缓存.只能是同一sql 参数都一样的.
6:返回结果
	2.存储引擎是有一定的增量返回的,如果结果过多,那么引擎会进行一定的控制进行逐步返回.

MySQL的存储引擎:

负责与具体的存储系统进行交互,执行sql、拿出存储的文件,都是引擎的工作.
InnoDB:支持事物:提交、回滚、崩溃恢复、事物安全
MyISAM:不支持事物和外键,访问速度更快
Memory:速度极快,数据存储在内存,默认使用Hash索引.关闭既消失
Archive:归档类型引擎,只能支持insert和select
Csv:类似于表格型的格式存储,由于被格式限制,所以列不能为null,不支持索引和分区,适合数据传输
BlackHole:黑洞引擎,只进不出,insert的数据不会保存.但是会有insert记录,可以查询到
Federated:远程的数据库的表.本地表不保存数据,通过远程来返回,oracle的link机制.
MRG_MyISAM:一组MyISAM的表,结构相同,操作一个 对所有的表都生效.
InnoDB和MyISAM的对比:
1.事物和外键:
	InnoDB支持,大量新增和更新,强调安全和数据完整
	MyISAM不支持,高速的检索和存储.
2.锁机制:
	InnoDB支持行级锁,可以锁定具体的一条记录,基于索引加锁.
	MyISAM支持表级锁,表内所有数据都被锁定
3:索引结构
	InnoDB聚集索引,索引和记录存储在一块,缓存索引也缓存记录
	MyISAM索引和记录是分开的,所以查询较快.
4:并发处理能力:
	MyISAM是表级锁,并发写入性能低下
	InnoDB行级锁,大量新增性能较好,
		相比下他们俩更新具体一条记录时,性能持平,比如库存控制,现在基本也不这么设计了,都是用消息中间件或者中间缓存来延迟更新数据库.减轻数据库的压力.
5:存储文件
	InnoDB对应两个文件,一个.frm表结构文件,一个.idb数据文件
	最大支持64TB
	MyISAM多一个 一个.frm表结构文件,一个.MYD数据文件,一个.MYI索引文件.256TB最大存储(5.0以上)
应用场景:
	MyISAM:高速查询、不需要事物、并发低、数据一致性要求低
	InnoDB:数据安全、行级锁提高并发能力、事物控制、大量新增、提升服务器内存利用率.
	普遍场景:推荐使用InnoDB

InnoDB存储引擎:

在这里插入图片描述

存储结构:
结构一.内存结构:
		buffer pool缓存池:存放缓存和配置.
			详细剖析:
				1)管理机制:
					1>free page 空闲page,未被使用
					2>clean page 被使用page,但没有被修改
					3>dirty page 脏页:被使用,被修改,与磁盘不一致
				用三种链表结构来管理这三个page, 
					freelist->free page
					flushlist->dirty page 脏页的  按修改时间排序.最早在后,先更新磁盘,寄存在lrulist中,但互不影响
					lrulist -> 正在使用的 clean page 和 dirty page,以midpoint为中点,左面为new列表,存放经常访问的数据.占63%右面为old,存放不咋用的,要被清掉的.占37%
				2)采用改进型LRU算法维护:
					普通LRU:末尾淘汰法,新数据进入头,释放空间从末尾释放.
					改进LRU:链表分为new和old的,添加不从头,而从中点插入,数据被访问了,那么就从中点开始左移,如果没怎么被访问,那么就会被挤压到中点右面,等待被释放.
					每当有新的page数据放入缓存池,InnoDB先判断有没有足够的free page,如果有就删除free list中的数据,然后放到LRU,如果没有了,那么LRU末尾就会开始释放,够了再插进来.
				3)配置参数
					show variables like '%innodb_page_size%'page大小
					show variables like '%innodb_old%'  lru old的参数
					show variables like '%innodb_buffer%' 查看所有参数
					缓存池的存储模块嵌套关系buffer->instance->chunk ->page
					buffer推荐占物理内存的60-80% instance按需增加数量, page微量调整
		change buffer 写缓存:负责存储新增和更新的缓存,避免频繁的磁盘操作,先对比缓存池中已有数据,,然后更新的数据放这,闲置时再更新入磁盘.
			占用buffer pool空间 默认占25%,最大允许50% 根据写入量进行调整.
			show variables like '%innidb_change_buffer_max_size%' 查看当前cb占比
			set global innodb_change_buffer_max_size = 占比数 
			这个有用啊,目前开发的应用就需要大量的新增和更新操作,innoDB符合要求,再配合将changebuffer缓冲区调高,增加写入缓冲的大小,可以提高写入性能.
			如果更新记录时 记录在buffer pool存在 就直接在buffer pool修改 并成为dirdy page,需要磁盘操作.如果没存在, 那么就直接存在change buffer,省下一次磁盘IO,如果下次查询时,会先磁盘读取,然后与change buffer数据进行合并, 最终存储在bufferpool中.
			(自我总结)就是尽量省下磁盘IO,因为磁盘的性能远不如内存性能快速,在高频使用的数据就主要放入内存中提供频繁的访问,而不常用的就持久化到磁盘存储.
			change buffer 仅仅使用非唯一普通索引.带主键或者唯一索引的进行修改时,innoDB需要做校验,这样就避免不了磁盘IO,所以带主键的表必须要磁盘获取了.但也是放入缓冲池 buffer pool修改.不会有change buffer这一操作了.
		log buffer日志缓存区:负责存储操作记录.存储一定数量更新到磁盘.也有计划更新到磁盘
			redo、undo日志.一般为16M大小(默认不是),过大会影响崩溃恢复的能力.
			记录引擎日志.记录dml的redo undo日志.
			show variables like '%innodb_log%'
			show variables like '%innodb_flush_log%'
			写入磁盘策略 默认1
				0:每隔1秒进行写日志和刷盘操作 流程:log buffer-> OScache ->DISK
				1:事务提交 就刷盘,频繁操作.
				2:事物提交 就写日志 每隔一秒刷盘(兼顾,推荐使用)
		自适应hash索引:监控缓存池的索引使用情况,进行自动调整.
结构二.磁盘结构:
		system tablespcaes系统表空间
			show variables like '%innodb_data_file_path%'查看
			innoDB Data Dictionary:
			Doublewrite buffer:
				show variables like '%innodb_doublewrite%'
				脏页先写到这里的缓冲区,防止系统的磁盘出现问题,写入速度也较快.
			Undo Logs:
				撤销日志.记录一些我们的一些操作,在必要时可以进行回滚.
		File-Per-Table-Tbablespaces独立表空间
			show variables like '%innodb_data_file_pre_table%'查看
		General Tablespaces 通用表空间
			create tablespace {name} add datafile '{name}.ibd' engine innoDB创建表空间 并使用innoDB引擎
		Undo Tablespaces 回滚表空间

在这里插入图片描述

5.7与8.0的改变:
	磁盘存储结构更改:
		删除了表结构在系统表空间的存储.和frm存储有重叠,所以去掉了
		8.0的系统表空间只保留了change buffer
		doublewrite 单独分出
		undo日志和undo表空间合并.
		临时表空间细化区分 分为了全局和会话
innoDB的后台线程:

在这里插入图片描述

	master thread 主线程:
		调度其他三个线程,通过调用其他线程来实现工作,主线程不会被阻塞,如果有关闭的线程,那么该线程的工作还是主线程来做.内部有两个主处理,每隔一秒和每隔十秒
		一秒的操作:
			刷新日志缓冲区到磁盘
			合并change buffer 根据IO读写压力决定是否操作
			刷新脏页. 根据脏页比例, 达到75%再操作.  show varables like '%innodb_max_dirty_pages_pct%' 查看百分比
			show varables like '%innodb_io_capacity%' 查看可刷新写入多少页(page块)
		十秒的操作:
			脏页刷新到磁盘,没有限制了,必须做
			合并change buffer 直接做
			刷新日志缓冲到磁盘
			删除无用的undo页
			show varables like '%innodb_purge_batch_size%' 查看删除无用undo一次的数量
	IO thread AIO机制: 10个线程
		read负责读取操作,从磁盘加载到缓存 4个
		write负责写入操作.缓存脏页刷新到磁盘中. 4个
		log thread 日志缓存刷新到磁盘 1个
		insert buffer thread :change buffer的内容写入到磁盘 1个
	purge thread:
		show variables like '%innodb_purge_thread%'
		负责回收已经提交的undo页, 可以关闭
	page cleaner thread:
		show variables like '%innodb_page_cleaners%'
		将脏页写入到磁盘.会调用write线程.释放redo log
innoDB数据文件:

在这里插入图片描述

	文件存储结构:
		Tablespace:
			表空间存储多个ibd数据文件,存储表的记录和索引,一个文件包含多个段
		Segment:
			管理多个extent,分为数据段(leaf node segment)、索引段(Non-leaf node segment)、回滚段(rollback segment),一个表至少有两个segment 数据和索引,每多一个索引,就会多两个segment(索引和非索引)
		Extent:
			区的概念,固定包含64个连续的Page,大小为1M,当表空间不足,需要分配新的页资源时,会直接增加一个区,不会增加一个page,类似于地砖,你只能买一整块,不能买一个碎块
		Page (最基本的单位):
			页,存储多个row记录,大小为16k,包含数据page,undo page,系统page,事物page,大的blob对象page
			具体结构:
				header 头信息
				body 具体的row
				trailer 尾部信息
		Row:
			行,包含了该行的每个字段值,事物ID trx id, 滚动指针(roll pointer),不同session修改同一行数据的记录行为,形成一个链方便回滚.字段指针(field pionter)
	文件存储格式:
		查看的命令:
		show table status; 在具体库中使用
		select * from information_schema.innodb_sys_tables;
		文件的格式是根据行格式来决定的,行格式为REDUNDANT、COMPACT对应Antelope,行格式为Dynamic和compressed对应Barracuda
		innodb文件格式:Antelope和Barracuda
		innodb行格式:Redundant、COMPACT、Dynamic、compressed
		Redundant:
			将变长列的前768b存在B树节点的索引记录中.其余在溢出页对与大于等于786b的也会转换为变长字段.方便溢出页存储
		COMPACT:
			与Redundant区别于 compact是紧凑型.但会增加CPU压力
		Dynamic:
			全都放到溢出页,索引记录只记录指向溢出页的指针.支持大索引引擎,最多为3072字节. 通过innodb_large_refix参数控制
		Compressed:
			针对Dynamic做高效压缩.其余功能一致.
		修改row format:
			alter table table_name row_format=format_name;
			中途修改行格式不会影响之前的数据.
Undo Log:

在这里插入图片描述

undo就是撤销操作.回复到某个状态.
当事物开始之前,undo log会存储将要改变的记录和操作,当回滚时就可以利用undo log,事物提交前 undo log就会生成,  提交后并不会立即删除,而是把undo log放入删除列表中,等待 后台线程purge thread的删除处理,Undo log 属于逻辑日志,记录变化的过程.比如新增操作, undo log将会记录一个 delete操作, 反之一样.
采用段的方式管理和记录,在innodb数据文件中包含一种rollback segment回滚段,里面包含1024个 rollback segment
show varables like '%innodb_undo%' 查看undo log 的信息,
作用:
	实现事物的回滚.
	多版本并发控制(MVCC)
Redo log:

在这里插入图片描述

Redo:重做.当数据库发生问题时,redo可以重新做一次之前的操作.数据修改之后的信息记录在redo log中.
rodo log的生成:事物提交是先将修改数据存入change buffer,这时生成redo log,当该数据进入脏页
rodo log的释放:刷入磁盘时,对应的该条redo log 才会释放, 新的修改事物来后 该条redo log将被覆盖写入
Redo解决的问题:
	如果没有redo log的机制,那么每次更新都要执行IO去刷新磁盘,而磁盘数据的位置不是整齐的摆放,而是随机位置的,这样就会增加IO的时间降低了效率,而将更新的数据顺序放入redo log,redo log再去IO 刷新磁盘,在一定意义上就是顺序IO,提升效率.

在这里插入图片描述

Redo log写入机制:
	顺序循环方式写入文件,把所有log文件写满了后,从头开始覆盖写入.
Redo log相关配置参数:
	show variables like '%innodb_log%'
	至少有一个group日志, 一个group可有多个.默认2个
	buffer刷新到redo log文件的策略:
		0:事物提交就会写入log buffer,后台线程每秒刷新到OS cache再到磁盘的log文件.
		默认1:提交时直接写入到buffer和OS cache,同时异步刷新到log文件.
		2:提交时直接写到buffer和OS cache,但不启动任务刷新到log文件,等后台进程一秒刷新到log文件.
	show variables like '%Inoodb_flush_log_at_trx_commit%' 来查看当前的策略.
Bin log:
redo log 是innodb引擎的功能,bin log是数据库的日志.负责记录表结构变更和数据修改的二进制日志.
默认是关闭的,以事件形式记录
应用场景:
	主从复制:主库开启bin log,传递给从库.从库根据bin log进行数据恢复来达到数据一致.
	数据恢复:灾难恢复,删库删表的情况,可以通过bin log文件来恢复数据和表结构
命名:默认主机名_binlog-序列号格式 也可以指定名称,
文件模式:
	ROW格式:记录每一行数据被修改的情况,在slave端对相同的数据进行修改. 
		可靠、清楚记录修改细节,完全实现主从复制.
		批量操作会占用大量空间,尤其修改表结构,日志暴增.
	STATMENT格式:记录每一条修改的SQL.简称SQL复制.
	日志量较低,但是sql有变化值(last_insert_id()、now())的话,那么数据一致性就无法保证了.
	MIXED格式:混合模式,两种模式混合使用,一般使用statment,一致性无法保证时使用row格式.根据sql语句决定使用哪种格式.
文件结构:
事件:query、row、xid等.
一个一个的事件组成了bin log文件.
事件的结构:
	timestamp 开始时间
	event type 事件类型
	server_id 服务器的id
	event size 事件长度
记录机制:
1:执行操作会触发event事件生成log event(事件出发机制)
2:将log event写入缓冲区,每个事物线程都有一个缓冲区.query有query的这样.)
	每个event保存在binlog_cache_mngr数据结构中,在该结构中有两个缓冲区,一个是stmt_cache,用于存放不支持事务的信息;另一个是trx_cache,用于存放支持事务的信息。
3:事物提交阶段会产生log event写入到外部的binlog文件
	不同事物以串行方式写入binlog文件,是时间连续性的,不会被插入
binlog的一些操作:
状态查看:
	show variables like '%log_bin%'
-针对只读的属性,只能去修改配置文件.cnf和.ini文件
开启:
	log_bin:ON
	log_bin_basename=binlog文件名
	binlog-format=记录格式 ROW
查看文件状态:
	show master status 查看文件
	show 查看当前写入的文件名
	show binlog events 查看事件
查看binlog文件(全局):
	mysql目录/data下:mysqlbinlog "binlog文件名" >"输出到的文件名称"
恢复数据:
	按照事件位置号恢复:
		mysqlbinlog --start--position=位置号 --stop--position=位置号 binlog文件名 | mysql -u 用户名 -p 密码(不写就没警告,敲回车再输入密码一样的)
	按照时间节点恢复:
		mysqlbinlog --start--datetime=时间节点 --stop--datetime=时间节点 binlog文件名 | mysql -u 用户名 -p 密码(不写就没警告,敲回车再输入密码一样的)
	定期备份数据库数据:
		可定期做增量备份和恢复,用这些命令备份到另一个库
删除binlog:
	purge binary logs to 'binlog文件'
	purge binary logs before '时间节点'
	reset master 清空所有binlog文件
	自动清理:
		定时清理:
			show variables like 'expire_logs_days' 默认0 可set groble expire_logs_days 来设置多少天清理一次
binlog与redo log的区别:
相同点:
	都是用于恢复一些之前的操作,记录一些曾经修改的数据记录.
区别:
	redolog是innodb引擎的,binlog是mysql数据库的二进制的文件,级别不一样
	redolog是物理日志记录具体数据.binlog记录是逻辑日志,以事件为基础,记录一些操作过程.
	redolog是循环写入,空间大小是固定,binlog是追加写入,写满一个文件写下一个.
	redolog做为服务器异常宕机的情况下短期数据丢失的自动恢复.binlog做为主从复制和灾难恢复的.没有自动的崩溃恢复.需要手动操作.

MySQL的索引:

提升查询速度,影响where查询以及order by排序.
存储结构划分:B tree索引,hash索引、fulltext全文索引、R Tree索引(Btree的多维空间)
应用层次划分:普通索引、唯一索引、主键索引、复合索引
索引键值类型:主键索引、辅助索引(二级索引)
从数据存储和索引值逻辑关系划分:聚集索引(聚簇索引)、非聚集索引(非聚簇索引)
索引的分类:
	普通索引:normal index: 
		create index <索引的名字> ON tablename(filed name)
		alter table tablename add index [indexname](fieldname)
		create table tablename(field... index[indexname])
		show index from tablename 查看当前表的索引
		drop index indexname from tablename 删除指定name索引,不写就全删
	唯一索引:unique index
		允许null 
		增加和普通索引一样, 就是index前多了个unique
	主键索引:primary
		not null + unique的组合索引. 表中只能有一个.
	复合索引:
		多个字段组成的索引,当查询时某几个字段需要组合查询时,可以将这几个的单索引合成为一个复合索引.
		窄索引和宽索引:1-2列为窄索引,超过两列为宽索引.
	全文索引:
		在varchar或者textarea上建立
		数据量小时可用like,但数据量大时就需要使用全文索引了
		创建该索引多添加一个关键字 fulltext 
		使用:
			select * from table where match(field) against('str');
		索引建立条件:
			innodb引擎使用全文索引时,建立索引的最小大小默认是3个字符,最大为84个字符,myisam为4-84.不满足的话都不会建立索引,所以无法查询出结果,通过 show variables like '%ft%' 可以查看 myisam和innodb的全文索引相关参数.
			只能通过配置文件修改了.属性都是只读的
		切词语法:
			检索的字符中含有一些指定的切分符号,才会匹配成功查询出来,否则不会查询出来
		匹配结果:
			默认是精确匹配(等值匹配) 需要使用*,再改成 in boolean mode才会实现类似于like '%%'的查询结果
索引的原理:
用于快速查找的一种数据结构,但需要额外的空间和维护.
存储位置:
	物理数据页存储,在数据文件中 innodb就是ibd文件.利用page存储.
可以加快检索的速度.但是会降低插入操作的速度,因为需要修改索引.
理论:
	二分查找、hash查找、B+tree.
	二分查找:
		优点:等值查询、范围查询速度快
		缺点:插入数据成本高.
		原理:
			定位left和right
			除2计算 出中位数与目标值比大小,大了就把左指针的位置变为中位数的位置+1(排除中位左侧区间),小了就把右指针的位置变为中位数的位置-1(排除中位右侧区间)

在这里插入图片描述

	hash查找:
		将字段值做hash计算后存储hash值,当查询等值数据时直接使用hash值进行查询,适合高速的等值查询.但范围查询速度就不会很快了.
		memory引擎原生带hash索引,innodb有自适应hash索引.
		自适应hash索引:
		会根据数据访问的频率和模式进行自动的创建索引.无法认为干预.
		使用hash索引访问时,一次查找就能直接定位到数据,等值查询时性能高于B+tree.
		show engine inndb status; 查看索引相关信息
		释放自适应hash索引:
		show variables like '%innodb_adaptive%'.
		set innodb_adaptive_flushing  =0 关闭自适应hash索引

在这里插入图片描述

	B+tree查找:
		普遍采用.在Btree结构上优化而来.
		Btree的特性:
			索引值和数据分布在树中.
			每个节点可存放多个数据和索引值.
			有序排列(左至右)
		流程:
			从根节点进行搜索,采用二分查找.没有找到继续深入查询子节点进行二分,找到了就完成. 一直找到指针为null或者为叶子节点了,那么查找完成没有找到数据.

在这里插入图片描述

		B+tree的特性:
			非叶子节点不存储数据,只存储索引值.
			叶子节点存储所有的数据和索引值.
			每个叶子节点指针连接,提高区间访问
		流程:
			与Btree一致.
	与Btree对比,B+tree不需要遍历所有的数据,而且每个叶子节点之间有指针关联,查询效率更快.但在等值查询时,Btree的速度相对来说会优于B+tree,因为非叶子节点存储数据,查询时等值到根节点时,直接查找完成.再插入时,B+tree的IO操作将会更低.因为只有叶子节点存储数据.

在这里插入图片描述

聚簇索引和非聚簇索引、主键索引和辅助索引:
聚簇索引:
	索引值和行记录存储在一起.
	主键索引:
		一种聚簇索引,按照主键顺序构架B+tree结构.叶子节点的数据就是整行记录.innodb的表必须要有聚簇索引.有主键了,那么就有了聚簇索引,如果没主键,那么第一个unique列作为聚簇索引.如果还没有,innodb会创建一个隐藏的row-id作为聚簇索引,表中只能有一个聚簇索引.
	辅助索引(二级索引、普通索引):
		一种聚簇索引,也是B+tree结构.叶子节点只存储了索引列和主键的信息.表中可以有多个.查询时如果通过该索引查询时,通过值获取到该值的主键索引,再通过主键索引来获取整条记录.
非聚簇索引:
	索引和数据分开存储.
索引分析与优化:
explain命令:
	用来测试某一条sql的执行性能. 里面显示了详细的sql执行时的一些相关信息,如使用到的索引、查询的条数.
	重要参数解析:
		select_type:查询类型:
			simple简单,不包含子查询与合并 -常见
			primary最外层查询
			union合并查询或后续查询
			depedent union后续查询使用到了外面的查询条件.依赖外面一层的条件
			union result 合并查询的结果
			subquery子查询语句
			depedent subquery依赖外面查询结果的子查询.
		type:存储引擎查询时采用的方式.是全表扫描还是部分扫描,从上到下效率不断增强,null最强.
			all:全表扫描,性能最低
			index:索引查询,基于索引查询,先扫索引再扫全表.
			range:使用索引范围查询,用了 大于小于等号in等等.只扫描一个范围了
			ref:使用非unique索引进行单值查询.单个结果就是ref,多个结果还是all
			eq_ref:多表join查询,每个记录都只能匹配后面一行结果.
			const:使用主键或者唯一索引做等值查询.
			null:表示不用访问表.dual的查询.
		possible_keys:查询能够使用到的索引,不一定真正使用到
		key:实际使用到的索引.
		rows:扫描的行数,表示你这个sql要查询到结果需要扫描多少行(估算值).比如要查询出N条数据,那么最快的查询rows就应该是接近于N或者微微大于N,要是查10条扫描10000行,那这个sql效率就很低了
		key_len:表示查询使用了索引的字节数量,可判断组合索引长度的使用占比.
			规则:
				字符串类型:跟字符集有关,
					latin1=1、
					gbk=2、
					utf8=4、
					utf8mb4=4
				char(n): n*字符集长度
				varchar(n)n*字符集长度+2可变字节
				数值类型:
					tinyint:1
					smallint:2
					mediumint:3
					int、float:4
					bigint、double:8
				时间类型:
					date:3
					timestamp:4
					datetime:8
				字段属性:
					NULL属性=1 加1个长度
					not null属性:0 就不加
		Extra:
			显示额外的信息,各种操作会在Extra提示相关信息,
				Using where
					查询需要索引回表查询? 需要索引之外的信息
				Using index
					通过了索引就够了(索引覆盖)
				Using filesort
					对结果需要额外的排序.数据量小的化是内存排序,大的话就在磁盘了.如果有这个情况出现就需要优化一下了
				Using temprorary
					查询使用了临时表,出现于去重、分组等操作.要尽量避免了
回表查询:
	当辅助索引查询没有查询到数据或者数据不完整,那么就需要去innodb必须的聚簇索引里去查找数据,这就是回表数据.相当于扫描了两个索引.辅助索引没满足.性能低了这样.
覆盖索引:
	只需要在一个索引树上就能获取到sql查询的所有数据,就叫覆盖索引.这是性能最好的.
最左前缀原则:
	复合索引在使用时,按照索引列的左侧顺序查询时,索引才会生效, 左侧开始向后连贯增加索引列也是生效的,一直可增加到全部索引列 索引都是生效的.但是如果打破了这个规则,比如不是最左侧的索引列或者最右的索引列,而且查询的索引列不是左侧开始连贯的,那么索引就不会生效

在这里插入图片描述

	举个例子:
		一个符合索引(field1、field2、field3)
			select 1 生效,select 1,2生效,select 1,2,3生效
			select 2 不生效 select 3不生效 select 1,3不生效 select 2,3不生效
关于Like与索引的问题:
	使用like时,索引会不会生效?
	5.6前 like的索引不会生效. 5.6后,like条件会进行下沉到存储引擎进行过滤.这会利用更充分.但也是有条件的,当前like条件中后面有通配符的或者没有才会生效.前面有通配符就不会生效.
关于null值列与索引的问题:
	列有null时,索引会不会生效?
	可以生效.因为null属性是占用空间的,所以我感觉索引也能够过滤null属性
	null比空串更占空间,索引尽量避免一下,需要空那就设默认''.
索引与排序的关系:
	filesort:把结果拿出来,然后在缓存或者磁盘进行排序,效率低哦.
		filesort的排序算法:
			双路排序:两次磁盘扫描读取,第一次将排序字段读取出来,第二次读取其他字段数据
			单读排序:从磁盘读取所有列数据,然后在内存里排序.
		如果查询的数据量超出sort_buffer的空间,那么会导致多次磁盘IO并创建临时表.会增加查询负担,所以尽量不要使用select * 或者设置一下 sort_buffer_size 
		show variables like sort_buffer_size 查看buffer大小.
	如果我们查询时extra表达出了using filesort,那么就需要优化一下使之成为using index 
	using index索引的话本身就是有序的,所以就不需要额外的排序,效率很高,如果where+order by 可以将条件和排序的字段建立组合索引.再配合最左原则.
	有索引也不好使的条件:
		排序多个字段,排序方向却不同.
		范围条件 < > .
		没遵循索引的最左原则.
		排序的多个字段都是单独的索引.
		使用了函数.
MySQL的查询优化:
慢查询的一些原因:
	全表扫描
	全索引扫描 一直扫到索引树最底层,再去拿全数据.
	索引过滤性低,设置了索引条件查询时却没有过滤很多数据
	频繁的回表查询
开启慢查询日志:
	show variables like 'slow_query_log%' 查看慢查询的一些功能和参数
	set global slow_qeury_log = ON 开日志功能
	set global slow_qeury_log_file = 'file name' 指定慢日志文件
	set gloabl log_queries_not_using_index = ON 是否记录查询没有使用到索引的sql
	set long_qurey_time = 10 查询超过阈值被记录
查看慢查询日志命令:
慢查询的优化:
	范围查询如果范围过大,那么使用索引查询也会很慢.,是否使用索引只是SQL的执行过程,并不直接与SQL查询的快慢有关系.要提升查询一个SQL的查询速度,不光要建立索引,还要考虑查询条件可否缩小范围.定位精确.这样才能降低速度.
虚拟列:
	可以将一些like查询的固定字段进行创建虚拟列,配合索引后达到等值查询的效果来提升速度
MySQL的分页查询优化:
limit的问题:
	偏移量固定,变化取出数:
		查询量小时变化差距较小.大时开始增加时间
	偏移量变化,固定取出数:(翻页的机制)
		偏移量在增加时开始翻倍的增加时间,limit在执行时,会从第一条开始扫描,所以当偏移量越来越大,sql limit需要扫描的条数就越多.所以性能就开始大幅的下降.
		针对性优化:
			使用覆盖索引来配合limit 进行扫描位置的提前定位,来避免limit page,10中的page过大而导致扫描记录过多.简单来说,不要利用page的变化来进行翻页查询,而是利用索引和固定偏移位取出当前页的ID做为起始的偏移位,再进行limit的查询时就避免了当前页数前的记录扫描.
				sql: select * from user limit 10000,100; 效率低下
				优化sql:select * from user where id>=(select id from user limit 10000,1) limit 100
	查询上一个SQL的监控命令:profiling 需要打开,打开后就可记录SQL的执行监控数据

MySQL事物和锁:

事务的ACID:
	原子性(要么都执行,要么都不执行redo和undo的作用),
	一致性(保持数据修改后都为一致),
	隔离性(必须保证某一数据被一个用户访问),
	持久性(数据被修改后就永久生效,被记录了,回档也是利用了记录,相当于新增了一条修改记录,持久性概念没有变)
事务的并发问题以及隔离级别:
	重复提交:更新的数据被覆盖或回滚
	脏读:读到了其他人修改了但是没提交的数据.并发常见,锁的主要应用区域,互联网主要针对的区域,当避免了这个问题就会避免重复提交可幻读问题.乐观锁、悲观锁的主要针对问题.
	不可重复读:读取到了修改后数据,以至于读了一次后再读一次结果不一致.这个问题不是灾难性的.因为这个现象没有产生灾难,容错率较高.
	幻读:读到了新增或者删除的数据.也是属于容错率较高的情况.针对新增来说,幻读也是一个特有功能,如:刷新朋友圈,哈哈哈哈哈.但删除是一个影响体验的功能,比如刷着商品菜单,突然少一个,但这都为效果问题,一旦上升到数据库问题,那么将引起程序问题.所以用逻辑删除来避免数据库的物理删除,可降低这类问题风险.
事物的处理方式:
	排队:按顺序一个个执行.
	排他锁:可以实现并发,但是相同数据修改时,谁先加锁谁独占,其他都等着.这个场景适应一些修改个人资料,修改一些独占的信息.如用户、我的博客等.
	读写锁:
		读-读、写-写、读-写、写-读.四种场景并行处理,对并发处理进行细化,区别并发的操作来智能加锁.这样可以提高并发读的速度.但无法提高带有写的操作.
	MVCC 多版本控制:
		copy on write ,写入时先复制一份供其他事务来读.多余的版本在系统进程会定时清理释放undo空间.
		生成机制:
			事务操作时Undo日志会记录操作的事务号和修改数据状态.这样就可以通过undo日志进行更新前的查询,或者回滚数据等操作.
		读操作:
			快照读 不用加锁,但会读到历史版本、当前读:永远读最新的.但会加锁.
		实现原理:
			隐含ID 跟oracle的row id应该相同.
			事务ID 该次事务操作的ID号.
			回滚指针 更新回滚操作的标记点.来保证回滚的正确操作
			流程1:更新时先创建redo log进行准备
			流程2:更新数据 
			流程3:undo记录事务ID 状态,指针链接上一个版本的数据.
事物隔离级别:
隔离级别是SQL92标准,对并发事务的一种解决方案.是锁和MVCC的具体实现(封装)的体现
锁是处理并发的基础,对并发的事务进行控制.
可重复读隔离级别可能会发生幻读.当session1查询,session2新增或删除,seesion1再次查询是可以避免幻读现象,但session执行插入操作后,幻读现象将会出现.
事务操作流程:
	开启事务 begin;
	执行sql操作;
	提交事务 commit
更改事务隔离级别:
	show variables like 'tx_isolation' 或者 select @@tx_isolation
	set [global] tx_isolation = 'read-uncommitted' 读未提交 
	set [global] tx_isolation = 'read-committed' 读已提交  oracle和sql server 的默认级别
	set [global] tx_isolation = 'repeatable-read' 可重复读  默认级别
	set [global] tx_isolation = 'serializable' 串行化 
mysql锁:
表锁:安全高,并发最低
行锁:并发最好
	原理:innodb是锁住索引.
		record lock 记录锁
		gap lock 间隙锁. 是一种范围锁
		netx-key lock 上面两个锁的组合.锁数据也锁范围.
	RR隔离级别:首先用NK锁,如果索引为主键和唯一.那么降级变为记录锁.
	场景:
		普通的select不锁.
		select ... lock in share mode 共享锁添加 nk锁算法处理.有主键唯一索引,进行降级
		select ... for update 追加排他锁 nk算法或降级处理(加锁基本操作)
		update  也是排他锁 nk算法或降级处理
		delete  同上
		insert 同上 排他锁
	锁定原理:
		加锁:
			主键索引直接给主键加锁
			唯一索引加锁先给索引加锁,同时也给主键索引加锁
			非唯一索引先锁索引,再锁间隙(GAP)锁和周边数据,最后锁周边主键
			无索引的话会导致全表加锁和全间隙加锁.(所以一定要注意索引的使用,避免加锁的问题)

在这里插入图片描述

页锁:锁定一部分数据关联的数据.并发性能居中
读锁:S锁,共享锁,针对同时读取数据时多session不受影响.
写锁:X锁,排他锁,一个session写入没完成时,其他写入和读取都会被阻拦/
	IS锁、IX锁:意向读锁和意向写锁.针对表锁. S和X是行级锁,读取和写入时先向表加上IS和IX锁,然后再会对具体行进行S和X锁
S锁可以被追加S锁,X锁不能被被追加X锁,连S锁都不能追加
乐观锁:大家都可以操作,直到更新时进行比对操作,冲突了进行报错.一定几率才会出现,但是能提高并发
	不使用数据库和引擎的锁,通过我们逻辑控制,利用版本控制字段来解决冲突,冲突了的session不会影响到数据库,不会造成锁住的等待机制.而是直接返回失败.
悲观锁:
	S锁和X锁都属于悲观锁 锁主数据不允许访问,就很悲观.
	表锁:
		手动给表加锁:lock table tablename read|write
		查看表锁 show open tables;
		删除表锁 unlock tables;
	行锁:
		共享锁:就只能读,可追加锁.
			加锁select ... lock in share mode;
		X锁写锁: 连读没法读了,也不能被追加
			innodb引擎默认会将更新操作加上for update 排他锁
			加锁select ... for update;

在这里插入图片描述

死锁:大部分死锁就是两个session在互相等待对方释放锁
	表级死锁:
		A先操作表1再操作表2.B先操作表2再操作表1. 双方都在等待对方释放锁.就造成了死锁. 这是属于逻辑设计问题.
		要么都锁,别先锁表1再锁表2,要么就都别锁, 更改逻辑
	行级死锁:
		1.查了一个没索引的字段导致全表锁死.多个用户都这么执行,那么很容易就死锁了.别关联太多表查询,必要时可以拆开逐步查询,索引要建立完善但不是越多越好.
		2.A操作行1再操作行2,B先操作表2再操作表1.也死锁了,这种死锁处理跟表级死锁一样.
	共享锁转成了排他锁:
		A加了S锁,紧接着换了个X锁.B想更新加X锁,结果A的S锁还在,B加不上X锁,A也因为没执行完等着加X锁, 导致了死锁.
	如何排查死锁:
	show engine innodb status 其中会报告死锁信息.
	show status lik 'innodb_row_lock%'

MySQL集群架构:

大型互联网单库已经不能支撑住了,库要是崩了那将是毁灭性的.
当下环境高可用性是主要需求,在高可用性下维持数据一致和容错.也是数据库的分布式思想.
高可用的方法就是冗余,疯狂的剩余.
可用性的架构模式:
	主从模式:高速读取,但写入需要自行优化
	双主模式:互为主从.双主双写和双主单写. 双主单写更可控,较为安全.推荐使用.
拓展性的扩容:
	加从库:主库性能便会降低,因为要推送binlog给从库同步.但是只能作为临时应急,如果持续性饱和,那么就需要设计新的结构了.
	分库分表:分为垂直拆分和水平拆分. 垂直缓解部分压力,水平可以无限扩展.
一致性处理方式:
	不要使用从库.但这又导致读能力低下了
	路由层来控制,在同步的时间内,先使用主库,同步完成再可访问从库.
架构模式-主从模式:

在这里插入图片描述

高可读,一个主节点库,同步到其他的库中,采用异步复制.
实现原理:
	主库收到插入操作,将操作写入binlog,从库去读取binlog并接收,然后写中继log:relay log,从库再从relay log进行回放来实现修改数据的效果.
	用三个进程做工作1.binlogDump thread、2.IO thread、3.SQL thread
		1:负责推送binlog给从库
		2:负责将binlog 写入到relay log
		3:负责将relay log恢复到库中.
问题:
	会有延迟问题; 主库崩溃,从库没有复制完成,数据丢失了就.
半同步:
	从库提交事务ACK主表也提交.5.5
增强版同步:5.7
	从库收到binlog的日志就ack主库,主库与从库提交.
主从复制-并行复制:
	将从库的两个线程进行多线程执行.其实只有sql thread多线程才有意义,io thread没啥太大作用,因为这个性能是主库发送时间和速度决定的.5.6、5.7、8.0都是并行复制.提升性能.
	5.6的复制对于单从库的优势就发挥不出来了,可能会导致性能变低.执行顺序也会导致问题的存在.
	5.7进行升级,组提交的概念.
		show variables like slave-parallel-type
		将binlog日志中不冲突的操作划为一组,然后并行执行.每组6个,指定的吗?
	8.0的并行复制:
		采用write-set并行复制,记录了事务修改的ID的HASH值,新来的提交日志需要和已经提交的ID hash进行比对.来判断是否冲突.这就精细化到了行级数据,达到了高并行.
			复制模式:
				commit_order 组提交
				writeset:写集合机制
				write session 比写集合多了一个约束,last_committer按先后顺序递增.
		并行复制的监控:
			show variables like 'replication%' 查看一些复制的参数
主从模式的操作方法:

在这里插入图片描述

主库
my.cnf配置文件配置:
	binlog功能开启:log_bin=logName
	设置server id:server-id=1
	sync-binlog=1 每次同步进行写入磁盘.
	binlog-ignore-db=忽略哪些数据库不同步
	binlog-do-db=同步哪些数据库.
	从库需要连接主库
授权:
	grant replication slave on *.* to 'root'@'%' identified by root(8.0.x的版本不加密码)
	grant all privileges on *.* to 'root'@'%' identified by 'root'
show master status;查看主库状态
从库:
my.cnf配置:
	server-id=2 server id设置
	relay_log=logName 中继日志名称设置
	read_only=1 只读模式 
初始化:
	show slave status
	change master to master_host='0.0.0.0',master_port=3306,master_user='username',master_password='password',master_log_file='binlogName',master_log_pos=postion
	start slave
主从复制半同步复制:

在这里插入图片描述

需要安装插件:semi   rpl_semi_sync_master (主从都需要安装,从库就把master改为slave)
select @@have_dynamic_loading;是否可以动态加载插件
show plugins 查看当前已有插件
install plugin pluginName  soname 'semisync_[master/salve].so'(固定的)   安装插件
设置参数:
	rpl_semi_sync_master_enabled = 1 开启自动半同步复制
	rpl_semi_sync_master_timeout = 10000 设置超时时间
如何查看半同步复制是否成功:
	主库:
		查看下日志mysqld.log
主从复制并行复制:

在这里插入图片描述

主库:
	show variables like '%binlog_group%' 查看事务组参数.
	组同步参数设置. 设置延迟、设置每组事务数量
从库:
	show variables like '%slave%' 查看从库中的组同步参数
	设置同步slave_parallel_type 改为 logical_clock
	设置并行线程数slave_parallel_workers 不要太大 最高设8就行
	show variables like '%relay_log%' 查看中继日志参数
	设置relay_log_recovery = 1; 需要改my.cnf
	设置master_info_repository=table 
	设置relay_log_info_repository=table 
查看并行复制信息:
	切换到performance_schema库
	select * from replication_applier_status_by_worker;
主从复制读写分离:

在这里插入图片描述

主库只负责写,从库只负责读,主从实现复制.
避免了死锁的风险,提高读的效率.
主库不建索引.负责读的从库建立索引,这样可提高写入速度.
面临的问题:
	主从同步延迟的一些方案:
		写后立刻读.一段时间内查询还是用主库,之后同步了再查询从库
		二次查询.先去从库查询,从库没有的话再去主库查询.并没有实际减轻了主库压力.需要程序模块来控制查询频率
		根据业务特殊处理:根据需求来决定哪些查询要求实时更新.哪些可以等待从库同步完成后查询成功.
		具体的情况,需要按照项目的实际需求来灵活应用
	主从分配机制的方案:
		基于程序和配置进行分配,根据需求来切换数据源,比较常用.但可维护性不佳.
		基于服务器端代理:
			数据源只访问一个,这个数据源实际是个代理.他来选择读写的服务器.虽然增加硬件成本,但可维护性好.
			代理中间件:
				mysql proxy:服务端代理.
					中间件的安装:
						1.解压tar.gz
						2.创建mysql-proxy.cnf配置文件
							user=root 当前运行中间件的帐号
							admin-username=root 主从用的帐号
							admin-password=password
							proxy-address=代理的地址:4040
							proxy-backend-addresses=主库的地址们:端口
							proxy-read-only-backend-addresses=从库的地址们:端口
							proxy-lua-script=rw-splitting.lua的path
							log-file=设置日志
							log-level=日志级别
							daemon=true 是否守护进程 true守护进程
							keeplive=true 是否崩溃重启
						3.给文件指定权限 chmod 777 mysql-proxy.cnf
						4.修改rw-splitting.lua
							min_idle_connections=最小读写分离启动连接数,改为1可查看效果,实际应用根据并发量设置.
						5.启动 ./mysql-proxy defaults-file=./mysql-proxy.cnf
						6.打开火墙对应端口
					中间件的使用:
						命令行的图形化针对8.0会有问题,所以可以直接使用图形化工具,命令行会找不到表...
						使用可视化工具创建代理的连接
						在代理中insert 查看是否设置生效. 暂时先stop slave 来停止复制
						在代理中select 查看时看是否是读库查询. 断开了复制,不会同步,那么主从就有数据差.一定能看出来效果.
				myCat: 基于阿里cobar开发
				shardingSphere:开源分布式中间件,包含sharding-jdbc、sharding-proxy.应用级分配就是用sharding-jdbc
				atlas:360开发的中间件.基于mysql proxy0.8的版本升级
				amoeba:早期的代理中间件.不支持事务、分库分表
主从模式-双主模式:

在这里插入图片描述

主从复制中,一主多从的情况下,如果写入需求很大,那么单主就会形成性能瓶颈,而且如果主库崩溃,那么应用将不可用.所以需要双主模式来保证可用性.
多主模式其中的两台主库其实互为从库.但根据server id不会引起无限循环.
双主双写:
	会出现的问题:
		ID冲突.当1号主写入后没有同步到2号主库,2号主库又接到写入请求,这就会导致两个库写入用了同一个ID(针对自动递增.).但是也可以避免.但对后期扩展支持不友好.
		更新丢失:同一条记录在2个主库同时更新,就会导致更新冲突而丢失一条记录.控制较为复杂.
双主单写(推荐,较为安全):
	不会轮询使用双主(应用来控制).另一个主库是做为备用库做好准备的.当其中一个主库故障,自动切换到另一台主库.同时从库也要跟过去.stop再start?
双主的配置方法:
1号主库:
	my.cnf配置:
		relay_log=log_name 开启中继日志功能.
		log_slave_updates=1 更新是否写入binlog
		auto_increment_offset=1 双主单写不需要配置了就 双写的ID起始位置
		auto_increment_increment=2 生成ID间隔
	做主库关联2号库(1号对于2号就是2号的从库)
	change master to master_host='',master_port=3306.....
2号主库:
	my.cnf配置:
		配置同1号主库
	做主库关联1号库(2号对于1号就是1号的从库)
	change master to master_host='',master_port=3306.....
binlog的时间点容易导致数据库结构不同.注意避免,尽量双库从0开始搞.
MMM架构:
一个三方软件,master-master replication manager for mysql
可以实现1号崩溃自动切换到2号主库.
一个主库为写入,另一个备用主库设为读.双主互相复制.从库一直跟着写入的主库.写入主库崩溃,读取主库转换为写入,从库更换复制主库.
MHA架构:

在这里插入图片描述

基于主从模式,主库故障后,将从库快速切换为主库.可以管理多个集群.
由manager和node组成.
切换数据库流程:
	保存主库binlog.
	找寻最新的slave
	用最新的slave 的relaylog修复其他从库
	将保存下来的binlog恢复到最新的从库
	将最新的从库升为主库
	其他从库指向新的主库.
MHA配置方法:
	更改主库my.cnf:
		relay-log=mysql-relay-bin //开启中继日志
		skip_name_resolve 关闭名称解析
主从复制-主从切换策略:
主备延迟问题.
show slave status中 seconds_behind_master表示备库同步的延迟时间.
	网络问题、备库性能差、单个机器当多个主库的从库都会影响可用性、分工问题、大事务操作
可靠性优先:
	判断从库的SBM延迟值,小于阈值开始下一步操作
	主库设为只读(这个时间节点将不可写入,影响可用性)
	等待B库的SBM延迟降为0
	B库改为读写状态.
	应用的写入请求调转到B库上.B库成为主库.
可用性优先:
	A库写入后binlog发送给从库时,从库被快速切换为主库,并收到了写入请求.这时binlog还没有同步.这就导致主键被占用.升为主库的从库同步给原库时就会出现数据冲突.
分库分表架构:
数据量在疯狂的堆叠.主从复制的模式就无法解决.
拆分方案:单分库、单分表、分库分表
拆分模式:
	垂直拆分:表数量庞大.拆成多个库存储
		应用层来说.只是切换数据源了而已
		垂直分表:将一个大表拆分成多个小表.主从表的思想.
		优点:业务清晰.规则明确;可扩展好;减少IO次数;提高查询速度,最大化利用cahce;冷热分离
		缺点:主键冗余,要做关联查询.(现在开发我已尽量减少表连接查询sql,转用程序级循环查询);单表数据量过大问题没有解决.
	水平拆分:单表数据量多大.分成多个表存储
		优点:拆规则设计好.表连接就可关联起来..不存在单库大数据.拆分后表结构相同.不需要改动应用过多.提高系统稳定性和负载能力
		缺点:拆分规则复杂;会出现跨库查询;一致性事务较难;扩容和维护量大.
业务上,更关注垂直拆分.进行细化. 技术上,使更注重水平拆分.提高应用本身性能.
分布式ID主键生成策略:
UUID:耗费空间,对索引树影响较大,因为UUID无序.
COMB UUID的变种:有序的UUID,解决了对索引的影响
SNOWFLAKE:雪花算法.LONG型占用空间小,有序.但强依赖系统时钟.大厂都单独封装.
专门的数据库ID表:在这表里生成ID,再插入到业务表中,风险较高,性能无法保障
Redis生成ID:用redis生成全局ID,集群redis就需要设置好间隔.扩展性不太好
分片策略:
sharding,把一个整体数据库打散,进行分散存储.
将整体数据按一定的规则进行拆分存储的流程思想就是分片.而分库分表是结果.
根据数据中的某个字段作为分片键进行分片.
基于范围分片:
	根据分片键的指定范围进行分片.
	优点:新数据落在新节点上.扩容不需要迁移数据.
	缺点:数据分布不是很均匀.导致查询权重失衡.新节点压力会过大.造成洪峰.
hash、%分片.
	对于数字型key直接%运算进行分片,非数字型进行hash运算后%运算分片.
	优点:实现简单.数据分布较为平均.,不会存在权重问题.
	缺点:需要将已有数据进行重新分配迁移.增加节点就需要重新计算,
一致性hash分片:
	为了避免扩容时导致的迁移问题.只需要迁移少部分数据.不需要对整体数据进行迁移调整.只会影响hash环中两个节点之间的数据
扩容方案:
首要面临问题:数据迁移问题、分片规则更改、数据同步、时间点、一致性
停机扩容方案:
	服务下线,进行扩容操作.进行数据导出,增加节点,数据导出,分片,导入.
	适用于小型项目,管理系统类项目.
平滑扩容:
	保持可用性的情况下,进行无感扩容.只能扩容到原有数量的2倍,将扩容的节点与原有节点进行双主同步,保持可用性,并开启双写模式,然后关闭双主同步模式.然后根据分片规则对每个库的数据进行删除. 
	不需要迁移数据,服务高可用,对完成没有限时,可调试.不影响线上服务.降低已有库的性能.
	缺点:配置较为复杂,双主同步、开启双主双写,检测数据同步性问题.迭代成本较高
	始用高可用的服务.大型互联网
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值