目录
如何解决这些高频面试题?
大致回答思路如下:
谈谈如何理解索引?
谈谈如何理解事务?
有想法了吗?
1.索引的效果:本质上就是缩小扫描范围,避免全表扫描,可以加快查找效率;
2.索引的代价:索引实际上也是一张表,保存主键和索引字段,指向实体表的记录,因此不仅需要占用一部分空间,还在每次对表的索引字段进行增删的同时,还需要更新一下索引文件,牺牲了一定的开销.
3.背后的数据结构:B+树(N叉搜索树)
条件1:数据量庞大
条件2:该字段经常出现在where的后面,以条件的形式存在。即这个字段总是被扫描。
条件3:该字段很少的DML操作。因为DML之后索引需要重新排序
Ps:建议不要随意添加索引,因为索引也是需要维护的。太多的话反而会降低系统的性能。建议通过主键查询,通过unique约束的字段进行查询,效率较高。
1、表记录太少
2、经常增删改的表
3、where条件里用不到的字段不建立索引主键的创建
给 student 表的 id 字段创建索引,起名为 id_index
create index id_index on student(id);
将 student 表上的 id_index 索引对象删除
drop index id_index on student
这里博主已经整理出十分详细的博客啦,可以来看看~
通俗来讲,就是干一件事,要么全都执行完,要么一个都不执行~
(从特性切入讲给面试官,先从原子性开始):这里就不得不说以下他的一大特性:原子性。什么是原子性呢?都知道的是以前物理书上讲:原子是不可分割的最小单位(当时科技还不发达,其实原子还可以再分为原子核和核外电子,原子核又是中子和质子构成,夸克...哈哈扯多了)后来就把这个术语沿用到计算机领域了,事务就是用来保证原子性的;
举个栗子,例如一个转账服务,张三给王五微信转账500块钱,那么就需要从张三的微信中扣除500元,接下来给王五的微信账户中加上500元,但是万一在这个转账的过程中(执行王五收账的这条代码还没有执行)出现了故障(例如断电),那么给王五转账的那500元就收不到了~
这个时候啊,需要按照原子的方式来进行,要么都执行,要么一个都不不执行(不是说真的 不执行,而是执行到一半出现问题的时候,能够自动回复如初);
事务就能保证,如果执行到一半出问题时,自动进行还原,恢复如初,这叫做——”回滚“,在事务进行的过程中MySQL都会记录每步干了什么,一旦遇到问题,就可以根据记录回滚~;
原子性:事务的根本所在(也是事务存在的意义),能够把多个sql语句打包成一个整体,要么都执行完,要么一个都不执行(如果出错,直接回滚);
一致性:事务执行前后,数据处在“一致”状态;(数据能对的上,合情合理)
持久性:事务进行的改动都是在硬盘里的,不会随着主机的(重启 / 关机)而丢失数据;
隔离性(隔离性最复杂,也是面试管最想听到的(看你能不能讲清楚~)):多个事务并发执行的时候,事务之间可以保持“隔离”,互不干扰;
MySQL的本体就是服务器,执行sql语句,本质也是客户端把sql发送给服务器,让服务器去执行;事务也是将sql语句发给服务器执行,而同一时刻,多个客户端都在给服务器发送事务,让他执行,这便是“并发执行”(简单理解就是同时做很多事情~);
如果这些并发执行的事务是对多种不同的数据库 / 不同的表 操作,那就没事了~
但是如果操作的同一数据库,同一个表,那就可能要“打架”了!
隔离存在的意义,就是让并发执行的事务,尽量避免“打架”(使问题控制在可控范围之内~);
举个栗子,我的妈妈说:“咱们中午在家吃饭吧~”,而我的媳妇却说:“咱们中午出去吃吧~”,在这种冲突之下,该做何选择?说不准吧~
讲个有意思的栗子:你和你妈掉水里了,你救哪个?我:救我妈,然后我也跳河里,一起坠入爱河~
在说个详细点的,想象这样一个场景,我在上班的时候敲代码,然后我的同事跟我要完成同一个任务,但他在一旁暗中观察,他看到我这样写:“class list { public int val; publi...”;然后他没看完就走了,他或许还会想:“原来要这样写,我真是给大聪明!”;是啊,真是个大聪明,顺便提一嘴,在公司工作的时候不要抄袭别人代码!!!后果很严重!!!言归正转,他走了之后,我忽然发现刚刚写的代码有点问题,我就给改了~
这就是属于脏读问题,脏读数据,就是一个零时数据,不代表结果;
脏读:一个事务A在修改数据之前,事务B读取了数据,然后A修改了数据,那么此时B读到的就是“无效的数据”,简称:脏读。
我说,等我整个程序做完了,交给老板后,上传码云,你再看着学习吧;等我提交之后,我突然又有了一些想法,就直接开始在码云上改,而同事真好在看码云,忽然发现,代码变了~
不可重复读:在一个事务A中,多次读取数据发现不一样(读的过程中被修改了);
既然约定,你读的时候我不能改,那么我这样想,你读文件A的时候,我去修改B;(掩耳盗铃,同事刚读完的B文件,我就去修改,别人不看就说明我能修改...);
幻读:可以视为“不可重复读”的特殊情况,两次读虽然关心的数据一样,但结果集变了。
我跟那个同事说,你就不要看我的代码了,等我把任务完成,提交给老板,我在把码云发出来,你可以学习以下~
在提交之前不能读,提交之后才能读;
相当于对写操作,加锁;
分析:加锁前,我写的操作,和同事读的操作是并发的(效率最高),隔离性最低(准确性最低);加锁后,我写的操作时,同事不能读了,只有等我上传码云之后才能读,并发性降低了(效率变低了),隔离性变高(准确性变高了);
在写加锁的基础上,同事跟我说,我读的时候你就不要修改了~
在我写的时候,你不能读,你读的时候我不能写;
你看的时候我不能修改,这就是读加锁;
分析:此时并发性进一步降低(效率降低),隔离性进一步提高(准确度提高)
咱就是说,只要你在读代码,我就关机,什么都不要做,代码一点都不能动!
分析:此时并发性最低(效率最低),隔离性最高(准确度最高);
如果需求对于精确度要求不高,因此就可以让并发性高一点,隔离性低一点,提高效率;(例如:点赞数,浏览量...)
如果需求对于精确度要求高,因此就可以让并发性低一点,隔离性高一点,提高准确度;(例如:有关钱财问题...)
- 1.read uncommitted;
- 允许读未提交的数据,并发程度最高,隔离性最低,可能存在 脏读/不可重复读/幻读 问题;
-
- 2.read committed;
- 只能读提交之后的数据,相当于写加锁,并发性降低,隔离性提高,解决脏读问题,可能存在不可重复读,幻读问题;
-
- 3.repeatable read;(默认)
- 相当于读和写都加锁了,并发性再次降低,隔离性再次提高,解决 脏读/不可重复读,可能存在幻读问题;
-
- 4.serializable;
- 严格执行串行化,并发性最低,隔离性最高,解决 脏读/不可重复读/幻读问题
在一些数据需求精确度要求高的地方,我们就可以使用事务,比如银行转账服务等...
具体的,想象这样一个场景:张三需要从卡上取 100 元钱,那么这个时候就可以使用事务了~(因为一旦出现网络错误,或是数据库挂掉了,就有可能出现卡中的钱扣掉了,但钱没取出来~)
(1)首先在取钱之前开启事务:start transaction;
(2)执行取钱的 SQL 语句;
(3)回滚或提交(若没有意外,则进行提交,否则进行回滚~):rollback/commit;
如下: