面试之MySQL中的锁

请说一下数据库锁的种类?

MySQL数据库由于自身架构的特点,存在多种数据储存引擎,MySQL中冈的储存引擎支持不同的锁机制。

MylSAM 和 MEMORY 存储引擎采用的是表级锁。

InnoDB储存引起既支持行级锁,也支持表级锁,默认情况下采用行级锁。

按照数据的操作类型分:

读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。

写锁(排他锁):写操作没有完成前。它会阻断其他写锁和读锁。

按照数据操作的粒度分:

表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发度最低。

行级锁:开销大,枷锁慢,不会出现死锁。锁定粒度小,发生锁定冲突的概率最低,并发度最高。

页面锁:开销和加锁时间介于表锁和行锁之间,会出现死锁,锁定粒度界于表锁和行锁之间,并发度一般。

操作性能分为 乐观锁和  悲观锁

乐观锁:实际上并没有加锁,只是锁一种思想。乐观的意思说,我每次拿数据的时候,认为别人不会修改,所以不会上锁,但是在提交的时候才会判断一下别人有没有修改过这个数据 。乐观锁适用于多读少写的场景。这样可以提高 吞吐量。通过在行数据上添加版本号,如果版本号跟预期的不一致则更新失败。(对于java来说,CAS,CurrentHashMap,atomic  都是 乐观锁)

当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:

  • 取出记录时,获取当前 version
  • 更新时,带上这个 version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果 version 不对,就更新失败

悲观锁:顾名思义,就是很悲观,每次去拿数据都认为别人去改数据,所以每次拿数据的时候都会上锁,这样别人想拿这个锁就会 block。(在java中的syschronized就是悲观锁)

乐观锁比较适用于读多写少的情况(多读场景),悲观锁比较适用于写多读少的情况(多写场景)。

请你谈谈共享锁和排他锁:

行为锁分为共享锁和排他锁:

行锁的是mysql锁中粒度最小的一种锁,因为锁的粒度很小,所以发生资源争抢的概率也很少,并发性能很大,但是 也会造成死锁,每次加锁和释放锁的开销也会很大。

使用MySQL行级锁的两个前提:

使用innoDB引擎

开启事务(隔离级别为Repeatale Read)

InnoDB行锁的类型:

共享锁(S):当事务对数据加上共享锁后,其他用户可以并发读取数据,但任务事务都不能对数据进行修改,直到已释放所有的共享锁。

排他锁(X):如果事务T对数据A加上排他锁后,则其他事务不能再对数据A加任何类型的封锁。获取排他锁的事务可以 读数据,也可以写锁。

加锁的方式:

   InnoDB引擎默认更新语句,update,delete,insert 都会自动 给涉及的数据 加上排他锁,select语句不会任何类型的锁,如果要加可以使用下面的方式:

 加共享锁(S):select * from table_name where lock in share mode;

 加排他锁(X): select * from table_name where for update;

锁兼容:

 共享锁只能兼容共享锁,不兼容排他锁。

  排他锁互斥 共享锁 和其他排他锁。

InnoDB的行锁是怎么实现的?

      InnoDB行锁是通过对索引页上的记录加锁实现的。主要实现算法有3中:Record Lock,Grp Lock 和Next - key Lock.

RecordLock锁:锁定单个行记录的锁。(记录锁,RC,RR 隔离级别 都支持)。

GapLock锁:间隙锁,锁定索引记录间隙,确保索引的间隙不变。(外围锁,RR隔离级别支持)。

Next-key-Lock锁:  记录锁 和间隙锁组合,同时锁住数据,并且锁住数据前后范围。(记录锁+范围锁,RR隔离级别锁支持)

你可能感兴趣的:(面试,mysql,职场和发展)