事务和索引(面试常问)

面试常问:

一、数据库隔离级别?事务隔离级别解决的问题?

答:1.数据库隔离级别:

  • READ_UNCOMMITTED 读未提交
  • READ_COMMITTED 读提交(不可重复读)
  • REPEATABLE_READ 可重复读
  • SERIALIZABLE 串行化

2.事务的隔离级别解决的问题

(1)READ_UNCOMMITTED 读未提交

事务读取:不加锁

事务写入:加写锁

解决问题:脏写

存在问题:脏读、不可重复读、幻读。

(2)READ_COMMITTED 读提交(不可重复读)

事务读取:加读锁(每次select完成都会释放读锁)

事务写入:加写锁

解决问题:脏写、脏读

存在问题:不可重复读、幻读。

(3)REPEATABLE_READ 可重复读

事务读取:加读锁(每次select不会释放锁,而是事务结束后才释放)(如果是MySQL的InnoDB还会加间隙锁)

事务写入:加写锁

解决问题:脏写、脏读、不可重复读、幻读(如果是MySQL的InnoDB则解决)

存在问题:幻读(如果是MySQL的InnoDB则不存在)

(4)SERIALIZABLE 串行化

不管读取还是修改所有的事务串行化执行,一个事务的执行必须等其他事务结束。

二、幻读和不可重复度概念?

答:1.不可重复读 Unrepeatable Read

不可重复读指一个事务对统一数据的读取结果前后不一致

2.幻读 Phantom Read

幻读指事务读取某个范围的数据时,因为其他事物的操作导致前后两次读取的结果不一致

这两种情况都是事务并发时可能出现的问题。

三、数据库事务的理解以及实现原理?

**答:1.事务:**就是将一组SQL语句放在同一批次去执行,如果有一个SQL语句出错,则该批次内所有的SQL语句全部被取消执行。

2.实现原理:

  • **日志记录:**在事务执行过程中,对每一个操作都会进行日志记录。这些日志包含了操作的详细信息,用于在出现故障时进行恢复。

    例如,记录修改前和修改后的数据值。

  • **锁机制:**通过对数据加锁来保证事务的隔离性和并发控制。

    比如,在一个事务修改某行数据时,会对该行加排他锁,防止其他事务同时修改。

  • **回滚机制:**如果事务执行过程中出现错误或者事务被主动取消,能够根据日志记录将数据回滚到事务开始之前的状态。

  • 提交确认:当事务所有操作成功完成后,进行提交操作,将更改永久保存到数据库

四、说说你对锁的理解?

在MySQL中,特别是针对InnoDB存储引擎,存在多种类型的锁,⽤于控制事务之间的并发访问, 确保数据的⼀致性和隔离性。以下是⼀些常⻅的锁类型:

1. 共享锁(S):也称为读锁。当⼀个事务对某个数据项加了共享锁,其他事务可以同时对该数 据项加共享锁,但不能加排他锁。共享锁主要⽤于⽀持读取操作。

2. 排他锁(X):也称为写锁。当⼀个事务对某个数据项加了排他锁,其他事务不能对该数据项 加任何类型的锁。排他锁主要⽤于⽀持写⼊操作,如更新、插⼊或删除数据。

3. 意向共享锁(IS):事务想要获取⼀个表上的多个⾏的共享锁时,可以在表级别加意向共享 锁。这样可以减少锁的粒度,提⾼并发性能。

4. 意向排他锁(IX):事务想要获取⼀个表上的多个⾏的排他锁时,可以在表级别加意向排他 锁。这种锁表明事务可能需要对这些⾏加排他锁。

  1. 表锁:这种锁是在表级别上加的,通常⽤于MyISAM存储引擎。表锁包括表共享读锁和表排他 写锁,它们分别对应于共享锁和排他锁。

6. 行级锁:这种锁是在⾏级别上加的,主要⽤于InnoDB存储引擎。⾏级锁包括记录锁(Record Locks)、间隙锁(Gap Locks)和临键锁(Next-Key Locks)。这些锁主要⽤于实现 MVCC(多版本并发控制)和避免幻读现象。

7. 乐观锁:这种锁机制假设并发冲突较少,事务在提交时才检查是否有冲突。通常通过版本号或 时间戳来实现。

8. 悲观锁:这种锁机制假设并发冲突较多,事务在开始时就加锁,以防⽌其他事务的修改。这种 ⽅式可能导致锁等待和性能下降。

在实际应⽤中,MySQL会根据事务的需要和配置参数⾃动选择合适的锁类型,以平衡并发性能和 数据⼀致性。了解这些锁类型有助于优化数据库性能和解决并发访问问题。

五、InnoDB支持的锁是什么?

InnoDB 支持多种类型的锁,主要包括以下几种:

1.共享锁(Shared Lock,S 锁):允许其他事务读取锁定的数据,但不允许修改。多个事务可以同时持有共享锁。例如,在一个查询操作中,如果只是读取数据而不进行修改,就会获取共享锁。

2.排他锁(Exclusive Lock,X 锁):仅允许持有该锁的事务进行读取和修改操作,其他事务无法获取任何类型的锁。比如在进行数据修改或插入操作时,会获取排他锁。

3.意向共享锁(Intention Shared Lock,IS 锁):当事务想要在表的某些部分获取共享锁时,首先在表级别获取意向共享锁。

4.意向排他锁(Intention Exclusive Lock,IX 锁):当事务想要在表的某些部分获取排他锁时,首先在表级别获取意向排他锁。

5.记录锁(Record Lock):锁定表中的某一行记录。

6.间隙锁(Gap Lock):用于锁定一个范围,但不包含记录本身,主要用于防止幻读。

7.临键锁(Next-Key Lock):它是记录锁和间隙锁的组合,既锁住记录,又锁住记录前面的间隙。

这些锁的存在和协同工作,保证了 InnoDB 存储引擎在并发环境下的数据一致性和完整性。例如,在一个高并发的数据库系统中,多个事务同时对同一张表进行操作,通过合理地获取和释放各种锁,可以避免数据冲突和错误。

六、redis分布式和mysql实现的乐观锁有什么区别?

Redis分布式锁和MySQL乐观锁的主要区别在于数据存储方式、‌事务处理、‌隔离性、‌持久性和一致性保证。‌

1.数据存储方式:‌

Redis分布式锁 是通过在内存中存储锁的状态来实现的,‌而MySQL乐观锁是基于关系型数据库的行级别锁机制,‌通过在数据表中添加版本号或时间戳来实现并发控制。‌

2.事务处理:‌

Redis 事务只能保证事务内指令可以不被干扰地在同一批次执行,‌但没有机制保证全部成功则提交,‌部分失败则回滚。‌MySQL事务支持强原子性,‌有Undo Log机制,‌支持回滚。‌

3.隔离性:‌

MySQL 提供多个事务并发执行的能力,‌有MVCC机制保证隔离性。‌Redis在单线程环境下执行事务,‌没有提供多事务并发执行的隔离性保证。‌

4.持久性:‌

MySQL事务先写Undo Log,‌并有Redo Log的两阶段提交机制,‌可以保证持久性。‌

Redis只有RDB和AOF持久化策略,‌若事务成功执行且数据刚好被保存,‌则可以满足持久性要求。‌

5.一致性:‌

MySQL 保证数据库从一个合法状态转换成另一个合法状态的一致性。‌Redis只要执行不出错,‌可以保证一致性。‌

综上所述,‌Redis分布式锁和MySQL乐观锁在设计理念、‌实现方式以及保证的属性上都有显著的区别,‌选择使用哪种锁机制取决于具体的应用场景和需求

七、什么是死锁?怎么解决死锁?

1.死锁

在MySQL中,死锁是指两个或多个事务在等待对⽅释放锁的情况下,导致所有事务都⽆法继续执 ⾏的现象。死锁通常发⽣在事务并发操作且相互锁定资源时。

2.死锁产生的必要条件:

  1. **互斥条件:**资源只能被一个进程使用。
  2. 请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程阻塞,但仍保持已有的资源。
  3. 不可剥夺条件:进程所获得的资源在未使用完之前,不能被其他进程强行夺走。
  4. 循环等待条件:存在一种进程资源的循环等待链。

3.死锁检测

  • **使⽤INFORMATION_SCHEMA:**可以通过查询 INFORMATION_SCHEMA.INNODB_TRX 和 INFORMAT ION_SCHEMA.INNODB_LOCKS 这两个视图来检测事务和锁的状态。

    SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

这些查询可以帮助你了解当前活跃的事务及其持有的锁信息。

  • SHOW ENGINE INNODB STATUS: 这个命令可以显示InnoDB存储引擎的当前状态,包括锁 信息、事务状态等,有助于分析死锁情况。

    SHOW ENGINE INNODB STATUS;

4.解决死锁的方法

  • 设置超时时间: 通过设置 innodb_lock_wait_timeout 参数,可以指定事务等待锁的超时时 间。超过这个时间后,事务将⾃动回滚。

    SET GLOBAL innodb_lock_wait_timeout = 60;

  • ⼿动⼲预: 通过查询 INFORMATION_SCHEMA.INNODB_TRX 找到死锁的事务,然后⼿动杀死其中⼀ 个事务,以解除死锁。

    SELECT trx_mysql_thread_id FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_sta
    te = 'LOCK WAIT';
    KILL trx_mysql_thread_id;

  • 调整事务的执⾏顺序: 改变事务中SQL语句的执⾏顺序,或者调整事务的⼤⼩和范围,可以避 免死锁的发⽣。

  • 使⽤死锁检测⼯具: MySQL本身没有内置的死锁检测⼯具,但可以通过第三⽅⼯具或⾃定义脚 本来检测和处理死锁。

  • 优化锁的使⽤: 尽量减少锁的持有时间,避免在事务中进⾏⻓时间的计算或等待操作。尽量使 ⽤低隔离级别的事务,以减少锁的使⽤。

  • 使⽤悲观锁或乐观锁: 根据实际情况选择适合的锁策略。悲观锁适⽤于并发冲突较多的场景, 乐观锁适⽤于并发冲突较少的场景。

通过以上⽅法,可以有效地检测和解决MySQL中的死锁问题,提⾼系统的稳定性和性能。

例如,在一个数据库系统中,如果两个事务分别持有一部分数据的锁,并同时请求对方持有的锁,就可能导致死锁。可以通过合理的事务设计和资源分配策略来预防或解决死锁问题。

八、说说索引?底层是什么数据结构(索引的底层结构是什么)?为什么用B+树?为什么不用红黑树?

1.定义:索引是数据库的一种排序结构,用于加快数据的检索和查询速度。

2.索引的底层数据结构B+树

3.用B+树,不用红黑树做数据结构的原因:

  • **磁盘访问:**处理大量磁盘存储数据,B+树节点容纳键值对多,减少磁盘 I/0 次数。
  • **数据组织:**B+树数据记录存于叶子节点,连续存储便于范围查询和顺序访问。
  • **高度平衡:**B+树节点含更多子节点,高度低,查询效率高,红黑树结构调整多。
  • **空间利用:**B+树非叶子节点不存数据记录,空间利用率高。
  • **并发控制:**B+树更易支持并发操作,范围查询时易实现锁粒度控制。

综上,B+树在磁盘、数据组织、查询、空间和并发控制等方面更适合数据库索引,所以被 MySQL 选用。

九、B树和B+树的区别?为什么数据库索引使用了B+树?谈谈相对于B树的优点?

1.B树和B+树的区别

B树(B-Tree)和B+树(B+-Tree)是两种常用的数据结构,特别是在数据库和文件系统中用于实现索引。它们的主要区别:

(1)数据存储位置

  • B树: 数据可以存储在非叶子节点和叶子节点中。每个节点包含一组键值对,这些键值对按顺序排列。
  • B+树: 所有数据记录都存储在叶子节点中。非叶子节点仅包含键值,用于指导搜索路径。

(2)节点结构

  • B树: 每个节点包含多个键值对和多个子节点指针。节点内的键值对和子节点指针数量之间存在一定的关系,以保持平衡。
  • B+树: 每个非叶子节点包含多个键值和相同数量的子节点指针。叶子节点除了包含数据记录外,还包含指向相邻叶子节点的指针,形成一个链表。

(3)搜索性能

  • B树: 搜索操作可能需要访问非叶子节点,搜索路径上的每个节点都需要比较和跳转。
  • B+树: 搜索操作只需访问叶子节点。由于叶子节点形成一个链表,搜索过程中可以快速遍历所有键值。

(4)插入和删除操作

  • B树: 插入和删除操作可能导致节点分裂或合并,维护树的平衡。
  • B+树: 插入和删除操作仅影响叶子节点,非叶子节点仅需更新键值和指针信息。

(5) 应用场景

  • B树: 适用于需要快速访问中间节点数据的场景,如文件系统中的目录结构。
  • B+树: 适用于需要频繁搜索、插入和删除操作的场景,如数据库索引。由于所有数据都在叶子节点,B+树在范围查询和排序方面更具优势。

2.数据库索引使用 B+树的原因以及相对于 B 树的优点

(1) **磁盘读写代价更低:**B+树的非叶子节点不存储数据,相同磁盘页可以容纳更多的关键字,降低了树的高度,减少了磁盘 I/O 次数。

(2) 范围查询更高效:B+树的叶子节点通过链表相连,便于进行范围查询,而 B 树则不便于范围查询。

(3) **数据存储更集中:**B+树的所有数据都存储在叶子节点,方便进行数据的批量读取和写入。

(4) **稳定性更高:**B+树的插入和删除操作相对更稳定,对树的结构调整较小。

十、聚簇索引是什么?

1.如果表设置了主键,则主键就是聚簇索引

2.如果表没有主键,则会默认第一个NOT NULL,且唯一(UNIQUE)的列作为聚簇索引

3.以上都没有,则会默认创建一个隐藏的row_id作为聚簇索引

InnoDB 的聚簇索引的叶子节点存储的是行记录(其实是页结构,一个页包含多行数据),InnoDB必须要有至少一个聚簇索引
由此可见,使用聚簇索引查询会很快,因为可以直接定位到行记录

十一、使用普通索引查询的过程?索引是怎么发挥作用的?

1.定义:普通索引也叫二级索引, 除聚簇索引外的索引,即非聚簇索引。
InnoDB的普通索引叶子节点存储的是主键(聚簇索引)的值,而MyISAM的普通索引存储的是记录指针。

2.步骤:(这个过程叫做回表

  • 首先,数据库系统会在普通索引中查找与查询条件匹配的索引值。普通索引通常存储的是索引列的值以及对应的主键值。
  • 找到匹配的索引值后,通过索引中存储的主键值,再去主键索引(如果有的话)中查找完整的行数据。

3.作用:

(1) 索引发挥作用的关键在于它能够大大减少数据库需要扫描的数据量。如果没有索引,数据库可能需要逐行扫描整个表来查找符合条件的数据,这是非常耗时的。而有了索引,就能够快速定位到可能包含符合条件数据的位置,从而提高查询效率

(2) **(缺点)**但需要注意的是,过多的索引会增加数据插入、更新和删除操作的开销,因为这些操作不仅要更新数据,还要维护相关的索引。所以,在设计数据库时,需要合理地创建索引,权衡查询性能和数据维护的成本。

十二、全文索引是什么?是什么结构?

**1.定义:**全文索引是一种特殊的索引类型,主要用于对文本类型的字段(如文章内容、评论等)进行快速搜索。

**2.数据结构:**它的结构通常基于 倒排索引倒排索引类似于一个字典,其中包含了单词(或称为词项)以及包含这些单词的文档列表。

十三、导致索引失效的情况?

  1. 最佳左前缀法则
  2. 主键插入顺序
  3. 计算、函数导致索引失效
  4. 类型转换导致索引失效
  5. 范围条件右边的列索引失效
  6. 不等于(!= 或者<>)索引失效
  7. is null可以使用索引,is not null无法使用索引
  8. like以通配符%开头索引失效
  9. OR 前后存在非索引的列,索引失效
  10. 数据库和表的字符集统一使用utf8mb4
相关推荐
chengooooooo6 小时前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展
码农爱java7 小时前
设计模式--抽象工厂模式【创建型模式】
java·设计模式·面试·抽象工厂模式·原理·23种设计模式·java 设计模式
测试杂货铺7 小时前
如何用postman做接口自动化测试及完美的可视化报告?
自动化测试·软件测试·测试工具·职场和发展·jenkins·压力测试·postman
Jiude7 小时前
算法题题解记录——双变量问题的 “枚举右,维护左”
python·算法·面试
撞上电子9 小时前
蓝桥杯物联网开发板硬件组成
物联网·职场和发展·蓝桥杯
pzx_0019 小时前
【LeetCode】LCR 175.计算二叉树的深度
开发语言·c++·算法·leetcode·职场和发展
Aloha_up9 小时前
LeetCode hot100-89
算法·leetcode·职场和发展
测试老哥11 小时前
Jmeter测试脚本编写技巧
自动化测试·软件测试·功能测试·测试工具·jmeter·职场和发展·性能测试
长安051113 小时前
面试经典题目:LeetCode134_加油站
c++·算法·面试
Jamesvalley14 小时前
【工作流】工作顺序
职场和发展