美文网首页
Java面试——数据库

Java面试——数据库

作者: 抬头挺胸才算活着 | 来源:发表于2020-04-04 20:31 被阅读0次

    参考资料:
    [1]. MySQL 是怎样运行的:从根儿上理解 MySQL
    [2]. Mysql并发时经典常见的死锁原因及解决方法
    [3]. 数据库连接池-常用参数配置及含义

    binlog机制描述,binlog日志格式有哪些

    MySQL主从架构(读写分离),主从数据复制过程,数据复制过程丢失如何处理

    在数据库层面怎么保证对某个库存数据的加减安全?

    数据库分布式锁

    1. 悲观锁
      for update 直接加锁
    2. 乐观锁
      增加version字段,每次更新加一次version,更新的时候where带上上一次的version

    嵌套子查询如何优化

    建立子查询,转化为内连接

    Innodb如何解决幻读

    MVCC:每条记录记录修改的版本,里面含有事务的id,事务一开始的时候保存ReadView,包含当时活跃的事务id,提交的事务id等,然后查询的时候找到那些已经提交的事务id提交的记录。

    如果线上出现慢sql,如何定位和解决,有实际动手优化过慢sql吗。

    慢查询日志,explain

    索引有哪些种类

    聚簇索引,二级索引,联合索引。

    建立索引的原则

    根据用途进行建立,建立尽量少的索引

    聚簇索引和非聚簇索引实现区别

    非聚簇索引只包含索引列和主id,查询的时候需要回表

    mysql写入数据的时候,是先把数据写到缓冲区,然后再flush到磁盘的,如何在flush过程中发生了宕机,数据如何恢复。

    读取log日志,然后将log日志写入到buffer,再刷新到磁盘

    mysql的底层数据结构、B+树和B树区别

    B+树是应数据库所需而出现的一种B树的变形树
    对比:

    1. B+树关键字和子树的对应关系为:n:n;B树关键字和子树的对应关系为:n-1:n
    2. B+树的关键字是对应的子树的最大元素,该元素在节点中也有包含;B树的关键字是大于对应的子树的所有元素的,该元素在节点中没有包含。
    3. B+树种关键字起到索引的作用而已,B树包含的是对应的记录。

    连接池的参数都什么意思

    maxActive :最大连接数
    initialSize:初始化连接数目
    maxWait:等待时间

    数据库的三范式

    数据库单一尽量要精简和联系比较简单,越拆越明那种。

    第一范式:列不可分,eg:【联系人】(姓名,性别,电话),一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF;
    第二范式:有主键,保证完全依赖。eg:订单明细表【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName),Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID,不符合2NF;
    第三范式:无传递依赖(非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况),eg:订单表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID),CustomerName,CustomerAddr,CustomerCity 直接依赖的是 CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。

    解决幻读

    分2种,快照读和当前读
    (1)快照读(mvcc) 普通的 select 就是快照读。将历史数据存一份快照,所以其他事务增加与删除数据,对于当前事务来说是不可见的。事务每次取数据的时候都会取创建版本<当前事务的数据,以及删除版本号码>当前版本的数据。
    (2)当前读 执行数据库的增删改操作的时, 就是当前读
    采用next-key锁的方式解决问题
    next-key 锁包含两部分: 记录锁(行锁)+ 间隙锁 就是在索引和索引之间上面加锁

    • char和varchar的区别
    1. 占用空间
      char占用的空间开始的时候是固定的,char(n)最少占用n个字节,当然如果存储字符够多,编码起来也多的话,会增加字节,并不是不变的,varchar占用的空间是不固定的,实际存储的字符串长度+1或者+2,用来表示字符串的长度。char(n)和varchar(n)中的n指的是字符。UTF-8:一个汉字=3个字节。GBK:一个汉字=2个字节
    2. 最大长度
      char:255字节
      varchar:65535字节
    3. 截断空格
      char会截断空格,char类型如果小于实际定义的字符个数,会用空格进行填充。(参考[1]第5节InnoDB记录结构)
    4. 存储方式
      char的存储方式是:英文字符占1个字节,汉字占用2个字节;varchar的存储方式是:英文和汉字都占用2个字节,两者的存储数据都非unicode的字符数据。
    • 索引字符串的前缀



      创建索引的时候,我们可能会在列上限定长度,如果列过于长,在建索引的时候会出现两个问题:
      1、索引的占用空间太大
      2、建立索引的时候花费时间过多,对短的字符串排序比较快。
      缺点可能会是同一个前缀可能有多个对应的字段值,需要进一步进行排查,还看会使得


    • 创建索引和不创建索引的情况



    • 建议在真实工作中最好不要使用*作为查询列表,最好把真实用到的列作为查询列表
      比如index就比all快,前者是扫描索引,后者是扫描全表。

    • 死锁(参考2
      因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.
      此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等竺的进程称为死锁进程。
      解决办法:让不同的事务加锁有次序。
      例子1:
      依次选择多条记录,如果不按照顺序来的话,很容易就产生死锁,最好还是用in来解决,在in里面的列表值mysql是会自动从小到大排序,加锁也是一条条从小到大加的锁。下面的语句中是用5,8,10的顺序进行锁定的,如果8已经被锁定,那么会先锁定5,然后在8这里等待。

    Select * from xxx where id in (10,8,5) for update
    

    例子2:
    在插入之前会先检查是否存在,会加gap锁,然后插入,select...for update和insert两个语句,两个session分别执行完第一句,加了两个gap锁进去,然后接下来的insert都无法执行了。

    insert into t3(xx,xx) on duplicate key update `xx`='XX';
    

    因为insert语句对于主键来说,插入的行不管有没有存在,都会只有行锁。
    例子3:
    session1锁住了一个id=9这条记录,session2锁住了id<20的范围,除了id=9,被锁住了,然后session1要去插入id=7,已经被锁住,死锁了。

    mysql> select * from t3 where id=9 for update;
    
    +----+--------+------+---------------------+
    
    | id | course | name | ctime               |
    
    +----+--------+------+---------------------+
    
    |  9 | JX     | f    | 2016-03-01 11:36:30 |
    
    +----+--------+------+---------------------+
    
    1 row in set (0.00 sec)
    
     
    
    Session2:
    
    mysql> select * from t3 where id<20 for update;
    
    锁等待中
    
     
    
    Session1:
    
    mysql> insert into t3 values(7,'ae','a',now());
    
    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
    
    • mysql表级锁为什么不会产生死锁?

    MyISAM 操作数据都是使用表级锁,MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。所以不会产生死锁,但是由于每操作一条记录就要锁定整个表,导致性能较低,并发不高。

    • 怎么解决 like ‘%字符串%’ 时索引失效?
      只有右边的%是不会失效的。可以用多个字段的索引覆盖所有查询字段,那样type=index而不是all了

    相关文章

      网友评论

          本文标题:Java面试——数据库

          本文链接:https://www.haomeiwen.com/subject/drwruhtx.html