-
技术性
1.加锁lock
2.多行并发cuontdownlatch
3.最基本的代码快,以及运行的结果与验证逻辑和目的查看全部 -
1.抢红包的设计目的是?
2.抢红包的代码并发与分类块的群体如何区分?大数据分析的出用户手机的人群角色?
3.抢红包为了营造气氛和收割用户互联网社交与用户未来角色与精准营销而设计金额大小?
4.老年用户与年轻用户之间的互动,家庭成员之间关于网络使用的正确打开方式的模块会带来更好的春晚的团聚和良好的国风家风?
5.免费始终是免费,可付费也不见得这么多年春晚有抢红包环节是市场营销、头部冠名赞助商、互联网大咖品牌赞助商、实体品牌赞助商有将广告文案、营销与红包让利及真正的老舍下的身心健康真正运用到实际,哪怕是无穷接近到实际也好,但从无。这也是这个免费课程无法带来更深层次的教育营销和真正应用到各行各业的营销课程。下沉的教育营销和公益营销都够不着………查看全部 -
学习数据
查看全部 -
Mysql
1.一条SQL查询语句是如何执行的?mysql的服务架构
整体结构:MySQL Server架构自顶向下大致可以分网络连接层、服务层、存储引擎层和系统文件层。
网络连接层:也就是各种数据库连接客户端,如 常见的 Java、C、Python、.NET等,它们通过各自API技术与MySQL建立连接。
服务层:是MySQL Server的核心,主要包含 连接器、查询缓存、分析器、优化器、执行器等。
存储引擎层:各种存储引擎,其架构模式是插件式的,存储引擎层负责数据的存储和提取,MySQL 5.5.5 版本InnoDB开始成为了默认存储引擎。
系统文件层:各种系统文件,比如日志文件,比如 binlog undo.log redo.log
上面我们提到mysql的服务层划分:
第一步:连接器:负责管理链接,用户账户权限验证
第二步:查询缓存:查询缓存,命中直接返回
连接建立完成后,你就可以执行sql查询语句了,执行逻辑就会来到第二步:查询缓存。
MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。
如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。
但是:不建议使用查询缓存,原因如下:
因为查询缓存往往弊大于利。查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。
对于你确定要使用查询缓存的语句,可以用 SQL_CACHE 显式指定,像下面这个语句一样:
mysql> select SQL_CACHE * from T where ID=10;
同时:需要注意的是,MySQL 8.0 版本直接将查询缓存的整块功能删掉了,也就是说 8.0 开始彻底没有这个功能了。
查询缓存如何设置:
have_query_cache 表示当前mysql版本是否支持查询缓存。
query_cache_type 0 时表示关闭,1时表示打开,2表示只要select 中明确指定SQL_CACHE才缓存。
query_cache_limit 表示单个结果集所被允许缓存的最大值。
query_cache_min_res_unit 每个被缓存的结果集要占用的最小内存。
query_cache_size 用于查询缓存的内存大小。
qcache_free_memory 查询缓存目前剩余空间大小。
qcache_hits 查询缓存的命中次数。
qcache_inserts 查询缓存插入的次数。
第三步:分析器:词法分析 语法分析
如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析,生成"解析树"。
预处理器根据一些MySQL规则进一步检查“解析树”是否合法;
分析器先会做“词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。
做完了这些识别以后,就要做“语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个sql语句是否满足 MySQL 语法。
第四步:执行优化器
经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。
优化器是 决定使用哪个索引; 决定各个表的连接顺序。
原则是:尽可能扫描少的数据库行纪录
第五步:执行器: 操作存储引擎,获取结果并返回
MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。
开始执行的时候,先检验权限
如果操作表的权限,就打开表继续执行。打开表的时候,执行器就会根据表的存储引擎,去使用这个引擎提供的接口。
2.日志系统:一条SQL更新语句是如何执行的?
关键词: WAL write ahead logging 先写日志、 undolog redolog 、 binlog、 两阶段提交 innodb存储引擎
如果要将 ID=2 这一行的值加 1,SQL 语句就会这么写:
mysql> update T set c=c+1 where ID=2;
该过程是如何执行的呢?
首先,可以确定的说,查询语句的那一套流程,更新语句也是同样会走一遍。
1.你执行语句前要先连接数据库,这是连接器的工作。
2.前面我们说过,在一个表上有更新的时候,跟这个表有关的查询缓存会失效,所以这条语句就会把表 T 上所有缓存结果都清空。这也就是我们一般不建议使用查询缓存的原因。
3.接下来,分析器会通过词法解析和语法解析知道这是一条更新语句。
4.优化器决定要使用 ID 这个索引。
5.然后,执行器负责具体执行,找到这一行,然后更新。
更新流程还涉及两个重要的日志模块:redo log(重做日志)和 binlog(归档日志)
客户端执行DDL语句(create)/ DML语句(insert,update,delete)/DCL语句(grant,revoke),数据库服务端执行的时候会涉及到 undolog(撤销日志) redolog(重做日志) 和 binlog (归档日志)
show engines:查看当前数据库支持的引擎信息,在5.5版本之前默认采用MyISAM存储引擎,从5.5开始采用InnoDB存储引
常见存储引擎有:
InnoDB:支持事务,具有提交,回滚和崩溃恢复能力,事务安全
MyISAM:不支持事务和外键,访问速度快
Memory:利用内存创建表,访问速度非常快,因为数据在内存,而且默认使用Hash索引,但是一旦关闭,数据就会丢失
了解 redolog(重做日志) 和 binlog (归档日志) 之前我们先详细学习下Innodb存储引擎的架构模型
分析下 Innodb 存储引擎:
Innodb存储引擎: 它支持外键,擅长处理事务,具有自动崩溃恢复的特性;
InnoDB引擎架构图:主要分为内存结构和磁盘结构两大部分
内存结构:
内存结构主要包括Buffer Pool、Change Buffer、Adaptive Hash Index和Log Buffer四大组件
Buffer Pool:缓冲池,以缓存页page作为基本单位,大小默认为16k, 缓存页之间通过链表进行链接
作用:在InnoDB访问表记录和索引时会在Page页中缓存,以后使用可以减少磁盘IO操作,提升效率
page页的类型分为三种:
free page :空闲page,未被使用
clean page:被使用page,数据没有被修改过
dirty page:脏页,被使用page,数据被修改过,页中数据和磁盘的数据产生了不一致
page页通过三种链表来进行维护
free list :表示空闲缓冲区,管理free page
flush list:表示需要刷新到磁盘的缓冲区,管理dirty page,内部page按修改时间排序。脏页即存在于flush链表,也在LRU链表中,但是两种互不影响,LRU链表负责管理page的可用性和释放,而flush链表负责管理脏页的刷盘操作。
lru list :表示正在使用的缓冲区,管理clean page和dirty page,缓冲区以midpoint为基点,前面链表称为new列表区,存放经常访问的数据,占63%;后面的链表称为old列表区,存放使用较少数据,占37%。
Change Buffer:
写缓存区:在进行DML操作时,如果缓存池中没有其相应的Page数据,并不会立刻将磁盘页加载到缓冲池,而是在写缓冲区记录缓冲变更,等未来数据被读取时,再将数据合并恢复到BP中。
当更新一条记录时,该记录在BufferPool存在,直接在BufferPool修改,一次内存操作。
如果该记录在BufferPool不存在(没有命中),会直接在ChangeBuffer进行一次内存操作,不用再去磁盘查询数据,避免一次磁盘IO。
当下次查询记录时,会先进性磁盘读取,然后再从ChangeBuffer中读取信息合并,最终载入BufferPool中。
Adaptive Hash Index:自适应哈希索引,用于优化对BP数据的查询
InnoDB存储引擎会自动根据访问的频率和模式来为某些页建立哈希索引。
Log Buffer: 日志缓冲区,用来保存要写入磁盘上log文件(Redo/Undo)的数据
LogBuffer主要是用于记录InnoDB引擎日志,在DML操作时会产生Redo和Undo日志
磁盘结构:
表空间:存放表结构和数据(InnoDB使用聚集索引(聚簇索引),索引和记录在一起存储,既缓存索引,也缓存记录。)
数组字典:InnoDB数据字典由内部系统表组成,这些表包含用于查找表、索引和表字段等对象的元数据
redo日志:用于在崩溃恢复期间更正不完整事务写入的数据。MySQL以循环方式写入重做日志文件,记录InnoDB中所有对Buffer Pool修改的日志。
undo日志:撤消日志是在事务开始之前保存的被修改数据的备份,用于例外情况时回滚事务
3.详细解析日志文件 undo.log redo.log binlog作用和功能?
undo.log撤销日志:
Undo Log:数据库事务开始之前,会将要修改的记录存放到 Undo 日志里,当事务回滚时或者数据库崩溃时,可以利用 Undo 日志,撤销未提交事务对数据库产生的影响
Undo Log产生和销毁:
Undo Log在事务开始前产生;
事务在提交时,并不会立刻删除undolog,innodb会将该事务对应的undo log放入到删除列表中,后面会通过后台线程purge thread进行回收处理。
Undo Log属于逻辑日志,记录一个变化过程。例如执行一个delete,undolog会记录一个insert;执行一个update,undolog会记录一个相反的update。
Undo Log存储:undo log采用段的方式管理和记录。在innodb数据文件中包含一种rollback segment回滚段,内部包含1024个undo log segment。
Undo Log作用:
实现事务原子性:事务处理过程中,如果出现了错误或者用户执行了 ROLLBACK 语句,MySQL 可以利用 Undo Log 中的备份将数据恢复到事务开始之前的状态
实现MVCC多版本控制:事务未提交之前,Undo Log保存了未提交之前的版本数据,Undo Log 中的数据可作为数据旧版本快照供其他并发事务进行快照读
redo.log重做日志:
redo.log:以恢复操作为目的,在数据库发生意外时重现操作。防止在发生故障的时间点,尚有脏页未写入表的 IBD 文件中,在重启 MySQL服务的时候,根据Redolog进行重做,从而达到事务的未入磁盘数据进行持久化这一特性。
redo.Log 的生成和释放:
随着事务操作的执行,就会生成Redo Log,在事务提交时会将产生Redo Log写入Log Buffer,并不是随着事务的提交就立刻写入磁盘文件。(两阶段提交)
等事务操作的脏页写入到磁盘之后,Redo Log 的使命也就完成了,Redo Log占用的空间就可以重用(被覆盖写入)。
redo.log的写入机制:循环顺序写
属于innodb,4个文件共4GB大小,环形,磁盘地址有序,负责事务。crash-safe能力。
Mysql数据库的写前日志(Write Ahead Log, WAL)机制,也就是说,在实际将数据记录表中之前,先把修改的数据记到日志文件中,以便故障时进行恢复。
binlog归档日志:
属于mysql server层,无大小限制,会无限创建binlog文件,负责归档恢复。
binlog是记录所有数据库表结构变更以及表数据修改的二进制日志,不会记录SELECT和SHOW这类操作。
binlog日志是以事件形式(Log Event)记录,还包含语句所执行的消耗时间。
应用场景:
主从复制:在主库中开启Binlog功能,这样主库就可以把Binlog传递给从库,从库拿到Binlog后实现数据恢复达到主从数据一致性。
数据恢复:通过mysqlbinlog工具来恢复数据。
redo 和undo 两种日志的相同和差异:
1redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
2redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
3redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
4.数据库的两阶段提交:为了保证binlog和redolog两个日志之间的一致性
两阶段提交过程:
1.server拿到数据对数据修改,把修改结果发给引擎。
2.引擎记录redo log状态为 prepare,之后告诉server可以提交事务。
3.server接到通知后记录binlog,之后调引擎接口提交事务。
4.引擎接到提交事务的通知,将redo log改为commit状态。
引擎修改两次redo log的状态的操作叫两阶段提交。
为什么日志需要“两阶段提交”。这里不妨用反证法来进行解释。 崩溃恢复 和 数据主从同步
由于 redo log 和 binlog 是两个独立的逻辑,如果不用两阶段提交,要么就是先写完 redo log 再写 binlog,或者采用反过来的顺序。我们看看这两种方式会有什么问题
仍然用前面的 update 语句来做例子。假设当前 ID=2 的行,字段 c 的值是 0,再假设执行 update 语句过程中c=1 ,在写完第一个日志后,第二个日志还没有写完期间发生了 crash,会出现什么情况呢?
第一种情况:先写 redo log 后写 binlog。假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。
由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。
但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。
然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。
第二种情况:先写 binlog 后写 redo log。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。
但是 binlog 里面已经记录了"把 c 从 0 改成 1"这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。
可以看到,如果不使用“两阶段提交”,那么数据库的状态就有可能和用它的日志恢复出来的库的状态不一致。
5.详解事务的ACID特性以及实现原理 和 事务隔离级别 以及 多版本控制MVCC
事务:简单来说,事务就是要保证一组数据库操作,要么全部成功,要么全部失败。在 MySQL 中,事务支持是在引擎层实现的;
提到事务,你肯定会想到 ACID,那它们是如何实现的呢?(只有Innodb存储引擎支持事务)
原子性(Atomicity): 事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
事务的原子性是通过WAL(先写日志再刷磁盘)实现。最终落地到 undo日志实现
隔离性(Isolation):指的是一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对其他的并发事务是隔离的。
InnoDB 支持的隔离性有 4 种,隔离性从低到高分别为:读未提交、读已提交、可重复读、串行化。
底层是通过对 锁 和 多版本控制(MVCC)技术的封装,从而实现不通的隔离级别
持久性:指的是一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,后续的操作或故障不应该对其有任何影响,不会丢失。
redo log在系统宕机重启之类的情况时,可以修复数据,从而保障事务的持久性。
MySQL的持久性也与WAL技术相关,redo log在系统Crash重启之类的情况时,可以修复数据,从而保障事务的持久性。
通过原子性可以保证逻辑上的持久性,通过存储引擎的数据刷盘可以保证物理上的持久性。
一致性(Consistency): 指的是事务开始之前和事务结束之后,数据库的完整性限制未被破坏。一致性包括两方面的内容,分别是约束一致性和数据一致性。
一致性也可以理解为数据的完整性。数据的完整性是通过原子性、隔离性、持久性来保证的,而这3个特性又是通过 Redo/Undo 来保证的
6.如果没有事务隔离会产生什么问题?
当数据库上有多个事务同时操作同一条记录的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题
更新丢失
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题:最后的更新覆盖了由其他事务所做的更新。
当两个或多个事务更新同一行记录,会产生更新丢失现象。可以分为回滚覆盖和提交覆盖。
回滚覆盖:一个事务回滚操作,把其他事务已提交的数据给覆盖了。
提交覆盖:一个事务提交操作,把其他事务已提交的数据给覆盖了。
脏读: 读到其他事务未提交的数据; (一个事务读取了其它事务update后未提交的数据,注意是针对其它事务的修改未提交的操作 )
不可重复读: 前后读取的同一条记录内容不一致; (一个事务读取了其它事务update或delete后已提交的数据,注意是针对其它事务修改或删除已提交的操作 )
幻读: 前后读取的记录数量不一致。 (一个事务读取了其它事务新insert已经提交的数据。注意是针对其它事务新增已提交的数据)
7.mysql的隔离级别有哪些? 隔离级别是如何实现的?隔离级别如何设置?
在谈隔离级别之前,你首先要知道,隔离得越严实,数据库执行效率就会越低。因此很多时候,我们都要在二者之间寻找一个平衡点。
SQL标准的事务隔离级别包括:
读未提交 : 一个事务还没提交时,它做的变更就能被别的事务看到。(别人改数据的事务尚未提交,我在我的事务中也能读到)
读已提交 : 一个事务提交之后,它做的变更才会被其他事务看到。 (别人改数据的事务已经提交,我在我的事务中才能读到)
可重复读**: 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。(别人改数据的事务已经提交了,但该事务比我的事务开始的晚,我在我的事务中也不去读)
串行化: 顾名思义是对于同一行记录,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;(我的事务尚未提交,别人就别想改数据)
数据库对四种隔离级别的实现,是依靠视图来实现的:
1、读未提交:没有视图的概念,直接返回记录的最新值;
2、读已提交:每次执行sql语句之前创建视图;
3、可重复读:每次创建事务的时候创建视图;
4、串行化:通过加锁来避免并行访问
事务设置隔离级别的相关命令:
mysql> show variables like 'transaction_isolation';查看事务隔离级别
set tx_isolation='各个隔离级别';// 设置事务隔离级别
8.什么是索引?以及索引的作用?常用的索引有哪些类型?
索引一种数据结构,通常采用B+树实现;为了提升查询速率;类似于新华字典中的字典目录,索引是存储在文件中的,因此需要占据物理空间。因此并不是索引越多越好
索引可以分为以下几种:
从应用层次划分:普通索引:没有任何限制、 唯一索引:唯一可为空、 主键索引:唯一且非空、 复合索引:遵循最左前缀原则
从数据存储和索引键值逻辑关系划分:非聚集索引(非聚簇索引,数据和索引分开存放 ,比如mysame)、聚集索引(聚簇索引 比如 innodb引擎将数据和索引存储在一个表中)
从索引键值类型划分:主键索引、辅助索引(二级索引)
从索引存储数据结构划分:B+树索引、Hash索引、FULLTEXT全文索引等
9.索引采用了哪些数据结构?常用的有三种:哈希表 有序数组 B+树
哈希表:
哈希表是一种键值存储数据的结构,我们只要输入待查找的键即 key,就可以找到其对应的值即 Value。
如果产生哈希冲突,使用拉链法接入,在节点下面挂一个数组或链表
查找一个元素的过程:
处理步骤就是:首先,将 key值 通过哈希函数算出 N;如果存在链表,按顺序遍历,找到目标记录。
哈希表只适用于等值查询,其区间查询效率很低;
该种数据结构主要应用在 Memory 存储引擎 和 innodb存储引擎的自适应hash索引中
有序数组:
基于排序的数组实现;
有序数组能够解决hash函数不能满足支持快速范围查询。查找速度为log(n),但缺陷也很明显,针对插入和删除场景,需要挪动后面的整个记录,代价太高。
可以结合二分法就可以快速得到某个等值查询,这个时间复杂度是 O(log(N))。
有序数组适用于静态搜索引擎。
B+树(为什么非要采用B+树)
为什么数据库存储使用b+树 而不是二叉树,因为二叉树树高过高,每次查询都需要访问过多节点,即访问数据块过多,而从磁盘随机读取数据块过于耗时。
MySQL的存储结构
表存储结构
单位:表>段>区>页>行
在数据库中, 不论读一行,还是读多行,都是将这些行所在的页进行加载。也就是说存储空间的基本单位是页。
一个页就是一棵树B+树的节点,数据库I/O操作的最小单位是页,与数据库相关的内容都会存储在页的结构里
10.数据库三大范式
第一范式:每一列都是不可以再才拆分的
第二范式:基于第一范式,非主键字段完全依赖主键字段,而不是依赖于主键字段的一部分
第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。
在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会为了性能而妥协数据库的设计
11.binlog的应用场景? Binlog 日志文件的录入方式,录入方式优缺点对比?
Binlog是记录所有数据库表结构变更以及表数据修改的二进制日志,不会记录SELECT和SHOW这类操作。
Binlog日志是以事件形式(Log Event)记录,还包含语句所执行的消耗时间。开启Binlog日志有以下两个最重要的使用场景。
主从复制:在主库中开启Binlog功能,这样主库就可以把Binlog传递给从库,从库拿到Binlog后实现数据恢复达到主从数据一致性。
数据恢复:通过mysqlbinlog工具来恢复数据。
binlog的日志文件录入方式有三种: row statment mixed
ROW(row-based replication, RBR):日志中会记录每一行数据被修改的情况, 修改记录复制
优点:能清楚记录每一个行数据的修改细节,能完全实现主从数据同步和数据的恢复。
缺点:批量操作,会产生大量的日志,或者修改表结构,尤其是alter table会让日志暴涨。
STATMENT(statement-based replication, SBR):记录每一条修改数据的SQL语句到master的Binlog中,简称SQL语句复制。
优点:日志量小,减少磁盘IO,提升存储和恢复速度
缺点:在某些情况下会导致主从数据不一致,比如last_insert_id()、now()等函数。 无法记录数据库函数
MIXED(mixed-based replication, MBR):以上两种模式的混合使用,一般会使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择写入模式。
12.分析下mysql的存储引擎有哪些?优缺点?以及Innodb和mysiam的区别?存储引擎选择?
通过 show engines 可以查看当前数据库所支持的引擎信息;主要应用的是 innodb myisam , 在mysql版本5.5默认采用myisam存储引擎,5.6.版本之后采用innodb存储引擎
innodb 和 myisam 的区别
锁机制
InnoDB默认支持行级锁,锁定指定记录。基于索引来加锁实现。
MyISAM默认支持表级锁,锁定整张表。
索引结构
InnoDB使用聚集索引(聚簇索引),索引和记录在一起存储,既缓存索引,也缓存记录。
MyISAM使用非聚集索引(非聚簇索引),索引和记录分开。
并发处理能力
MyISAM使用表锁,会导致写操作并发率低,读之间并不阻塞,读写阻塞。
InnoDB读写阻塞可以与隔离级别有关,可以采用多版本并发控制(MVCC)来支持高并发
存储文件
InnoDB表对应两个文件,一个.frm表结构文件,一个.ibd数据文件。InnoDB表最大支持64TB;
MyISAM表对应三个文件,一个.frm表结构文件,一个MYD表数据文件,一个.MYI索引文件。从MySQL5.0开始默认限制是256TB。
如何选择存储引擎:
如果没有特别的需求,使用默认的Innodb即可。
MyISAM:以读写插入为主的应用程序,比如博客系统、新闻门户网站。
Innodb:更新(删除)操作频率也高,或者要保证数据的完整性;并发量高,支持事务和外键。比如OA自动化办公系统。
13.详解索引为什么是B+tree数据结构,而不采用B tree
B+树索引:首先B+树具备以下特性:
1.非叶子节点不存储data数据,只存储索引值,这样便于存储更多的索引值
2.叶子节点包含了所有的索引值和data数据,也就是说 一颗树就是带有索引的完整表记录
3.叶子节点用指针连接,提高区间的访问性能
相比B树,B+树进行范围查找时,只需要查找定位两个节点的索引值,然后利用叶子节点的指针进行遍历即可。而B树需要遍历范围内所有的节点和数据,显然B+Tree效率高。
14.什么情况下会导致索引失效? 查询范围不明确导致索引失效
1. 使用like 左边包含 %
2. 不满足最左前缀原则
3. 在索引列上进行计算或者使用函数
4. 使用了select * ,会导致全表查询
5. 查询时字段类型不同,如 某个表中的code 字段 varchar类型 添加了索引 查询时 code='101'可以命中索引,但是code=101就会导致全表扫描status
6. 错误的使用 or关键字,注意:如果使用了or关键字,那么它前面和后面的字段都要加索引,不然所有的索引都会失效,例如:where id=1 or service_code ='test02' or status =1; 前两个字段有索引,但是status没有索引
7. 使用 order by 关键字容易导致索引失效
如果order by语句中没有加where或limit关键字,该sql语句将不会走索引。
对不同的索引做order by
联合索引不满足最左匹配原则
如果order by后面有一个联合索引的多个字段,它们具有不同的排序规则也会导致索引失效
8. 使用表中的列进行对比
9. 错误的使用 not in 或者 not exists
15.索引分析和优化?如何对数据库sql语句进行索引分析与优化?explain 命令是如何执行的?
我们可以通过explian命令来查询sql语句的执行情况,例如 explian select 语句
explian命令有一些关键信息 如 select_type type possiable_key key rows extra
详细解析
select_type 表示sql语句查询类型: 例如,SIMPLE : 表示查询语句不包含子查询或union;SUBQUERY:SELECT子查询语句
type: 表示存储引擎查询数据时采用的方式,通过它可以判断出查询是全表扫描还是基于索引的部分扫描。
all: 全表查询
index:表示基于索引的全表扫描,先扫描索引再扫描全表数据。
range:表示使用索引范围查询。使用>、>=、<、<=、in等等。
ref:表示使用非唯一索引进行单值查询。
eq_ref:一般情况下出现在多表join查询,表示前面表的每一个记录,都只能匹配后面表的一行结果。
const:表示使用主键或唯一索引做等值查询,常量查询。
NULL:表示不用访问表,速度最快。
possible_key:可能会使用到的索引
key:命中的索引,使用的索引
rows:估算SQL要查询到结果需要扫描多少行记录。这个值越小越好
extra:查询时的扩展信息
Using where :表示查询需要通过索引回表查询数据。
Using index:表示查询需要通过索引,索引就可以满足所需数据。
Using filesort:表示查询出来的结果需要额外排序,数据量小在内存,大的话在磁盘,因此有Using filesort建议优化。
Using temprorary:查询使用到了临时表,一般出现于去重、分组等操作。
16.什么是回表查询(重点)?
回表查询:InnoDB索引有聚簇索引和辅助索引。聚簇索引的叶子节点存储行记录,InnoDB必须要有,且只有一个。
辅助索引的叶子节点存储的是主键值和索引字段值,通过辅助索引无法直接定位行记录,通常情况下,需要扫码两遍索引树。
先通过辅助索引定位主键值,然后再通过聚簇索引定位行记录,这就叫做回表查询,它的性能比扫一遍索引树低。
总结:通过索引查询主键值,然后再去聚簇索引查询记录信息
17.Mysql慢查询实战+SQL优化,慢查询日志分析?如何查看慢查询日志?如何优化慢查询日志
注意点:切记在生产环境上开启慢查询,会影响数据库性能 variables slow_query_log
1.首先查看慢查询是否开启: SHOW VARIABLES LIKE 'slow_query_log%'
2.开启慢查询并设置慢查询: 如果为OFF,则通过命令 SET global slow_query_log = ON 开启 并设置 long_query_time = 10 指定慢查询的阈值
3.查看慢查询sql文件:MySQL 提供了一个慢查询日志分析工具mysqldumpslow,可以通过该工具分析慢查询日志内容,主要看执行时长,锁表时间和sql语句等关键字段
4.通过explian命令分析慢查询sql
5.进行sql语句优化,并监控性能
18.事务并发控制的实现方案有哪些? 说下 MVCC 以及 mysql的锁机制 ****
事务并发会导致更新丢失,脏读,不可重复读,幻读问题,为了避免上述问题,我们可以通过以下方案解决:
1.通过排队的方法:就是完全顺序执行所有事务的数据库操作,不需要加锁,简单的说就是全局排队;
2.排他锁:如果事务之间涉及到相同的数据项时,会使用排他锁,先进入的事务独占数据项以后,其他事务被阻塞,等待前面的事务释放锁。
3.读写锁:读写锁区分读操作和写操作,让读和读之间不加锁,但是读写或写读或写写需要加锁
4.通过MVCC机制实现读读,读写,写读不加锁,通过读取副本(实现读写不加锁操作),但是写写仍然需要加锁;
所谓的MVCC是什么呢?多版本控制,基于 Copy on Write机制实现(先写日志再刷入磁盘)
在事务A开始写操作的时候会copy一个记录的副本(记录在undo.log日志中),其他事务B读操作会读取这个记录副本,因此不会影响其他事务对此记录的读取,实现写和读并行。
MVCC实现原理:
MVCC的实现原理主要依赖于记录中的三个隐藏字段,undolog, read view来实现的。
在 MVCC 并发控制中,读操作可以分为两类: 快照读(Snapshot Read)与当前读 (Current Read)。
快照读:读取的是记录的快照版本(有可能是历史版本),不用加锁。(select)
当前读:读取的是记录的最新版本,并且当前读返回的记录,都会加锁,保证其他事务不会再并发修改这条记录。(select... for update 或lock in share mode,insert/delete/update)
每个事务都会包含三个隐藏字段:隐含ID、事务号Tid和回滚指针Roll_PT,每次写更新都会在事务ID上增加1
19.锁可以有哪些分类?锁机制是如何实现得?乐观锁,悲观锁是如何实现的?
在 MySQL中锁有很多不同的分类。根据不通的划分规则:
根据锁的粒度可分为表级锁、行级锁和页级锁。
表级锁:每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB 等存储引擎中。
行级锁:每次操作锁住一行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB 存储引擎中。
页级锁:每次锁定相邻的一组记录,锁定粒度界于表锁和行锁之间,开销和加锁时间界于表锁和行锁之间,并发度一般。应用在BDB 存储引擎中。
根据锁的操作行为分为读锁和写锁,从操作的类型可分为读锁和写锁。
读锁(S锁):共享锁,针对同一份数据,多个读操作可以同时进行而不会互相影响。
写锁(X锁):排他锁,当前写操作没有完成前,它会阻断其他写锁和读锁。
根据锁的的实现方式分为悲观锁和乐观锁从操作的性能可分为乐观锁和悲观锁。
乐观锁:一般的实现方式是对记录数据版本进行比对,在数据更新提交的时候才会进行冲突检测,如果发现冲突了,则提示错误信息。
悲观锁:在对一条数据修改的时候,为了避免同时被其他人修改,在修改数据之前先锁定,再修改的控制方式。共享锁和排他锁是悲观锁的不同实现,但都属于悲观范畴。
从广义上来讲,前面提到的行锁、表锁、读锁、写锁、共享锁、排他锁等,这些都属于悲观锁范畴。
20.什么情况下会产生死锁?如何避免死锁? 如何解决死锁? https://blog.csdn.net/qq_34107571/article/details/78001309
死锁的标准定义:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
死锁产生必须要具备以下四个条件:
互斥条件:某资源在一段时间内只由一个进程占用
相互等待条件:指在发生死锁时,必然存在一个进程和资源的环形链,比如 A进程正在等待一个B进程占用的资源;B进程又正在等待A进程占用的资源
不可剥夺条件:指进程已经获取的资源,在未使用完之前,只能由自身释放
请求和保持:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放
以下几种情况下会出现死锁:
情况一:
如果在事务中执行了一条没有索引条件的查询,引发全表扫描,把行级锁上升为全表记录锁定(等价于表级锁),多个这样的事务执行后,就很容易产生死锁和阻塞
解决方案:
SQL语句中不要使用太复杂的关联多表的查询;
使用explain“执行计划"对SQL语句进行分析,对于有全表扫描和全表锁定的SQL语句,建立相应的索引进行优化。
情况二:
两个事务分别想拿到对方持有的锁,互相等待,于是产生死锁。
解决方案:
在同一个事务中,尽可能做到一次锁定所需要的所有资源
按照id对资源排序,然后按顺序进行处理
四、 如何预防死锁
如何避免死锁?为此我们在开发的过程中需要遵循如下原则:
1.编写应用程序避免长事务,让进程持有锁的时间尽可能短
2.避免并发的执行 修改数据的语句。
3.要求每一个事务一次就将所有要使用到的数据全部加锁,否则就不允许执行。
4.预先规定一个加锁顺序,所有的事务都必须按照这个顺序对数据执行封锁。如不同的过程在事务内部对对象的更新执行顺序应尽量保证一致。
5.使用尽可能低的隔离级别。
6.数据存储空间离散法。该方法是指采用各种手段,将逻辑上在一个表中的数据分散的若干离散的空间上去,以便改善对表的访问性能。主要通过将大表按行或者列分解为若干小表,或者按照不同的用户群两种方法实现。
怎么查询死锁: https://www.cnblogs.com/jpfss/p/11491526.html
1、查询进程id,然后kill id show processlist kill id
2、查询是否锁表 : show OPEN TABLES where In_use > 0;
3、在5.5中,information_schema 库中增加了三个关于锁的表(innoDB引擎):
innodb_trx ## 当前运行的所有事务
innodb_locks ## 当前出现的锁
innodb_lock_waits ## 锁等待的对应关系
4、通过show engine innodb status\G命令查看近期死锁日志信息。查看死锁日志
21.Mysql 主从之间是怎么同步数据的? 主从复制的用途?如何解决主从复制延迟问题?
主从复制主要应用于:
故障切换:用于故障切换(高可用)
数据备份:避免由于数据宕机影响业务(高可用)
读写分离:提供查询服务(读扩展)
主从复制通过以下三个步骤完成数据同步:
1.主库将数据库的变更操作记录到Binlog日志文件中
2.从库读取主库中的Binlog日志文件信息写入到从库的Relay Log中继日志中
3.从库读取中继日志信息在从库中进行Replay,更新从库数据信息
在上述三个过程中,涉及了Master的BinlogDump Thread和 Slave的I/O Thread、SQL Thread,它们的作用如下:
Master服务器对数据库更改操作记录在Binlog中,BinlogDump Thread接到写入请求后,读取Binlog信息推送给Slave的I/O Thread。
Slave的I/O Thread将读取到的Binlog信息写入到本地Relay Log中。
Slave的SQL Thread检测到Relay Log的变更请求,解析relay log中内容在从库上执行
22.mysql主从复制存在的问题,如何解决主从复制延迟问题?
mysql主从复制存在的问题:
主库宕机后,数据可能丢失
从库只有一个SQL Thread,主库写压力大,复制很可能延时
解决方法:
半同步复制---解决数据丢失的问题
半同步复制: 为了提升数据安全,MySQL让Master在某一个时间点等待Slave节点的 ACK(Acknowledgecharacter)消息,接收到ACK消息后才进行事务提交。
并行复制----解决从库复制延迟的问题
并行复制在从库中有两个线程IO Thread和SQL Thread,都是单线程模式工作,因此有了延迟问题,我们可以采用多线程机制来加强,减少从库复制延迟。(IO Thread多线程意义不大,主要指的是SQL Thread多线程)
在MySQL的5.6、5.7、8.0版本上,都是基于上述SQL Thread多线程思想,不断优化,减少复制延迟。
23.数据库如何实现分库分表?什么是分库分表?分库分表的策略是什么?
存在的问题:
业务越来越大,单表数据超出了数据库支持的容量
Tps过大,十几万并发量,传统的架构(一主多从),主库容量肯定无法满足这么高的Tps
拆分的模式:水平拆分 垂直拆分 都属于物理空间的拆分。
垂直拆分:由于表数量多导致的单个库大。将表拆分到多个库中。
水平拆分:由于表记录多导致的单个库大。将表记录拆分到多个表中。
面试八股文: https://blog.csdn.net/o9109003234/article/details/121026489
Mysql的集群架构
Mysql的集群方案有以下三种: 主从架构 双主架构 分库分表
主从架构(如何实现,如何保证数据一致性)
主从模式:是指数据可以从一个主数据库复制到一个或多个从节数据库。MySQL 默认采用异步复制方式
主从架构的作用:
读写分离,提供查询服务(读扩展)
数据备份,避免影响业务(高可用)
实时灾备,用于故障切换(高可用)
主从复制整体分为以下三个步骤:
1.主库将数据库的变更操作记录到Binlog日志文件中
2.从库读取主库中的Binlog日志文件信息写入到从库的 Relay Log中继日志中
3.从库读取中继日志信息在从库中进行Replay(数据恢复),更新从库数据信息
在上述三个过程中,涉及了三个线程, Master的BinlogDump Thread和Slave的I/O Thread、SQL Thread,它们的作用如下:
BinlogDump Thread(binlog日志推送线程) : 当Master服务器对数据库更改操作记录在Binlog中,该线程接到写入请求后,读取Binlog信息推送给Slave的I/O Thread。
I/O Thread(从库IO线程): 该线程读取到的Binlog信息写入到本地Relay Log中。
SQL Thread(从库sql线程): Slave的SQL Thread检测到Relay Log的变更请求,解析relay log中内容在从库上执行。
上述过程都是异步操作,俗称异步复制,存在数据延迟现象。
主从复制存在的问题(也就是异步操作导致的问题):
主库宕机,可能导致数据丢失问题:
数据延迟问题:从库只有一个SQL Thread,主库写压力大,复制很可能延时
如何主从复制存在的上述问题:
半同步复制---解决数据丢失的问题
为了提升数据安全,MySQL可以让Master在某一个时间点等待Slave节点的 ACK消息,接收到ACK消息后才进行事务提交,这也是半同步复制的基础,
MySQL从5.5版本开始引入了半同步复制机制来降低数据丢失的概率。
介绍半同步复制之前先快速过一下 MySQL 事务写入碰到主从复制时的完整过程,主库事务写入分为 4个步骤:
InnoDB Redo File Write (Prepare Write) 两阶段提交中的prepare阶段
Binlog File Flush & Sync to Binlog File 两阶段提交中的写入binlog阶段
InnoDB Redo File Commit(Commit Write) 两阶段提交中的写入commit阶段
Send Binlog to Slave: 主库通过binlogDump thread 推送binlog日志到从库
当Master不需要关注Slave是否接受到Binlog Event时,即为传统的主从复制。
当Master需要在第三步等待Slave返回ACK时,即为 after-commit,半同步复制(MySQL 5.5引入)。
当Master需要在第二步等待 Slave 返回 ACK 时,即为 after-sync,增强半同步(MySQL 5.7引入)
半同步复制:主库等待从库写入 relay log 并返回 ACK 后才进行Engine Commit。
并行复制----解决从库复制延迟的问题,通过增加 SQL Thread线程数实现
复制延迟的根本原因:
在从库中有两个线程IO Thread和SQL Thread,都是单线程模式工作,因此有了延迟问题;
我们可以采用多线程机制来加强,减少从库复制延迟。(IO Thread多线程意义不大,主要指的是SQL Thread多线程:解析redaylog中的内容,并在从库上执行)
在MySQL的5.6、5.7、8.0版本上,都是基于上述SQL Thread多线程思想,不断优化,减少复制延迟。
上面说主从复制的根本目的是为了实现 读写分离:
在读写分离的应用场景下, 可以在从库追加多个索引来优化查询,主库这些索引可以不加,用于提升写效率。
为了避免主从同步出现的延迟性问题出现,我们也可以使用以下方案:
写后立刻读
在写入数据库后,某个时间段内读操作就去主库,之后读操作访问从库。
二次查询
先去从库读取数据,找不到时就去主库进行数据读取。该操作容易将读压力返还给主库,
根据业务特殊处理
根据业务特点和重要程度进行调整,比如重要的,实时性要求高的业务数据读写可以放在主库。对于次要的业务,实时性要求不高可以进行读写分离,查询时去从库查询。
查看全部 -
call
查看全部 -
j
查看全部 -
1
查看全部 -
ccc
查看全部 -
并发
查看全部 -
现场是CPU调度的基本单位也是执行的基本单位查看全部
-
一个进程可以有很多个线程查看全部
举报