1、订单、库存两个表 如何保证数据的一致性?
在一个电子商务系统中,正常的应该是订单生成成功后,相应的库存进行减少必须要保证两者的一致性,但有时候因 为某些原因,比如程序逻辑问题,并发等问题,导致下单成功而库存没有减少的情况。这种情况我们是不允许发生 的,MySQL的中的事务刚好可以解决这一问题,首先得选择数据库的存储引擎为InnoDB的,事务规定了只有下订单 完成了,并且相应的库存减少了才允许提交事务,否则就事务回滚,确保数据一致性。
2、外键的作用
保持数据一致性,完整性,主要目的是控制存储在外键表中的数据。
3、什么是读锁,什么是写锁?
读锁:也叫共享锁、S锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S 锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
写锁:又称排他锁、X锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加 任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
4、数据库中,什么是锁?
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
MyISAM和InnoDB存储引擎使用的锁:
1)MyISAM采用表级锁(table-level locking)。
2)InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
表级锁和行级锁对比:
1)表级锁: Mysql中锁定粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。
2)行级锁: Mysql中锁定粒度最小 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。
InnoDB存储引擎的锁的算法有三种:
1)Record lock:单个行记录上的锁
2)Gap lock:间隙锁,锁定一个范围,不包括记录本身
3)Next-key lock:record+gap 锁定一个范围,包含记录本身
5、mysql事务隔离级别,说下你对事务的隔离性的理解?
为了达到上述事务特性,数据库定义了几种不同的事务隔离级别:
1)READ_UNCOMMITTED(未提交读): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、 幻读或不可重复读
2)READ_COMMITTED(已提交读): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
3)REPEATABLE_READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
4)SERIALIZABLE(串行): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
这里需要注意的是:Mysql 默认采用的 REPEATABLE_READ隔离级别,Oracle 默认采用的 READ_COMMITTED
隔离级别。
事务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是MVVC(多版本并发控制),通过保存修改
的旧版本信息来支持并发一致性读和回滚等特性。
6、什么是事务?及其特性?
是一系列的数据库操作,是数据库应用的基本逻辑单位。
事务特性:(ACID)
1)原子性(Atomicity):即不可分割性,事务要么全部被执行,要么就全部不被执行。
2)一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
3)隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
4)持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
7、请问 varchar 和 char有什么区别?
char是固定长度的字符类型,分配多少空间,就占用多长空间。Varchar是可变长度的字符类型,内容有多大就占用多大的空间,能有效节省空间。由于varchar类型是可变的,所以在数据长度改变的时,服务器要进行额外的操作, 所以效率比char类型低。
8、Mysql的存储引擎,myisam和innodb的区别:
1)InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在 begin和commit之间,组成一个事务;
2)InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
3)InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
4)InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
5)Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;
9、组合索引 (a,b,c),支持哪些基于索引的查找
最左原则
对于联合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。
例如索引是key index (a,b,c). 可以支持a 、 a,b 、ac、 a,b,c 4种组合进行查找,但不支持 b,c进行查找。当最左侧字段是常量引用时,索引就十分有效。
10、什么情况下应不建或少建索引
1)表记录太少
2)经常插入、删除、修改的表
3)数据重复且分布平均的表字段,假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。
4)经常和主字段一块查询但主字段索引值比较多的表字段
11、什么是表分区和分表?
表分区:是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。从逻辑上看,只有一张表, 但是底层却是由多个物理分区组成。
分表:指的是通过一定规则,将一张表分解成多张不同的表。比如将用户订单记录根据时间成多个表。
分表与分区的区别在于:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。
12、MySQL支持的分区类型有哪些?
1)RANGE分区: 这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区
2)LIST分区: 这种模式允许系统通过预定义的列表的值来对数据进行分割。按照List中的值分区,与RANGE的区别是,range分区的区间范围值是连续的。
3)HASH分区 :这种模式允许通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。例如可以建立一个对表主键进行分区的表。
4)KEY分区 :上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。
13、关于MVCC的了解
MySQL InnoDB存储引擎,实现的是基于多版本的并发控制协议——MVCC (Multi-Version Concurrency Control)
注:与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control
MVCC最大的好处:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能,现阶段几乎所有的RDBMS,都支持了MVCC。
1)LBCC:Lock-Based Concurrency Control,基于锁的并发控制
2)MVCC:Multi-Version Concurrency Control 基于多版本的并发控制协议。纯粹基于锁的并发机制并发量低,MVCC是在基于锁的并发控制上的改进,主要是 在读操作上提高了并发量。
14、MySQL优化
1)业务优化,数据库设计
2)数据库索引优化
3)分表分库(水平分割,垂直分割)
4)读写分离
5)存储过程(模块化编程,可以提高速度)
6)对MySQL配置优化(配置最大并发数my.ini,调整缓存大小)
7)SQL调优(使用Explain进行分析)
8)选择正确的存储引擎
9)定时清除不需要的数据,定时进行碎片整理
10)热点数据采用Nosql等替代品
11)模糊查询采用es等替代品
12)mysql配置优化
13)服务器优化(操作系统和硬件)
15、大表优化,以及谈谈你对mysql分库分表的见解
当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:
1)限定数据的范围:务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内;
2)读/写分离:经典的数据库拆分方案,主库负责写,从库负责读;
3)缓存:使用MySQL的缓存,另外对重量级、更新少的数据可以考虑使用应用级别的缓存;
4)垂直分区:根据数据库里面数据表的相关性进行拆分。例如,用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。 简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表;
a. 垂直拆分的优点: 可以使得行数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。
b. 垂直拆分的缺点: 主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此 外,垂直分区会让事务变得更加复杂;
5)水平分区:保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量。 水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。
水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,其实对于提升MySQL 并发能力没有什么意义,所以水平拆分最好分库 。 水平拆分能够 支持非常大的数据量存储,应用端改造也少,但分片事务难以解决 ,跨界点Join 性能较差,逻辑复杂
16、innodb索引用的数据结构是?
用的是树(B+树)【二分查找,二叉树查找,平衡二叉树,多路平衡查找树】
17 【索引失效】在哪些情况下会发生针对该列创建了索引但是在查询的时候并没有使用呢?
1)没有遵循索引最左原则。 建立几个复合索引字段,最好就用上几个字段。
2)最佳左前缀法则,如果索引了多列,要遵守最左前缀法则,指的是查询从索引的最左前列开始,可以跳过但是尽量不跳过索引中间的列。
3)不再索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
4)存储引擎不能使用索引中范围条件右边的列。(范围之后全失效) 若中间索引列用到了范围(>、<、like等),则后面的索引全失效
5)Mysql在使用不等于(!=、<>)或like的左模糊的时候无法试用索引会导致全表扫描
6)IS NULL和IS NOT NULL也无法使用索引
7)字符串不加单引号索引失效,因为这里有一个隐式的类型转换操作,更严重会导致行锁变表锁,降低SQL效率
18、mysql的水平拆分和垂直拆分
1,水平分割: 例:QQ的登录表。假设QQ的用户有100亿,如果只有一张表,每个用户登录的时候数据库都要从这100亿中查找, 会很慢很慢。如果将这一张表分成100份,每张表有1亿条,就小了很多,比如qq0,qq1,qq1...qq99表。 用户登录的时候,可以将用户的id%100,那么会得到0-99的数,查询表的时候,将表名qq跟取模的数连接起来,就 构建了表名。比如123456789用户,取模的89,那么就到qq89表查询,查询的时间将会大大缩短。 这就是水平分割。
2,垂直分割: 垂直分割指的是:表的记录并不多,但是字段却很长,表占用空间很大,检索表的时候需要执行大量的IO,严重降低 了性能。这时需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。 例如学生答题表tt:有如下字段: Id name 分数 题目 回答 其中题目和回答是比较大的字段,id name 分数比较小。 如果我们只想查询id为8的学生的分数:select 分数 from tt where id = 8;虽然知识查询分数,但是题目和回答这两个 大字段也是要被扫描的,很消耗性能。但是我们只关心分数,并不想查询题目和回答。这就可以使用垂直分割。我们可以把题目单独放到一张表中,通过id与tt表建立一对一的关系,同样将回答单独放到一张表中。这样我们插叙tt中的分数的时候就不会扫描题目和回答了。
19、你用什么软件实现数据库高可用?
1. MHA(Master High Availability):是由日本人yoshinorim开发的一款成熟且开源的MySQL高可用程序,它实现了MySQL主从环境下MASTER宕机后能够自动进行单次故障转移的功能,其本身由perl语言编写,使用MHA能够让我们更大程度的解放双手,用更少的指令完成更多的事,MHA主要能够做以下几件事:
1)自动的在MASTER宕机后0~30秒选举新的SLAVE作为MASTER,保证服务不被中断
2)自动的在MASTER宕机后将所有未被选举为新MASTER的SLAVE重新指向新的MASTER并启动复制
3)自动的在MASTER宕机后向数据库管理人员发送报警邮件
4)自动的进行VIP漂移服务,确保服务运行不会暂停
5)MHA搭建条件最少是1主2从,且必须是独立的服务器,不能单机多实例进行搭建。
优点:
1)MHA除了支持日志点的复制还支持GTID的方式
2)同MMM相比,MHA会尝试从旧的Master中回复旧的二进制日志,只是未必每次都能成功。如果希望更少的数据丢失场景,建议使用MHA架构
缺点:
1)MHA需要自行开发VIP转移脚本
2)MHA只监控Master的状态,未监控Slave的状态
2. MMM:是支持双主故障切换和双主日常管理的脚本程序,虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热
优点:
1)提供了读写VIP的配置,使读写请求都可以达到高可用
2)工具包相对比较完善,不需要额外的开发脚本
3)完成故障转移之后可以对Mysql集群进行高可用监控
缺点:
1)故障简单粗暴,容易丢失事务,建议采用半同步复制方式,减少失败的概率
2)目前MMM社区已经缺少维护,不支持基于GTID的复制
20、mysql执行一条sql语句的完整过程,sql语句在mysql中的执行过程
MySQL 主要分为 Server 层和引擎层:
1)Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有 一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有;
2)引擎层是插件式的, 目前主要包括,MyISAM,InnoDB,Memory 等。
SQL 等执行过程分为两类
1)一类对于查询等过程如下:权限校验 ----> 查询缓存 ----> 分析器 ----> 优化器 ----> 权限校验 ----> 执行器 ----> 引擎
2)对于更新等语句执行流程如下:分析器 ----> 权限校验 ----> 执行器 ----> 引擎 ----> redo log prepare ----> binlog ----> redo log commit
21、说说mysql主从同步怎么做的?
首先先了解mysql主从同步的原理:
1)master提交完事务后,写入binlog
2)slave连接到master,获取binlog
3)master创建dump线程,推送binglog到slave
4)slave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中
5)slave再开启一个sql线程读取relay log事件并在slave执行,完成同步
6)slave记录自己的binglog
由于mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。
1)全同步复制:主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。
2)半同步复制:和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。
22、知道什么是间隙锁吗?
间隙锁是可重复读级别下才会有的锁,间隙锁可以解决幻读的问题。我们还是以user举例,假设现在user表有几条记录
23、什么是覆盖索引和回表?
MySQL innodb的主键索引是簇集索引,也就是索引的叶子节点存的是整个单条记录的所有字段值,不是主键索引的就是非簇集索引,非簇集索引的叶子节点存的是主键字段的值。
回表是什么意思?就是你执行一条sql语句,需要从两个b+索引中去取数据。举个例子:
表tbl有a,b,c三个字段,其中a是主键,b上建了索引,然后编写sql语句
SELECT * FROM tbl WHERE a=1
这样不会产生回表,因为所有的数据在a的索引树中均能找到
SELECT * FROM tbl WHERE b=1
这样就会产生回表,因为where条件是b字段,那么会去b的索引树里查找数据,但b的索引里面只有a,b两个字段的
值,没有c,那么这个查询为了取到c字段,就要取出主键a的值,然后去a的索引树去找c字段的数据。查了两个索引
树,这就叫回表。
索引覆盖就是查这个索引能查到你所需要的所有数据,不需要去另外的数据结构去查。其实就是不用回表。\
怎么避免?不是必须的字段就不要出现在SELECT里面。或者b,c建联合索引。但具体情况要具体分析,索引字段多 了,存储和插入数据时的消耗会更大。这是个平衡问题。
24、对于关系型数据库而言,索引是相当重要的概念,请回答有关索引的几个问题:
1)索引的目的是什么? 快速访问数据表中的特定信息,提高检索速度创建唯一性索引,保证数据库表中每一行数据的唯一性。 加速表和表之间的连接,使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间
2)索引对数据库系统的负面影响是:创建索引和维护索引需要耗费时间,这个时间随着数据量的增加而增加;索引需要占用物理空间,不光是表需要占用数据空间,每个索引也需要占用物理空间;当对表进行增、 删、改、的时候索引也要动态维护,这样就降低了数据的维护速度。
3)为数据表建立索引的原则有哪些? 在最频繁使用的、用以缩小查询范围的字段上建立索引。
在频繁使用的、需要排序的字段上建立索引
4)什么情况下不宜建立索引:对于查询中很少涉及的列或者重复值比较多的列,不宜建立索引。
对于一些特殊的数据类型,不宜建立索引,比如文本字段(text)等
25、什么是存储过程?用什么来调用?
存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。可以用一个命令对象来调用存储过程。
26、主键、外键和索引的区别?
1)定义:
a、主键:唯一标识一条记录,不能有重复的,不允许为空
b、外键:表的外键是另一表的主键,外键可以有重复的,可以是空值
c、索引:该字段没有重复值,但可以有一个空值
2)作用:
a、主键:用来保证数据完整性
b、外键:用来和其他表建立联系用的
c、索引:是提高查询排序的速度
3)个数:
a、主键:主键只能有一个
b、外键:一个表可以有多个外键
c、索引:一个表可以有多个唯一索引
27、谈谈对mysql视图的理解,什么是基本表?什么是视图?
1)基本表是本身独立存在的表,在 SQL 中一个关系就对应一个表。
2)视图是从一个或几个基本表导出的表。视图本身不独立存储在数据库中,是一个虚表
视图的优点:
a、视图能够简化用户的操作
b、视图使用户能以多种角度看待同一数据
c、视图为数据库提供了一定程度的逻辑独立性
d、视图能够对机密数据提供安全保护
28、聚簇索引:
1)聚簇索引与非聚簇索引区别:叶节点是否存放一整行记录
2) 聚簇索引:(主键索引)
a. 特点:表数据和主键一起存储,放在叶子节点上,where条件使用到主键索引时,不需要回表
b. 缺点:
1. 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将出现页分裂,严重影响性能,所以innoDB索引引擎的表主键一般是数字自增;
2. 更新主键的代价很高,因为将会导致被更新的行移动
3)非聚簇索引:普通索引,唯一索引,组合索引,也称二级索引
a. 特点:表数据和索引是分成两部分存储的,where条件只使用了这类索引,但是select字段不在索引范围内,就需要回表查询了
29、术语:
1)DDL:数据定义语言,创建数据库中的各种对象:表、视图、索引、同义词、聚簇等;
2)DML:数据操纵语言,数据增删改查,INSERT、DELETE、UPDATE、SELECT
3)DQL:数据查询语言,是由SELETE子句、FROM子句、WHERE子句组成的查询块
4)DCL:数据控制语言,用来授予或者回收访问数据的某种特权,并控制数据库操作事务发生的时间以及效果,对数据库实行监控等
30、高性能索引策略:
1)保持列的干净:不要在列中使用表达式或函数,这样是无法命中索引的
2)索引字段要尽量小:IO次数取决于B+树的高度h,数据项占的空间越小,树的高度越低,IO次数就越低
3)前缀索引与列数据的区分度:索引越大,树就越高,合理设置前缀索引的长度,就能降低树的高度
4)索引列不参与计算
5)选择区分度高的列作为索引
6)尽可能去扩展索引,而不是新建索引
h = log(m+1)N,当数据量N一定的情况下,m越大,h越小;而m = 磁盘块的大小 / 数据项的大小,如果数据项占的空间小,数据项的数量越多,树的高度越低
31、死锁
1. 定义:死锁是指不同的事务无法继续进行的情况,因为每个事务都持有一个对方需要的锁,都在等待资源的可用,所有都没有释放它持有的锁;
2. 如果减少死锁:
1)避免大事务,尽量将大事务拆成多个小事务来处理,因为大事务占用资源多,耗时长,与其他事务冲突的概率也会变高
2)当不同的事务更新多个表或者大范围时,在每个事务使用相同的操作顺序
3)默认事务的隔离级别是RP,如果可接受幻读和不可重复读对应用的影响,可以改为RC,避免间隙锁导致的死锁
4)为表合理添加索引,如果不投索引将会加表锁,死锁的概率就会大大增加
5)避免在同一个时间点运行对同一个表进行读写的脚本
6)设置锁等待超时参数:innodb_lock_wait_timeout