Go语言八股文之Mysql锁详解

发布于:2025-05-16 ⋅ 阅读:(17) ⋅ 点赞:(0)

   💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。



非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
 

前言

小郑最近在准备Go语言的面试题,通过github和b站等各种学习网站上学习go语言的八股文,并且整理出自己觉得面试可能会问到的知识点,希望通过做笔记的方式来巩固自己的知识点,并且也希望可以帮助到大家在面试的时候更加得心应手一些,那么从现在开始,和我一起加入八股学习之旅吧!

1.为什么要加锁?

当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。 保证多用户环境下保证数据库完整性和一致性。

2.按照锁的粒度分数据库锁有哪些?

在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎 )和页级锁(BDB引擎 )。 行级锁

  • 行级锁是MySQL中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。
  • 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

表级锁

  • 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
  • 开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

页级锁

  • 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁
  • 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

MyISAM和InnoDB存储引擎使用的锁:

  • MyISAM采用表级锁(table-level locking)。
  • InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁

3.从锁的类别上分MySQL都有哪些锁呢?

从锁的类别上来讲,有共享锁和排他锁。

  • 共享锁: 又叫做读锁。 当用户要进行数据的读取时,对数据加上共享锁。共享锁可以同时加上多个。
  • 排他锁: 又叫做写锁。 当用户要进行数据的写入时,对数据加上排他锁。排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。

用上面的例子来说就是用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的。 一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以。 锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁。 他们的加锁开销从大到小,并发能力也是从大到小。

4.数据库的乐观锁和悲观锁是什么?怎么实现的?

  • 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制  (多写)
  • 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐一般会使用版本号机制或CAS算法实现。 (多读场景)

版本号(version)方式是一种实现乐观锁的常见方法,通常用于并发控制。其基本原理是给每条数据记录增加一个版本号,每次数据更新时,版本号都会递增。在更新操作时,系统会先检查该数据的版本号是否与当前操作时数据库中存储的版本号一致,如果一致则允许更新,否则说明数据已经被其他事务修改过,更新操作会被拒绝,事务需要重新执行。

5.InnoDB引擎的行锁是怎么实现的?

InnoDB是通过索引来实现行锁的,如果查询条件列是表的索引列,那么innoDB会根据索引定位到特点的行,并且对这些行进行加锁,确保事务完成之前其他事务没办法修改这些行。

如果是非索引列,那么innoDB就会对表进行全表扫描,这个过程会导致表锁,所以也意味着没办法并发执行操作。

6.什么是死锁?怎么解决?

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。 常见的解决死锁的方法 1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。 2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率; 3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率; 如果业务处理不好可以用分布式事务锁或者使用乐观锁

7.隔离级别与锁的关系

1.在Read Uncommitted级别下,读取数据不需要加共享锁,这样就不会跟被修改的数据上的排他锁冲突

2.在Read Committed级别下,读操作需要加共享锁,但是在语句执行完以后释放共享锁;

与锁的关系:在事务执行过程中,对读取的数据行会加共享锁,确保其他事务无法修改正在读取的数据,直到读取完成。

3.在Repeatable Read级别下,读操作需要加共享锁,但是在事务提交之前并不释放共享锁,也就是必须等待事务执行完毕以后才释放共享锁。

与锁的关系:在事务开始时,读取的数据会被锁住(共享锁),在整个事务生命周期中,不会释放这些锁,从而保证数据的一致性。其他事务无法修改或插入相同范围的数据,直到当前事务完成。

4.SERIALIZABLE 是限制性最强的隔离级别,因为该级别锁定整个范围的键,并一直持有锁,直到事务完成。

与锁的关系:该级别会锁定整个数据范围(包括正在读取的所有数据行),直到事务结束,因此会阻止其他事务修改、删除或插入范围内的任何数据。

隔离级别 锁类型 锁的持续时间 可能出现的并发问题
Read Uncommitted 无锁 无锁 脏读、不可重复读、幻读
Read Committed 共享锁(读取时加) 读取完后释放 不可重复读、幻读
Repeatable Read 共享锁(读取时加) 持续到事务结束 幻读
Serializable 范围锁(锁住数据范围) 直到事务完成 无脏读、不可重复读、幻读

❤️❤️❤️小郑是普通学生水平,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍


网站公告

今日签到

点亮在社区的每一天
去签到