掌握了这些数据库要点,你也能在面试上游刃有余了,(二)锁

我是方圆,愿你我皆能在面试中游刃有余

1. MyISAM和InnoDB锁的区别

  • MyISAM是表级锁,不支持行级锁
  • InnoDB是默认是行级锁,也支持表级锁

InnoDB在不走索引的时候,用的是表级锁,行级锁的开销更大一些,所以MyISAM查询效率要高于InnoDB

2. MyISAM和InnoDB的适用场景

  • MyISAM适用于频繁的执行查询操作;增删改较少;不需要执行事务;频繁的执行全表count语句(SELECT COUNT(*) FROM table)

MyISAM引擎采用的是非聚集索引,页中保存的不是数据,而是对应数据的地址,并且数据和索引分别保存在不同的文件中(.MYD文件和.MYI文件),查询行数时,不需要遍历全表,而是将行数保存为一个变量,查询起来效率较高。

  • InnoDB适用于更多的增删改操作;需要执行事务

InnoDB引擎采用的是聚集索引,而且在B+Tree的叶子节点中保存的始数据。所有数据和索引保存在一个文件中(.form),查询具体的行数需要遍历整个表,而没有将其保存为一个变量。

3. 用代码实现乐观锁

乐观锁大家都很熟悉了,我们用SQL简单实现一下

我们创建一个简单的表,其中只有一行数据,初始对应的版本号为1
在这里插入图片描述

时间 线程1 线程2
Time1 SELECT VERSION FROM positive WHERE id = 1 #发现此时的version为1 SELECT VERSION FROM positive WHERE id = 1 #发现此时的version也为1
Time2 UPDATEpositive SET name = “c” ,version = version + 1 WHERE id = 1 AND version = 1 #修改数据,版本数+1
Time3 UPDATEpositive SET name = “b” ,version = 1 WHERE id = 1 AND version = 0 #此时就会执行失败,版本不匹配

如下是我们最后执行的结果,没有如线程1一样,将name修改为c,这样我们就实现了乐观锁
在这里插入图片描述

4. ACID原则

  1. 原子性:事务中的所有命令,要么全部执行成功,要么执行全部回滚。
  2. 一致性:数据库中所有的数据都会保证完整性,比如一共有200元,在不同线程的存取过程中,总和不会改变
  3. 隔离性:多个线程中的事务不会互相干扰
  4. 持久性:数据一旦修改被提交,就会持久化到数据库中

5. 事务隔离级别产生的问题和解决办法

  1. 脏读,读到了别人未提交的数据

我们先需要对事务的隔离级别进行修改

#查看隔离级别,默认为REPEATABLE-READ(RR)
SELECT @@tx_isolation 

#我们需要将隔离级别修改为READ UNCOMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

我们创建表如下
在这里插入图片描述
执行操作如下

扫描二维码关注公众号,回复: 11217556 查看本文章
时间 线程1 线程2
Time1 开启线程 START TRANSACTION START TRANSACTION
Time2 UPDATE test SET balance = 900 WHERE id = 1 修改1000为900
Time3 此时事务还没有提交,线程2便读取到了修改后的值 SELECT * FROM test WHERE id = 1 #此时值为900,发生脏读
Time4 ROLLBACK 事务回滚
Time5 COMMIT

解决办法,修改隔离级别为read committed(RC)

set session transaction isolation level read committed
  1. 不可重复读

注:此时的隔离级别为read committed不可重复读,是事务1读取了一个数据,事务2也读取了同一个数据,并且对该数据进行了修改、提交,此时事务1再读取这个数据,就会发生两次读取数据不一致的情况,这就是不可重复读。

时间 线程1 线程2
Time1 开启线程 START TRANSACTION START TRANSACTION
Time2 select * from test where id = 2 #查询出余额输出为500;
Time3 update test set balance = balance + 300 where id = 2;commit;#将值修改为800
Time4 select * from test where id = 2 #查询出余额输出为800,两次查询结果不同,发生不可重复读

解决办法,我们需要将隔离级别修改为repeatbale read(RR)

set session transaction isolation level repeatbale read
  1. 幻读

幻读,是针对于插入和删除数据产生的,事务1在对数据进行读取的时候,事务2插入了1行数据并提交,此时事务1会读取到新增的数据,发生幻觉,称为幻读。此时的隔离级别为repeatbale read

时间 线程1 线程2
Time1 开启线程 START TRANSACTION START TRANSACTION
Time2 select count(*) from test where id <=5; #此时行数为3
Time3 insert into account(id,name,balance) values(“4”,“d”,“0”) ;commit;#添加一行
Time4 select count(*) from account where id <=10;#这时行数为4,发生幻读

解决办法,我们需要将隔离级别修改为serializable即可解决

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE

表格总结

隔离级别→ read uncommitted read committed repeatliable serializable
脏读 × × ×
不可重复读 × ×
幻读 ×

在这里插入图片描述

同系列

掌握了这些数据库要点,你也能在面试上游刃有余了,(一)索引

原创文章 56 获赞 19 访问量 6020

猜你喜欢

转载自blog.csdn.net/qq_46225886/article/details/105990118
今日推荐