Java面试知识点解析-34 —— 数据库篇(事务、隔离级别、视图)


借参加过的多场Java开发面试,应聘岗位均为Java开发方向,在不断的面试中,又仔细对Java知识点进行复习和总结,也算是重新学习一下Java吧。

推荐收藏链接:Java 面试知识点解析


4)听说过事务吗?(必考)

事务简单来说:一个 Session 中所进行所有的操作,要么同时成功,要么同时失败;作为单个逻辑工作单元执行的一系列操作,满足四大特性:

  • 原子性(Atomicity):事务作为一个整体被执行 ,要么全部执行,要么全部不执行
  • 一致性(Consistency):保证数据库状态从一个一致状态转变为另一个一致状态
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行
  • 持久性(Durability):一个事务一旦提交,对数据库的修改应该永久保存

实例说明:

/*
 * 我们来模拟A向B账号转账的场景
 *   A和B账户都有1000块,现在我让A账户向B账号转500块钱
 *
 **/
//JDBC默认的情况下是关闭事务的,下面我们看看关闭事务去操作转账操作有什么问题

//A账户减去500块
String sql = "UPDATE a SET money=money-500 ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();

//B账户多了500块
String sql2 = "UPDATE b SET money=money+500";
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();

从上面看,我们的确可以发现A向B转账,成功了。可是如果A向B转账的过程中出现了问题呢?下面模拟一下

// A账户减去500块
String sql = "UPDATE a SET money=money-500 ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();

// 这里模拟出现问题
int a = 3 / 0;

String sql2 = "UPDATE b SET money=money+500";
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();

显然,上面代码是会抛出异常的,我们再来查询一下数据。A账户少了500块钱,B账户的钱没有增加。这明显是不合理的。

我们可以通过事务来解决上面出现的问题:

    // 开启事务,对数据的操作就不会立即生效。
    connection.setAutoCommit(false);

    // A账户减去500块
    String sql = "UPDATE a SET money=money-500 ";
    preparedStatement = connection.prepareStatement(sql);
    preparedStatement.executeUpdate();

    // 在转账过程中出现问题
    int a = 3 / 0;

    // B账户多500块
    String sql2 = "UPDATE b SET money=money+500";
    preparedStatement = connection.prepareStatement(sql2);
    preparedStatement.executeUpdate();

    // 如果程序能执行到这里,没有抛出异常,我们就提交数据
    connection.commit();

    // 关闭事务【自动提交】
    connection.setAutoCommit(true);

} catch(SQLException e) {
    try {
        // 如果出现了异常,就会进到这里来,我们就把事务回滚【将数据变成原来那样】
        connection.rollback();

        // 关闭事务【自动提交】
        connection.setAutoCommit(true);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}

上面的程序也一样抛出了异常,A账户钱没有减少,B账户的钱也没有增加。

注意:当Connection遇到一个未处理的SQLException时,系统会非正常退出,事务也会自动回滚,但如果程序捕获到了异常,是需要在catch中显式回滚事务的。

5)事务的并发问题有哪几种?
  • 丢失更新:一个事务的更新覆盖了另一个事务的更新;
  • 脏读:一个事务读取了另一个事务未提交的数据;
  • 不可重复读:不可重复读的重点是修改,同样条件下两次读取结果不同,也就是说,被读取的数据可以被其它事务修改;
  • 幻读:幻读的重点在于新增或者删除,同样条件下两次读出来的记录数不一样。
6)事务的隔离级别有哪几种?

隔离级别决定了一个session中的事务可能对另一个session中的事务的影响。ANSI标准定义了4个隔离级别,MySQL的InnoDB都支持,分别是:

  • 读未提交(READ UNCOMMITTED):最低级别的隔离,通常又称为dirty read,它允许一个事务读取另一个事务还没 commit 的数据,这样可能会提高性能,但是会导致脏读问题;

  • 读已提交(READ COMMITTED):在一个事务中只允许对其它事务已经 commit 的记录可见,该隔离级别不能避免不可重复读问题;

  • 可重复读(REPEATABLE READ):在一个事务开始后,其他事务对数据库的修改在本事务中不可见,直到本事务 commit 或 rollback。但是,其他事务的 insert/delete 操作对该事务是可见的,也就是说,该隔离级别并不能避免幻读问题。在一个事务中重复 select 的结果一样,除非本事务中 update 数据库。

  • 序列化(SERIALIZABLE):最高级别的隔离,只允许事务串行执行。

MySQL默认的隔离级别是可重复读(REPEATABLE READ)

MySql 的事务支持

MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关:

  • MyISAM:不支持事务,用于只读程序提高性能;
  • InnoDB:支持ACID事务、行级锁、并发;
  • Berkeley DB:支持事务。
7)什么是视图?以及视图的使用场景有哪些?

视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。

如下两种场景一般会使用到视图:

  • 不希望访问者获取整个表的信息,只暴露部分字段给访问者,所以就建一个虚表,就是视图。
  • 查询的数据来源于不同的表,而查询者希望以统一的方式查询,这样也可以建立一个视图,把多个表查询结果联合起来,查询者只需要直接从视图中获取数据,不必考虑数据来源于不同表所带来的差异。

注意:这个视图是在数据库中创建的 而不是用代码创建的。

8)drop,delete与truncate的区别?

drop 直接删除表;truncate 删除表中数据,再插入时自增长id又从1开始 ;delete 删除表中数据,可以加where字句。

  • drop table:

    • 属于DDL(Data Definition Language,数据库定义语言)
    • 不可回滚
    • 不可带 where
    • 表内容和结构删除
    • 删除速度快
  • truncate table:

    • 属于DDL(Data Definition Language,数据库定义语言)
    • 不可回滚
    • 不可带 where
    • 表内容删除
    • 删除速度快
  • delete from:

    • 属于DML
    • 可回滚
    • 可带where
    • 表结构在,表内容要看where执行的情况
    • 删除速度慢,需要逐行删除
  • 使用简要说明:

    • 不再需要一张表的时候,用drop
    • 想删除部分数据行时候,用delete,并且带上where子句
    • 保留表而删除所有数据的时候用truncate
9)触发器的作用?

触发器是与表相关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据库的完整性。


我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。扫描二维码加VX好友,拉你进【程序员面试学习交流群】免费领取。也欢迎各位一起在群里探讨技术。
在这里插入图片描述

发表评论

邮箱地址不会被公开。 必填项已用*标注

昵称 *