4面试题--数据库(补充)

news2024/11/28 10:38:42

隔离性问题

若不考虑隔离性则会出现以下问题
1. 脏读:指⼀个事务在处理数据的过程中,读取到另⼀个 未提交 事务的数据
2. 不可重复读:指对于数据库中的某个数据(同⼀个数据项),⼀个事务内的多次查询却返回了不同
的结果。这是由于在查询过程中,数据被另外⼀个事务修改并 提交 了。可通过 锁⾏ 解决
3. 幻读:指事务⾮独⽴执⾏时发⽣的⼀种现象。例如事务T1对⼀个表中所有的⾏的某个数据做了修改,这时事务T2⼜向这个表中插⼊了⼀⾏数据项,⽽这个数据项的数据是以修改前的值 提交 到数据库的。⽽操作事务T1的⽤户如果查看刚刚修改的数据,会发现还有⼀⾏没有修改,其实这⾏是事务T2刚刚添加的,就好像产⽣幻觉⼀样,这就是幻读(针对⼀整批数据,即数据的个数)。可通过锁表 解决
Next-Key锁解决幻读
为了解决“当前读”中的幻读问题,MySQL事务使⽤了Next-Key锁。Next-Key锁是⾏锁和间隙锁的合并。间隙锁指的是锁加在不存在的空闲空间,可能是第⼀个索引记录之前或最后⼀个索引之后的空间。当InnoDB扫描索引记录的时候,会⾸先对选中的索引记录加上⾏锁,再对索引记录两边的间隙(向左扫描扫到第⼀个⽐给定参数⼩的值, 向右扫描扫描到第⼀个⽐给定参数⼤的值, 然后以此为界,构建⼀个区间)加上间隙锁。如果⼀个间隙被事务T1加了锁,其它事务是不能在这个间隙插⼊记录的。这样就 防⽌了幻读

隔离级别

1. 读未提交(Read uncommitted):这种事务隔离级别下,select 语句不加锁。可能读到不⼀致的数据,即脏读。这是并发最⾼,⼀致性最差的隔离级别。
2. 读已提交(Read committed):每次查询返回当前的快照。有不可重复读的问题。
3. 可重复读(Repeatable read):多次读取同⼀范围的数据会返回第⼀次查询的快照。MySQL默认隔离级别。
4. 串⾏化(Serializable):InnoDB 隐式地将全部的查询语句加上共享锁,解决了幻读的问题
读已提交、可重复读实现⽅式:MVCC。

4.7 数据库中的锁

按锁的粒度划分:
表级锁:表级锁分为表共享锁和表独占锁。表级锁开销⼩,加锁快,锁定粒度⼤,发⽣锁冲突最
⾼,并发度最低
⻚级锁:⻚级锁是MySQL中锁定粒度介于⾏级锁和表级锁中间的⼀种锁,⼀次锁定相邻的⼀组记录。
⾏级锁:⾏级锁分为共享锁和排他锁。⾏级锁是MySQL中锁定粒度最细的锁。InnoDB引擎⽀持⾏级锁和表级锁,只有在通过索引条件检索数据的时候,才使⽤⾏级锁,否就使⽤表级锁。⾏级锁开销⼤,加锁慢,锁定粒度最⼩,发⽣锁冲突的概率最低,并发度最⾼。
按锁级别划分:
共享锁:共享锁⼜叫读锁,如果事务T对A加上共享锁,则其他事务只能对A再加共享锁,不能加其他锁。共享锁的事务只能读数据,不能写数据。
排它锁:排他锁⼜叫写锁,如果事务T对A加上排它锁,则其他事务都不能对A加任何类型的锁。获得排它锁的事务既能读数据,⼜能写数据
意向锁:意向锁是⼀种不与⾏级锁冲突的表级锁。意向锁是由数据库引擎⾃⼰维护的,⽤户⽆法⼿动操作意向锁,在为数据⾏加共享 / 排他锁之前,InnoDB 会先获取该数据⾏所在数据表的对应意向锁。意向锁的⽬的是为了快速判断表⾥是否有记录被加锁。

意向锁(Intention Locks)

意向锁分为两种:
意向共享锁(intention shared lock, IS):事务有意向对表中的某些⾏加共享锁(S锁)。事务要获取某些⾏的 S 锁,必须先获得表的 IS 锁。
意向排他锁(intention exclusive lock, IX):事务有意向对表中的某些⾏加排他锁(X锁)。事务要获取某些⾏的 X 锁,必须先获得表的 IX 锁。
注意
上图的排他 / 共享锁指的都是表锁!!!意向锁不会与⾏级的共享 / 排他锁互斥!!!
意向锁在保证并发性的前提下,实现了⾏锁和表锁共存且满⾜事务隔离性的要求。
事务 B 检测到事务 A 持有某表的意向排他锁,就可以得知事务 A 必然持有该表中某些数据⾏的排他锁,那么事务 B 对该表的加锁请求就会被排斥(阻塞),⽽⽆需去检测表中的每⼀⾏数据是否存在排他锁。

多版本并发控制(MVCC)

        

MySQL 的⼤多数事务型存储引擎实现的都不是简单的⾏锁。⽽是基于提升并发性能的考虑,实现了多版本并发控制(MVCC)。可以认为,MVCC是⾏锁的⼀个变种,但它在很多情况下避免了加锁操作,减少了开销。MVCC实现了⾮阻塞的读操作,写操作也只锁定必要的⾏。

MVCC 实现⽅式:Read View

Read View 有四个重要的字段:
creator_trx_id :指的是创建该 Read View 的事务的事务 id。
m_ids :指的是在创建 Read View 时,当前数据库中「活跃事务」的事务 id 列表,“活跃事务”指
的就是启动了但还没提交的事务。
min_trx_id :指的是在创建 Read View 时,当前数据库中「活跃事务」中事务 id 最⼩的事务,也
就是 m_ids 的最⼩值。
max_trx_id :这个并不是 m_ids 的最⼤值,⽽是创建 Read View 时当前数据库中应该给下⼀个事
务的 id 值,也就是全局事务中最⼤的事务 id 值 + 1;
对于使⽤ InnoDB 存储引擎的数据库表,它的聚簇索引记录中都包含下⾯两个隐藏列:
trx_id,当⼀个事务对某条聚簇索引记录进⾏改动时,就会把该事务的事务 id 记录在 trx_id 隐藏列
⾥;roll_pointer,每次对某条聚簇索引记录进⾏改动时,都会把旧版本的记录写⼊到 undo ⽇志中,然后这个隐藏列是个指针,指向每⼀个旧版本记录,于是就可以通过它找到修改前的记录。
在创建 Read View 后,⼀个事务去访问记录的时候,除⾃⼰的更新记录总是可⻅之外,还有如下情况:如果当前⾏的 trx_id 值⼩于 Read View 中的 min_trx_id 值,表示这个版本的记录是在创建 Read View 前已经提交的事务⽣成的,所以该版本的记录对当前事务可⻅。
如果当前⾏的 trx_id 值⼤于等于 Read View 中的 max_trx_id 值,表示这个版本的记录是在创建
Read View 后启动的事务⽣成的,所以该版本的记录对当前事务不可⻅。
如果当前⾏的 trx_id 值在 Read View 的 min_trx_id 和 max_trx_id 之间,需要判断 trx_id 是否
在 m_ids 列表中:- 如果当前⾏的 trx_id 在 m_ids 列表中,表示⽣成该版本记录的活跃事务依然活跃着(还没提交事务),所以该版本的记录对当前事务不可⻅。
- 如果当前⾏的 trx_id 不在 m_ids列表中,表示⽣成该版本记录的活跃事务已经被提交,所以该
版本的记录对当前事务可⻅。
当记录不可⻅时会通过roll_pointer指针找到可⻅的第⼀个记录读取。这种通过「版本链」来控制并发事务访问同⼀个记录时的⾏为就叫 MVCC(多版本并发控制)。
读已提交隔离级别是在每次读取数据时,都会⽣成⼀个新的 Read View。意味着,事务期间的多次读取同⼀条数据,前后两次读的数据可能会出现不⼀致,因为这期间另外⼀个事务可能修改了该记录,并提交了事务。 可重复读 隔离级别是在执⾏第⼀个查询语句后⽣成⼀个 Read View,然后整个事务期间都在⽤这个

Read View

快照读与当前读
1. 快照读:读取历史数据的⽅式,如普通的select语句。
2. 当前读:读取数据库当前版本数据的⽅式,是特殊的读操作。插⼊、更新、删除操作,都属于当前读,处理的都是当前的数据,需要加锁。不过 select .. for update 语句就不是快照读了,⽽是当
前读了。

4.8 查询优化⽅法

避免向数据库请求不需要的数据
在访问数据库时,应该只请求需要的⾏和列。请求多余的⾏和列会消耗MySql服务器的CPU和内存资源,并增加⽹络开销。避免使⽤ SELECT * 这种⽅式进⾏查询,应该只返回需要的列。例如在处理分⻚时,应该使⽤ LIMIT 限制MySql只返回⼀⻚的数据,⽽不是向应⽤程序返回全部数据后,再由应⽤程序过滤不需要的⾏。
优化查询数据的⽅式
查询数据的⽅式有全表扫描、索引扫描、范围扫描、唯⼀索引查询、常数引⽤等。这些查询⽅式,速度从慢到快,扫描的⾏数也是从多到少。可以通过 EXPLAIN 语句中的 type 列反应查询采⽤的是哪种⽅式。
通常可以通过添加合适的索引改善查询数据的⽅式,使其尽可能减少扫描的数据⾏,加快查询速
度。例如,当发现查询需要扫描⼤量的数据⾏但只返回少数的⾏,那么可以考虑使⽤覆盖索引,即
把所有需要⽤到的列都放到索引中。这样存储引擎⽆须回表获取对应⾏就可以返回结果了。
当⼀⾏数据被多次使⽤时可以考虑将数据⾏缓存起来,避免每次使⽤都要到MySql查询。
update 语句应使⽤索引查询,否则全表查询会对所有记录加锁(⾮表锁),甚⾄导致业务停滞。分解查询
可以将⼀个⼤查询切分成多个⼩查询执⾏,每个⼩查询只完成整个查询任务的⼀⼩部分,每次只返回⼀⼩部分结果
分解关联查询,即对每个要关联的表进⾏单表查询,然后将结果在应⽤程序中进⾏关联。优化 LIMIT 分⻚
● 处理分⻚会使⽤到 LIMIT,当翻⻚到⾮常靠后的⻚⾯的时候,偏移量会⾮常⼤,这时LIMIT的效率 ⾮常差。例如对于LIMIT 10000,20这样的查询,MySql需要查询10020条记录,将前⾯10000条记 录抛弃,只返回最后的20条。这样的代价⾮常⾼,如果所有的⻚⾯被访问的频率都相同,那么这样 的查询平均需要访问半个表的数据。优化此类分⻚查询的⼀个最简单的办法就是尽可能地使⽤索引 覆盖扫描,⽽不是查询所有的列。然后根据需要与原表做⼀次关联操作返回所需的列。对于偏移量 很⼤的时候,这样的效率提升⾮常⼤。
优化 UNION 查询
除⾮确实需要服务器消除重复的⾏,否则⼀定要 使⽤UNION ALL。如果没有ALL关键字,MySql会给临时表加上 DISTINCT 选项,这会导致对整个临时表的数据做唯⼀性检查。这样做的代价⾮常⾼。
group by 查询原理:
在MySQL 中,GROUP BY 的实现同样有多种(三种)⽅式,其中有两种⽅式会利⽤现有的索引信息来完成 GROUP BY,另外⼀种为完全⽆法使⽤索引的场景下使⽤。GroupBy会默认按照分组的字段进⾏排序;如果不需要排序,可使⽤order by null
使⽤松散(Loose)索引扫描实现 GROUP BY
MySQL 完全利⽤索引扫描来实现GROUP BY ,并不需要扫描所有满⾜条件的索引键即可完成操作得出结果。Extra信息中显示:Using index for group-by 要利⽤到松散索引扫描实现 GROUP BY,需要⾄少满⾜以下⼏个条件:
GROUP BY 条件字段必须在同⼀个索引中最前⾯的连续位置;
在使⽤GROUP BY 的同时,只能使⽤ MAX 和 MIN 这两个聚合函数;
如果引⽤到了该索引中 GROUP BY 条件之外的字段条件的时候,必须以常量形式存在; 松散索引扫描需要读取的键值数量与分组的数量⼀样多,尽可能读取最少数量的关键字。
使⽤紧凑(Tight)索引扫描实现 GROUP BY 和松散索引扫描的区别是需要读取所有满⾜条件的索引值,之后取数据完成操作。Extra中不显示for group-by,在 MySQL 中,⾸先会选择尝试通过松散索引扫描来实现 GROUP BY 操作,当发现某些情况⽆法满⾜松散索引扫描实现 GROUP BY 的要求之后,才会尝试通过紧凑索引扫描来实现。(⽐如GROUP BY 条件字段并不连续或者不是索引前缀部分的时候)使⽤临时表实现 GROUP BY 当⽆法找到合适的索引可以利⽤的时候,就不得不先读取需要的数据,然后通过临时表来完成 GROUP BY 操作。Extra:Using temporary; Using filesort。

union、join 区别

1. union 在数据库运算中会过滤掉重复数据,并且合并之后是根据⾏合并的;
2. union all 不对数据进⾏过滤重复数据处理;
3. union 之后列数不变(两张表 union 保证列数和列结构⼀样 join 是进⾏表关联运算的,两个表要有⼀定的关系(某列可连接)。根据某⼀列进⾏笛卡尔运算和条件过滤,如果A表有3列,B表有3列,join 之后可能是5列。

mysql 深度分⻚

mysql 分⻚查询是我们常⻅的需求,但是随着⻚数的增加查询性能会逐渐下降,尤其是到深度分⻚的情况。可以把分⻚分为两个步骤,1.定位偏移量,2.获取分⻚条数的数据。所以当数据较⼤⻚数较深时就涉及⼀次需要耗费较⻓时间的操作。所以mysql深度分⻚的问题该如何解决呢 ?
以结果作为条件,已查询条件的变化换取分⻚的不变。分⻚查询⼀般都是逐渐往后翻⻚的,那么可以很清晰的知道,在当前查询⻚的最后⼀条数据的位置,那么,以此位置再查询N条,以位置的推移换取⻚数的不变,减少其偏移量的计算。
采⽤⼦查询模式,其原理依赖于覆盖索引,当查询的列均是索引字段时,性能较快,因为其只⽤遍历索引本身。针对复杂的查询逻辑,⼀般从数据的 偏移量着⼿,减少偏移量的定位时间。
简单的查询逻辑,可以从索引覆盖的思想着⼿,先确定查询数据的主键id,再由id找相关的数据。

4.9 主从复制

具体详细过程如下:
MySQL 主库在收到客户端提交事务的请求之后,会先写⼊ binlog,再提交事务更新存储引擎中的数据,事务提交完成后,返回给客户端“操作成功”的响应。
从库会创建⼀个专⻔的 I/O 线程,连接主库的 log dump 线程,来接收主库的 binlog ⽇志,再把
binlog 信息写⼊ relay log 的中继⽇志⾥,再返回给主库“复制成功”的响应。
从库会创建⼀个⽤于回放 binlog 的线程,去读 relay log 中继⽇志,然后回放 binlog 更新存储引
擎中的数据,最终实现主从的数据⼀致性。
在完成主从复制之后,你就可以在写数据时只写主库,在读数据时只读从库,这样即使写请求会锁表或者锁记录,也不会影响读请求的执⾏。
从库是不是越多越好?不是的。因为从库数量增加,从库连接上来的 I/O 线程也⽐较多,主库也要创建同样多的 log dump 线程来处理复制的请求,对主库资源消耗⽐较⾼,同时还受限于主库的⽹络带宽。所以在实际使⽤中,⼀个主库⼀般跟 2~3 个从库(1 套数据库,1 主 2 从 1 备主),这就是⼀主多从的 MySQL 集群结构。MySQL 主从复制还有哪些模型?
同步复制:MySQL 主库提交事务的线程要等待所有从库的复制成功响应,才返回客户端结果。这种⽅式在实际项⽬中,基本上没法⽤,原因有两个:⼀是性能很差,因为要复制到所有节点才返回
响应;⼆是可⽤性也很差,主库和所有从库任何⼀个数据库出问题,都会影响业务。
118 119
异步复制(默认模型):MySQL 主库提交事务的线程并不会等待 binlog 同步到各从库,就返回客
户端结果。这种模式⼀旦主库宕机,数据就会发⽣丢失。
半同步复制:MySQL 5.7 版本之后增加的⼀种复制⽅式,介于两者之间,事务线程不⽤等待所有的从库复制成功响应,只要⼀部分复制成功响应回来就⾏,⽐如⼀主⼆从的集群,只要数据成功复制到任意⼀个从库上,主库的事务线程就可以返回给客户端。这种半同步复制的⽅式,兼顾了异步复制和同步复制的优点,即使出现主库宕机,⾄少还有⼀个从库有最新的数据,不存在数据丢失的⻛险。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1256845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

yo!这里是异常相关介绍

目录 前言 异常的概念 异常的抛出与捕获 捕获过程 重新抛出 规范 异常体系 自定义 标准库 异常的优缺点 后记 前言 对于程序运行时发生的错误,比如内存错误、除0错误等类型,你会如何处理?是使用assert终止程序或是使用exit返回错误…

Redis 事件轮询

1 Redis 为什么快 数据存在内存中, 直接操作内存中的数据单线程处理业务请求避免了多线的上下文切换, 锁竞争等弊端使用 IO 多路复用支撑更高的网络请求使用事件驱动模型, 通过事件通知模式, 减少不必要的等待… 这些都是 Redis 快的原因。 但是这些到了代码层面是如何实现的呢…

P18 C++ 继承

目录 前言 01 不使用继承会让你多打很多无用的代码 02 继承 最后的话 前言 本期我们学习 C 面向对象编程中的继承。 面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做&#…

【云平台】STM32微信小程序阿里云平台汇总——持续更新

【云平台】STM32微信小程序阿里云平台汇总——持续更新 文章目录 前言总结 前言 提示:以下是本篇文章正文内容,下面案例可供参考 【云平台】STM32微信小程序阿里云平台学习板 【云平台】小白从零开始:小程序阿里云平台控制STM32&#xff08…

Centos 7.9 Install Docker Insecure Registry

文章目录 1. 镜像存储规划2. 安装定制 docker3. 部署 registry4. 验证镜像仓库 1. 镜像存储规划 linux LVM /dev/sdb mount dir /data【linux LVM 磁盘挂载目录】 创建两个目录 一个 docker 数据存储目录 :/data/docker,默认一般为linux为 /var/lib/d…

Java游戏制作——王者荣耀

一.准备工作 首先创建一个新的Java项目命名为“王者荣耀”,并在src下创建两个包分别命名为“com.sxt"、”com.stx.beast",在相应的包中创建所需的类。 创建一个名为“img”的文件夹来储存所需的图片素材。 二.代码呈现 package com.sxt;import javax.sw…

B树你需要了解一下

介绍B树的度数主要特点应用场景时间复杂度代码示例拓展 介绍 B树(B-tree)是一种自平衡的树,能够保持数据有序,常被用于数据库和文件系统的实现。 B树可以看作是一般化的二叉查找树,它允许拥有多于2个子节点。与自平衡…

大数据Doris(二十九):数据导入(Insert Into)

文章目录 数据导入(Insert Into) 一、​​​​​​​创建导入

Echarts 最简单创建柱状图

设置容器 <div ref"myChart" style"width: 500px; height: 500px;"> </div>mounted() {//document渲染完成this.draw()}draw() {const myChart this.$echarts.init(this.$refs.myChart)//初始化对象myChart.setOption({ //参数配置项title: …

OSG编程指南<十一>:OSG几何体操作及三维地形创建

1、简化几何体 在 OSG 中&#xff0c;场景都是由基本的绘图基元构成的&#xff0c;基本的绘图基元构成简单的几何体&#xff0c;简单的几何体构成复杂的几何体&#xff0c;复杂的几何体最终构造成复杂的场景。当多个几何体组合时&#xff0c;可能 存在多种降低场景渲染效率的原…

【双指针】三数之和

三数之和 在做这道题之前&#xff0c;建议建议先将两数之和做完再做&#xff0c;提升更大~ 文章目录 三数之和题目描述算法原理解法一解法二思路如下&#xff1a;处理细节问题&#xff1a; 代码编写Java代码编写C代码编写 15. 三数之和 - 力扣&#xff08;LeetCode&#xff0…

62 权限提升-烂土豆dll劫持引号路径服务权限

目录 演示案例:Win2012-烂士豆配合令牌窃取提权-Web权限Win2012-DLL劫持提权应用配合MSF-Web权限Win2012-不安全的服务权限配合MSF-本地权限Win2012-不带引号服务路径配合MSF-Web&#xff0c;本地权限补充说明: dll劫持提权及AlwaysInstallElevated等说明关于Windows相关知识点…

Redis未授权访问-CNVD-2019-21763复现

Redis未授权访问-CNVD-2019-21763复现 利用项目&#xff1a; https://github.com/vulhub/redis-rogue-getshell 解压后先进入到 RedisModulesSDK目录里面的exp目录下&#xff0c;make编译一下才会产生exp.so文件&#xff0c;后面再利用这个exp.so文件进行远程代码执行 需要p…

微机原理_5

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 8086微处理器CLK引脚输入时钟信号是由(提供。 A. 8284 B. 8288 C.8287 D. 8289 2.下面4个寄存器中,不能作为间接寻址的寄存器是(…

hivesql 将json格式字符串转为数组

hivesql 将json格式字符串转为数组 完整过程SQL在文末 json 格式字符串 本案例 json 字符串参考格式&#xff0c;请勿使用本数据 {"data": [{"province": 11,"id_card": "110182198903224674","name": "闾丘饱乾"…

【开源】基于JAVA的高校学院网站

项目编号&#xff1a; S 020 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S020&#xff0c;文末获取源码。} 项目编号&#xff1a;S020&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学院院系模块2.2 竞赛报名模块2.3 教…

人工智能_机器学习051_支持向量机SVM概念介绍_理解support vector machine---人工智能工作笔记0091

在出现深度学习,神经网络算法之前,支持向量机已经可以解决很多问题了,我们自然界中的问题,无非就是可以转换为回归问题和分类问题. 然后从现在开始我们来看支持向量机,首先看一下这几个字 support 是支持 vector是向量的意思,然后 machine指的是机器 那么我们之前用到的模型…

85基于Matlab的交通设施识别

基于Matlab的交通设施识别。 GUI设计图像处理, 基于数字图像处理&#xff0c;设计实现一个自然场景下公路交通限速标志分割和识别的程序。要求系统具有界面&#xff0c;并实现以下功能&#xff1a; 1&#xff09;读入自然场景下包含交通标志的图像&#xff1b; 2&#xff09;对…

Qt TCP网络上位机的设计(通过网络编程与下位机结合)

目录 TCP 协议基础 QTcpServer 和 QAbstractSocket 主要接口函数 TCP 应用程序 1.服务端 2.客户端 上位机通过网络编程与下位机实现通信 TCP 协议基础 传输控制协议&#xff08;TCP&#xff0c;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的、基于…

蓝桥杯-动态规划-子数组问题

目录 一、乘积最大数组 二、乘积为正数的最长子数组长度 三、等差数列划分 四、最长湍流子数组 心得&#xff1a; 最重要的还是状态表示&#xff0c;我们需要根据题的意思&#xff0c;来分析出不同的题&#xff0c;不同的情况&#xff0c;来分析需要多少个状态 一、乘积最…