JAVA工作1~3年面试准备:数据库

要想进阶成Java中级开发工程师,有一些东西总是绕不过去的,Java的知识体系里,像IO/NIO/AIO,多线程,JVM,网络编程,数据库,框架等必须有一定了解才行。最近在准备面试,所以对这些东西也做个记录。本篇记录的是数据库相关。

(吐槽下CSDN的改版,博客右边多出了一系列占视野的推荐文章,看着烦,还不能取消!)

数据库基本内容简单回顾(Mysql)

 

三范式?

1.列不可再分;

2.行通过主键/主属性可以唯一区分;

3.非主属性只依赖于主属性,而不能依赖于其它非主属性。

 

事务?

事务是一系列在数据库上的操作,是数据库应用中最基础的单位。

事务有四个性质,ACID。

原子性(Atomic) :指事务中的操作要么都发生,要么都不发生。  (如转帐扣款加款的两条语句,要么执行,要么不执行)

一致性(Consistency):指事务使得系统从一个一致的状态转换到另一个一致状态。(此处有强一致性,弱一致性,最终一致性,其它一致性的说法)

隔离性(Isolation):多个事务并发访问时,事务之间是隔离的,一个事务不影响其它事务的运行效果。 (此处有隔离级别的说法)

持久性(Durability):事务完成以后,该事务所对数据库所作的更改就持久地保存在数据库中,不会被回滚。

 

隔离级别?

不考虑事务的隔离性,会发生的几种问题:脏读,不可重复读,幻读。然后数据库隔离级别有如下四种:

读未提交(Read Uncommitted):最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。即可能出现脏读,不可重复读,幻读

读提交(Read Committed):只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。

可重复读(Repeated Read):在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。这是Mysql中默认的隔离级别。

串行化(Serialization):事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。

PS:

脏读:是指在一个事务处理过程里读取了另一个未提交的事务中的数据。

不可重复读:是指一个事务范围内多次查询却返回了不同的数据值,是因为在查询间隔别其它事务修改并提交了。

幻读:和不可重复读都是读取了另一条已经提交的事务,不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

MySQL数据库中查看当前事务的隔离级别:

select @@tx_isolation;
set tx_isolation=’隔离级别名称;’

MySQL数据库中设置事务的隔离级别:

设置数据库的隔离级别一定要是在开启事务之前,隔离级别的设置只对当前链接有效。一个窗口,或者一个connection。而不会影响其它

JDBC中:
conn = JDBCUtils.getConnection();
conn.setTransaction(Connection.TRANSACTION_SERIALIZABLE);
conn.setAutoCommit(false);

 

存储引擎?

MYISAM /INNODB 区别

MYISAM 不支持事务,不支持外键,行锁,插入数据时,锁定整个表,查表总行数时,不需要全表扫描。MyISAM的可移植性、备份及恢复较好。
       INNODB 支持事务,支持外键,行锁,查表总行数时,全表扫描。INNODB 的可移植性、备份及恢复相对较差。

MYISAM /INNODB选择:

MyISAM相对简单,所以在效率上要优于InnoDB。如果系统读多,写少。对原子性要求低。那么MyISAM最好的选择。

       InnoDb支持事务,如果系统写入较多或对事务一定的要求,InnoDB就是首选了。INNODB 也是默认的存储引擎。

 

Mysql索引?

索引用于快速找出在某个列中满足特定值的行。相当于是一本书的目录。

MyISAM和InnoDB存储引擎:只支持BTREE索引。 (MEMORY/HEAP存储引擎:支持HASH和BTREE索引)

索引我们分为四类来讲 单列索引(普通索引,唯一索引,主键索引)、组合索引 ( 遵从了最左前缀)、全文索引、空间索引、

创建方法:

alter table table_name add index index_name (column_list) ; 
alter table table_name add unique (column) ;
alter table table_name add primary key (column) ;
create index index_name on table_name (column);

索引原理:

顺序查找时间复杂度为O(n),建立索引后查找时间复杂度为O(log(n)),时间上有指数级的提高。

 

数据库锁

MySQL各存储引擎使用了三种类型(级别)的锁定机制:表级锁定,行级锁定和页级锁定。

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

MySQL数据库默认使用InnoDB存储引擎,它支持行锁,也支持表锁,默认情况下是采用行锁。

InnoDB实现了以下两种类型的行锁。

概念:

共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。

排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

使用:

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);

对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。

共享锁(S): SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(X): SELECT * FROM table_name WHERE ... FOR UPDATE

 

注意点:

行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。

show create table table_name; -- 可以看到表结构与表引擎
mysql -hlocalhost -uroot -proot  -- 登录
create index index_name on table_name(column); -- 创建索引
show variables like '%autocommit%'; -- 查看自动提交
set @@autocommit=0;  -- 临时生效(只对当前客户端有效)
show status like ‘table%’;  -- 查看表级锁的争用状态
show status like ‘innodb_row_lock%’;  -- 查看行级锁的争用状态

 

 

存储过程?

存储过程就是编译好了的一些sql语句。 (Procedure)
1)存储过程因为SQL语句已经预编绎过了,因此运行的速度比较快。
2)可保证数据的安全性和完整性。通过存储过程可以使没有权限的用户在控制之下间接地存取数据库,从而保证数据的安全。通过存储过程可以使相关的动作在一起发生,从而可以维护数据库的完整性。
3)可以降低网络的通信量。存储过程主要是在服务器上运行,减少对客户机的压力。
4)《阿里巴巴java编码规范》中,强制禁止使用存储过程,理由是存储过程难以调试和扩展,更没有移植性。

   mysql中确实没怎么见使用存储过程,sqlServer听说用得挺多。个人觉得不用也可以。哈哈。

 

触发器?

当满足触发器条件,则系统自动执行触发器的触发体。(Trigger)
触发时间:有before,after.

触发事件:有insert,update,delete三种。

触发类型:有行触发、语句触发

 

 

查询语句优化?

首先,要分析这个查询语句慢的原因。是因为表数据太多,还是SQL语句写得有问题。

可以用explain语句查看这个SQL的时间耗费情况。然后针对解决。

1)如果是表数据太多,就看有没有建索引,或者索引有没有用上。

2)然后再看一下能不能减少表之间的关联

3)然后看一下查询字段能不能简化,不用select * 而拿需要的字段,尽量返回少量数据

4)然后就是看一下sql能不能优化,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面,

  能用left join就不用子查询,能用 between 就不要用 in,也不要用 != <> like 这种使索引失效的语法。

5)如果实在没办法的话,就看要不要分库分表。减少每张表中的数据,分而治之。

一般来说,如果一开始数据库结构设计得好的话,每张表放三四百万数据查询起来还是挺快的。主要也是sql上的问题。

 

union/union all?

UNION在进行表链接后会筛选掉重复的记录,UNION ALL只是简单的将两个结果合并后就返回。

从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复的数据的话,那么就使用UNION ALL。

 

还有就是写SQL了

 

 

 

 

猜你喜欢

转载自blog.csdn.net/HelloWorld_In_Java/article/details/82584656