赞
踩
1 什么是事务,事务的几大特性是?
事务是保证数据库的一组操作,要么全部成功,要么全部失败。事务在引擎层实现,但是不是所有的数据库引擎都支持事务,比如MySQL原生数据库的引擎就不支持,而目前在用的innodb引擎是支持事务的。
事务有四个特性:acid,原子性,一致性,隔离性,持久性。
原子性:事务的原子性指的是一个事务中的所有操作是不可分割的,必须是同一个逻辑单元,要么全部执行,要么全部不执行
一致性:事务前后数据的完整性保持一致
隔离性:多个事务在同时触发的时候,彼此互不干扰,当事务出现并发操作的时候要相互隔离
持久性:事务一旦提交,对数据库的产生的效果是永久的,其他事务的执行或者故障都不会对本次事务的操作结果有影响
事务的四个性质是怎么实现的?
原子性:原子性依靠undolog回滚日志实现,每次对数据做修改或者删除插入的操作都会生成一条undolog来记录操作之前的数据状态,使用rollback的语句能够将所有执行成功的SQL语句产生的效果撤销。回滚日志先于数据持久化到硬盘上。回滚就是逆向操作。
一致性:依靠其他三个性质实现,一致性指的是数据的完整性,为了保证数据的有意义状态
隔离性:通过锁机制实现,当事务操作数据的时候加锁,让事务执行前后看到的数据时候一致的,并行执行事务和串行执行事务产生的效果一样。本质有两种,悲观锁和乐观锁
持久性:持久性通过redolog重做日志实现,redolog记录的是对数据库的操作。MySQL先把存放在硬盘上的数据加载到内存中,在内存中做修改再刷回磁盘,redolog使得在事务提交的时候将数据刷回磁盘。
当数据库宕机之后,先通过redolog来恢复数据库,然后根据undolog和binlog的记录决定是要回滚还是提交
2 四种事务的隔离级别是,分别有哪些问题?
事务隔离的越严格,效率就越低。
读未提交,读已提交,可重复读和序列化。
读未提交:在这种隔离级别下,别的事务在提交之前对数据进行修改,所有事务能够读到修改后的数据。读取未提交的数据会导致脏读,脏读指的是如果事务A读到事务B修改后的数据,但是事务B执行的回滚操作,那么事务A读到的数据就是脏数据。读未提交的隔离级别几乎不会用到。
读提交:只有别的事务提交之后,本事务才能看到修改后的数据,提交之前只能看到未修改的数据。这是大多数数据库默认的隔离级别,但是不是MySQL的默认隔离级别。导致不可重复读:在当前事务中只能看见已经提交事务的执行结果,当同一事务在读取期间出现新的commit操作,读到不一样的数据
可重复读:可重复读是MySQL的默认隔离级别。 对于同一个字段事务在执行过程中读到数据,除非自己修改。保证当前事务不会读取到其他事务的update操作,因此会导致幻读。
幻读指的是,由于时间差(同一个事务中相同的两个查询语句会返回不一样的结果)
序列化:串行化,对于同一行记录,读会加读锁,写会加写锁,出现读写冲突的时候,后访问的事务必须等前一个事务执行完成才能继续执行。
通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
3 MySQL的锁有哪些,怎样理解MySQL的间隙锁,行锁,表锁
数据库的DDL变更,包括创建表、添加字段、添加索引、修改字段属性等。
数据库锁设计的目标就是处理并发问题,数据库作为一个多用户访问的资源,当出现并发情况的时候,数据库需要合理控制各个资源的访问规则,而锁就是用来实现这些访问规则的重要数据结构。
基于锁的粒度分类,有表锁、行锁、记录锁、间隙锁、临键锁
还有全局锁,页锁等
全局锁:全局锁就是对整个数据库实例加锁,MySQL提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。
全局锁的应用:对全库做逻辑备份,备份过程中主从库都是处于只读的状态。如果只在主库上备份,那么更新期间不能有操作,业务会停摆,而只在从库上备份,备份期间从库不能执行主库同步过来的binlog,导致主从延迟。
表级锁:有两种,一种是表锁,另一种是元数据锁mdl
表级锁特点:开销小,加锁快;不会出现死锁;粒度大,容易出现锁冲突;数据库引擎总是一次性获取所有的锁,并且按照同样的顺序获取表锁,避免死锁
元数据锁:防止并发执行ddl、mdl阻塞:用于隔离dml(数据操纵语言,对表数据进行修改)和ddl(数据定义语言,对表结构进行修改)语句,每执行一条dml或者是ddl语句的时候都会申请mdl锁,DML操作需要MDL读锁,DDL操作需要MDL写锁(MDL加锁过程是系统自动控制,无法直接干预,读读共享,读写互斥,写写互斥)
表锁有两种:表的读锁和表的写锁
语句:
表锁是MySQL中最基本的锁策略,不依赖存储引擎,开销小,粒度大,最大的负面问题是锁竞争概率高,并发性差
行锁
Innodb支持行锁,这是代替原生的myisam引擎的重要原因
行锁分为共享锁(s锁)和排他锁(x锁)
共享锁又称为读锁,多个事务对于同一个数据能共享一把锁,都能访问到最新的数据
多个事务的查询可以共享一把锁,单个事务拿到共享锁之后,该事务可以进行修改,但是多个事务拿到共享锁,所有事务都不能修改,会导致死锁
排他锁(写锁),对某一样的数据排他锁只能有一个事务拿到,其余事务不能再获取该数据行的锁,基于该数据行的操作会被阻塞,直到锁释放。
共享/排它锁的使用场景
共享锁:确保某个事务查到最新的数据;这个事务不需要对数据进行修改、删除等操作;也不允许其它事务对数据进行修改、删除等操作;其它事务也能确保查到最新的数据。
排它锁:确保某个事务查到最新的数据;并且只有该事务能对数据进行修改、删除等操作。
4 当前读和快照读是什么意思
一般的select语句,不加锁称之为快照读:select * from test;
通过加s锁或者x锁的查询语句、插入、更新、删除操作,就是当前读:
为什么会出现锁等待:
没有索引的情况下,如果where语句不能通过索引进行快速过滤,SQL会对全表扫描,MySQL的server层会对所有的记录进行加X锁,然后调用innodb引擎查询
5 描述SQL语句执行的过程,涉及到wal机制,包括buffer pool三种日志
第一步 建立连接。使用连接器和客户端建立连接之后,通过验证用户名和密码,连接器到权限表查询能够获取的权限,之后进行的所有操作的权限都是依赖刚刚建立的这个权限。同时在建立连接之后,要管理和维护这个连接。
第二步 查询缓存。如果查询到之前执行过同样的语句会直接返回缓存中得到的结果。
大多数时候不建议使用缓存,因为只要一个表更新,这个表上的所有缓存数据就会被清空了。对于那些经常更新的表来说,缓存命中率很低。MYSQL8版本直接将查询缓存的整块功能删掉了。
第三步 词法分析。分析器会做词法分析,分析该条SQL语句中什么字符串代表的含义,然后做语法分析。
第四步 优化器。优化器会对SQL的执行顺序,根据使用的索引进行优化。
第五步 执行器。执行器先对权限进行校验,通过之后打开对应的表进行执行,根据不同表的引擎定义,调用这个引擎提供的接口。
update语句除了会执行上面的五步,还会涉及两个重要的日志模块。
两个重要的日志模块
redo log (重做日志):redo log 是innodb所特有的,当有一条更新语句时,innoDB引擎会先把记录写到redo log中,然后更新内存,这时候更新就算完成了。innoDB会在合适的时候将这个记录更新到磁盘中去。
特点:redo log 是固定大小的,属于循环写。redo log是物理日志,记录的是“在某个数据页上做了什么修改”。有了redo log ,InnoDB可以保证数据库发生异常重启的时候,之前提交的记录不会丢失,这个能力为crash-safe。
binlog(归档日志):binlog属于server层的日志,是逻辑日志,记录的是这个语句的原始逻辑,比如给“id =1 的一行的某个字段+2”。binlog是追加写入的,binlog写到一定的大小后切换到下一个,不会覆盖之前的。
更新语句的内部流程
update t set n = n+2 where id =1
两段式提交:redo log的写入分为两部分,是为了保证这两份日志的逻辑一致。
相关配置:redo log 用于保证 crash-safe 能力。innodb_flush_log_at_trx_commit 这个参数设置成 1,表示每次事务的 redo log 都直接持久化到磁盘。sync_binlog 这个参数设置成 1 的时候,表示每次事务的 binlog 都持久化到磁盘。
WAL,全称是Write-Ahead Logging, 预写日志系统。指的是 MySQL 的写操作并不是立刻更新到磁盘上,而是先记录在日志上,然后在合适的时间再更新到磁盘上。这样的好处是错开高峰期。日志主要分为 undo log、redo log、binlog。这三种在之前的博客已经详细说过了,作用分别是 " 完成MVCC从而实现 MySQL 的隔离级别 “、” 降低随机写的性能消耗(转成顺序写),同时防止写操作因为宕机而丢失 “、” 写操作的备份,保证主从一致 "。
什么是缓冲池?
在操作系统中,CPU与磁盘的执行速度不是一个量级的,因此CPU在磁盘中间,有一个高速缓存区,意思是,CPU将需要操作的数据存储在告诉缓存区中,并不直接操作磁盘。而操作系统另起一个线程去定期的将数据更新到磁盘中。
同样,缓冲池也是这个道理,你可以简单把缓冲池理解为缓存。
数据存储在内存中,加速数据访问,加速数据更新,避免每次查询数据都进行磁盘IO,这就是缓冲池的作用
缓冲池缓存什么数据?
缓存表数据和索引数据,将磁盘上最热最近的数据存储到缓冲池上,避免每次查询都到磁盘查询。
缓冲池的缺点
容量小,由innodb_buffer_pool_size决定,默认是128M。可以根据需求设置。
缓冲池污染当某一个SQL语句,要批量扫描大量数据时,可能导致把缓冲池的所有页都替换出去,导致大量热数据被换出,MySQL性能急剧下降,这种情况叫缓冲池污染
6 mvcc了解过吗,简单说它的原理
Mvcc是多版本并发控制,由undolog辅助实现,是innodb实现事务并发与回滚的重要功能,维持一个数据的多个版本,在不添加锁的情况下让读写操作没有冲突,通过添加三个隐式字段、undolog和read view实现
DBTRXID 6字节,最近修改事务id,记录创建这条记录或者最后一次修改该记录的事务id
DBROLLPTR 7字节,回滚指针,指向这条记录的上一个版本,用于配合undolog,指向上一个旧版本
DBROWJD 6字节,数据库默认该行的主键。如果数据表没有主键,那么innodb会自动生成一个6字节的row_id
Read View是事务进行快照读操作的时候生产的读视图,在该事务执行快照读的那一刻,会生成一个数据系统当前的快照,记录并维护系统当前活跃事务的id,事务的id值是递增的。
7 索引是什么,数据结构有哪些
8 什么是聚簇索引,什么是普通索引
聚簇索引是将索引和数据放在一起(叶子节点存储的是行记录),找到索引就找到了数据,普通索引把数据和索引分开存储,索引里放的是和数据关联的主键,还需要根据主键二次查找才能找到数据。
实现:如果一个主键被定义了,那么这个主键就是作为聚集索引
如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引
如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引ROWID,这个隐藏的主键是一个6个字节的列,改列的值会随着数据的插入自增。
9 什么是回表,什么是索引覆盖
回表指的是,普通索引无法直接定位行记录,因此需要查询两次索引树,第一遍通过普通索引定位到主键id,然后第二遍再通过集聚索引定位到具体行记录,性能相对于只扫描一遍的集聚索引树性能要低一些
索引覆盖指的是,当前所查询的数据正好是索引,是一种避免回表查询的优化策略。具体的做法是将要查询的数据作为索引建立普通索引(可以是单列索引,也可以是一个索引语句定义所有要查询的列,即联合索引),这样的话就可以直接返回索引中的数据,不需要再通过集聚索引去定位行记录,避免了回表的情况发生。
10 索引失效的场景有哪些
11 谈谈你对锁机制的理解
12 java里面有哪些锁
13 乐观锁,悲观锁,可重入锁,公平锁,非公平锁代表什么意思,能举几个例子吗
14 怎么理解syncronized, reentrantlock。讲一下各自的原理
15 关于分布式框架和分布式组件
分布式:
注册中心(Eureka Consul):让本服务模块能够被其他服务看见并调用,方便动态扩容
负载均衡(Ribbon):将用户访问请求,通 过某种算法,分发到集群中的节点
熔断措施(Hystrix):先降级再防止雪崩 防止一个服务挂了全体雪崩(断路器拒绝调用,直接返回失败)
限流措施:防止你的服务被错误地疯狂调用
消息总线(bus):使用轻量级的消息代理来构建一个共有的消息主题,这个主题生产的消息会被所有的实例监听和消费 rabbitmq kafka
调用重试机制:网络之间的调用不可靠
分布式链路追踪服务(springcloud Sleuth):调用链路长,网络开销大,出错难以定位,需要分布式链路追踪服务定位问题 logstash:集中跟踪消息 Zipkin:时间消耗监控 消息中间件:异步搜集
Elk:方便日志的查看和分析问题
配置中心(config):每个服务进行配置
降级策略:特殊时候,比如大促,让出硬件资源
声明式服务调用(feign):Spring Cloud的声明式调用,可以做到使用 HTTP请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更不知这是一个Http请求,无需关注与远程交互的细节,更无需关注分布式环境开发
网关(zuul gateway):对外暴露统一接口 zuul是Netflix孵化的一个致力于网关解决方案的开源组件
容器:docker kubernetes
分布式可以认为是通过网络连接多个组件而形成的系统。
广义上说前后分离的应用就能算分布式,前端的 js 代码在浏览器跑着,后端的代码在服务器跑着,两种不同的组件合力对外提供服务构成分布式。
而我们常提到的分布式是狭义上的,指代不同的组件通过协作构成的系统。
而集群常指的同一个组件多实例而构成逻辑上的整体。
这两个概念不冲突,分布式系统里面可以包含集群,像我们的商品服务就可以是集群部署。
16 dubbo和springcloud框架:
Dubbo:是分布式服务框架rpc(Remote Procedure Call Protocol
)的一种,两台服务器A、B,分别部署不同的应用a,b。当A服务器想要调用B服务器上应用b提供的函数或方法的时候,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义传达调用的数据。
说白了,就是你在你的机器上写了一个程序,我这边是无法直接调用的,这个时候就出现了一个远程服务调用的概念。
为什么使用Dubbo
因为是阿里开源项目,国内很多互联网公司都在用,已经经过很多线上考验。内部使用了Netty、Zookeeper,保证了高性能高可用性。
使用Dubbo可以将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,可用于提高业务复用灵活扩展,使前端应用能更快速的响应多变的市场需求。
分布式架构可以承受更大规模的并发流量。
Dubbo 和 Spring Cloud区别
1、通信方式不同:Dubbo 使用的是 RPC 通信,而Spring Cloud 使用的是HTTP RESTFul方式。
2、组成不一样:
dubbo的服务注册中心为Zookeeper,服务监控中心为dubbo-monitor,无消息总线、服务跟踪、批量任务等组件;
Spring Cloud的服务注册中心为spring-cloud netflix enruka,服务监控中心为spring-boot admin,有消息总线、数据流、服务跟踪、批量任务等组件;
17 用户点击URL之后请求是怎么样传递到我们编写的service层方法的
web
容器如
tomcat
接收到请求后会把请求列、请求头、请求体封装成
HttpServletRequest
传给
servlet
实例
Request能够通过不同的get方法获取请求头请求行请求体:
具体项目代码: request.getParameterMap()
18 分布式事务
分布式事务顾名思义就是要在分布式系统中实现事务,它其实是由多个本地事务组合而成。对于分布式事务而言几乎满足不了 ACID,其实对于单机事务而言大部分情况下也没有满足 ACID,不然怎么会有四种隔离级别呢?所以更别说分布在不同数据库或者不同应用上的分布式事务了。
常见的分布式事务包括 2PC、3PC、TCC、本地消息表、消息事务、最大努力通知
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。