Java面试准备——数据库

MySQL

说来惭愧,曾经在学校的项目中使用过MySQL,但是并不了解原理,基本是当做Excel来用的。。。之前面试字节跳动面试官问我MySQL索引了解吗?直接告诉不了解。这也加速了我面试挂掉的进度。 今天就来总结一下Java面试时数据库的知识点,一雪前耻。

本文学习自GitHub上的JavaGuide项目,感谢大佬的资源,此处为自我学习与整理,原项目链接 JavaGuide

什么是MySQL?

MySQL是一种关系型数据库。MySQL是Java开发中非常常用的数据库。MySQL是免费开源的,任何人都可以在GPL的许可下下载并且个性化修改。

什么是事务?

事务是逻辑上的一组操作,要么都执行,要么都不执行。
最经典的例子就是转账。A给B转账1000元,要么A扣钱,B收到钱,要么失败谁的钱都不会变化。

事务的四大特性:ACID
A:Atomicity 原子性,事务具有原子性,不允许分割,要么做完要么不做
C:Consistency 一致性,执行事务前后,数据保持一致,多个事务对同一个数据的读取结果是相同的
I:Isolation 隔离性,并发访问数据库时,一个用户的事务不被别的事务所干扰,并发事务之间的数据库时独立的
D:Durability 持久性,一个事务被提交之后,他对数据库的改变是持久的,即使数据库发生故障也不会对其有任何影响

并发事务带来的问题

  1. 脏读:当一个事务使用一个数据,并且修改了这个数据,但此时修改还没有放入数据库中,另一个事务也读取了这个数据,这一个事务可能就读到了脏数据,做出的操作可能是不正确的。
  2. 丢失修改:第一个事务读取了数据,第二个事务也读取了同一个数据,第一个事务进行了修改,第二个事务也进行了修改。这样一来第一个事务的修改就丢失了。
  3. 不可重复读:指在一个事务多次读取同一个数据时,另一个事务对数据进行了修改,导致第一个事务多次读取的数据不一样。
  4. 幻读:在一个事务多次读取同一数据时,另一个事务插入了或者删除了数据的内容,导致第一个事务发现多出来或者减少了一些数据条目。

事务隔离级别

SQL定义了四个隔离级别:

  1. READ-UNCOMMITTED(读取未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读,幻读和不可重复读取
  2. READ-COMMITTED(读取已提交):允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读和不可重复读取还是可能发生
  3. REPEATABLE-READ(可重复读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己修改,可以阻止脏读和不可重复读,但是幻读还是有可能
  4. SERIALIZABLE(可串行化):最高隔离级别,完全服从ACID的隔离级别,所有事务逐个执行,事物之间不会干扰
  5. MySQL默认的隔离级别是REPEATABLE-READ可重复度。InnoDB在REPEATABLE-READ隔离级别下使用了Next-Key Lock锁算法,使其达到了SERILIZABLE级别的并发安全。InnoDB在分布式事务情况下会使用SERIALIZABLE级别的事务隔离。

一些常用命令

查看MySQL提供的所有存储引擎

mysql> show engines;

在这里插入图片描述
查看默认存储引擎

mysql> show variables like '%storage_engine%';

查看表的存储引擎


show table status like "table_name" ;

MySQL当前的默认存储引擎是InnoDB,并且在5.7版本只有InnoDB是事务性存储引擎。只有InnoDB支持事务。

MyISAM和InnoDB的区别

MyISAM是MySQL在5.5之前的默认存储引擎,而且效率极佳。MyISAM提供了大量特性,包括全文索引,压缩,空间函数等,但是MyISAM不支持事务和行级锁,最大的缺陷是崩溃后无法安全恢复。5.5版本之后的InnoDB支持事务。
两者的对比:

  1. 是否支持行级锁:MyISAM只有表级锁,而InnoDB支持行级锁和表级锁,默认情况下支持行级锁。
  2. 是否支持事务和崩溃后安全恢复:MyISAM强调效率,每次查询具有原子性,执行速度比InnoDB快,但是不提供事务支持。 但是InnoDB支持事务,外键等高级数据库功能,具有事务,回滚,和崩溃修复能力的事务安全型表。
  3. 是否支持外键:MyISAM不支持;InnoDB支持。
  4. 是否支持MVCC(Multi-Version Concurrency Control):仅InnoDB支持,应对高并发事务,MVCC比单纯的加锁更加高效。MVCC其实是一种可以用乐观锁也可以用悲观锁实现,采用了修改copy份并且赋予版本号更新,支持roolback的方法。

锁机制与InnoDB锁算法

  1. MyISAM和InnoDB存储引擎的锁:
    MyISAM用表级锁,InnoDB使用行级锁和表级锁,默认行级锁。

  2. 行级锁vs表级锁
    表级锁:MySQL中锁定粒度最大的一种锁,直接锁住整张表,上锁简单,消耗资源少,不会死锁,但是并发度低,出现锁碰撞几率大。
    行级锁:MySQL中粒度最小的一种锁,只针对当前操作的行进行加锁,开销大,但是发生碰撞的概率小,并发度高,加锁慢,会出现死锁。

  3. InnoDB锁算法:
    Record Lock:单个行记录上的锁
    Gap Lock:间隙锁,锁定一个范围,不包括记录本身
    Next-Key Lock:record+gap 锁定一个范围,包括记录本身

    InnoDB对于行的查询使用Record Lock
    Next-Key Lock用于在REPEATABLE-READ隔离级别下解决幻读问题
    当查询索引中含有唯一属性时,将Next-Key Lock降级为Record Lock’
    Gap锁的设计目的是为了组织多个事务把记录插入到同一范围内,从而阻止幻读
    有两种方式关闭Gap锁:将事务隔离级别降低至READ-COMMITTED或者将参数innodb_locks_unsafe_for_binlog设置为1

字符集以及校对规则

  1. 字符集:是一种从二进制编码到某类字符的映射。
  2. 校对规则:某种字符集下的排序规则。
  3. MySQL采用的是类似继承的方式指定字符集的默认值,每个数据库以及每个数据表都有自己的默认值,逐层继承。比如:某个库中所有的表的默认字符集将是该数据库所指定的字符集。

索引

MySQL使用的数据结构主要有BTree索引哈希索引。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候可以使用哈希索引,查询性能最快。其余大部分场景建议使用BTree索引。
MySQL中的BTree索引使用的是B+树,但是对于主要的两种引擎(MyISAM和InnoDB)的实现方式是不同的。

  1. MyISAM:B+树的叶子节点的data域存放数据记录的地址。在索引检索的时候,首先按照B+树搜算算发搜索索引,如果指定的Key存在,取出其data域的值,然后以data域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。
  2. InnoDB:其数据本身就是索引文件,相比MyISAM,索引文件和数据是分离的,其表数据文件本身就是按照B+树组织的一个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的Key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引”。而其余的索引都作为辅助索引,辅助索引的data域存储相应记录的主键的值,而不是地址;这也是和MyISAM不同的地方。在根据主键索引查找时,则需要先取一遍主键的值,再走一遍主索引。因此在设计表的时候不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。

为什么不用二叉树?
在查找过程中,磁盘的IO相对于内存的运算是很慢的。可以理解为查找一个节点需要一次IO,所以我们希望索引树可以尽可能地层数低。二叉树层数过多导致IO次数增加。
为什么不用B树而用B+树?
首先对比B树和B+树,m阶B树每个非叶子节点最多有m个儿子,只能有m-1个关键字,所有节点的关键字用来存储。B+树非叶子节点可以有m个关键字,所有的非叶子节点不作为存储数据的点,所有的叶子节点包含了关键字的信息,叶子节点含有最小的关键字,根节点有最大的关键字,一般B+树有两个指针,一个指向根节点,一个指向关键字最小的叶子节点,B+树的叶子节点们根据关键字的大小自小到大链接。
B树:
在这里插入图片描述
B+树:
在这里插入图片描述
B+树相对比B树的优势:
B+树的中间节点不保存数据,所以磁盘可以容纳更多节点,使得树的形状更加矮胖
B+树必须要找到叶子节点,而B树只要匹配即可,不知道元素位置,B+树查找更加稳定
对于范围查找,B+树只需要遍历叶子链表,而B树还要反复的中序遍历

一条SQL语句在MySQL中是怎么执行的?

  1. MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。

  2. 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。

  3. SQL 等执行过程分为两类,一类对于查询等过程如下:
    权限校验 -> 查询缓存 -> 分析器 -> 优化器 -> 权限校验 -> 执行器 -> 引擎
    对于更新等语句执行流程如下:
    分析器 -> 权限校验 -> 执行器 -> 引擎 -> redo log prepare -> binlog -> redo log commit

一条SQL语句执行的很慢的原因是什么?

这篇很好:
SQL语句执行的慢的原因

发布了11 篇原创文章 · 获赞 0 · 访问量 3044

猜你喜欢

转载自blog.csdn.net/weixin_40407203/article/details/105335308