《带你走进Java的世界》第五章相关学习笔记

对于高级程序员,在SQL方面不仅要会简单的CURD语句,还得会使用相对复杂的语句实现项目的各种需求,了解诸如批处理和事务等高级知识点。更重要的是,还得具备一定的数据库调优能力。

项目中常用SQL语句注意点

尽量别写select *

不仅可能出现生产问题(插入新字段后结果错误),还会造成性能问题。

count(*)和count(字段名)比较

  1. 如果表中某字段允许为空,可能得到错误的结果
  2. 推荐使用count(主键)方式,有索引,性能会高些
  3. 经常见到select count(1) from xxx写法,标识用第一个字段获取总条数

但不推荐使用,万一第一个字段允许为空或者哪天在id前又加了允许为空的新字段。

insert 注意点

插入时要加入字段列表

同样是以防万一,以后插入新的字段

一些情况下能同时插入多条

insert into student (id,name,address) values (‘1’,’Peter’,’China’),(‘2’,’Mike’,’US’)

能够提升插入的性能,但需要注意:

  1. 有的数据库不支持批量插入,不如Oracle
  2. 在一个insert里,不能无限多插入,否则会出错

    delete里,可以通过in语句删除多条

    delete from student where id in (1,2,3,xxx)

能够提升性能,同样不能在一句delete语句的in从句里待删太多条,否则会出错

merge和update比较

merge——无则插入有则更新
注意点:

  1. 不是每种数据库都支持Merge,Oracle、SQL Server可用,MySQL不可用

    存储过程分析

    会编写存储过程是一项比较重要的技能,有几项开发要点:

  2. 争议点。存储过程只在创建时进行编译,以后每次执行都不需重新编译,这样能提高数据库执行速度。

  3. 针对某个业务逻辑,需要对多个表进行多次insert/delete/update/select操作,可以把这些操作汇集成一个存储过程,提高代码的重用性。
  4. 存储过程移植性很差
  5. 存储过程很难调试,Java抛出的异常只能知道“哪个存储过程出错”

⭐面试说辞*:

  1. 知道存储过程的语法,不仅学过,也在项目里用过
  2. 因为存储过程不大好调试,所以项目里用存储过程实现的功能比较简单,然后讲个存储过程实现的具体业务。
  3. 项目里有大批量数据插入更新操作时,用存储过程和JDBC里的批处理做了对比测试,具体做法是插入1w条数据,发现批处理的性能要比存储过程的好,所以项目里没有用存储过程来处理大批量的insert/delete/update操作。

数据库操作面试题

  1. 事务的四大特性是什么?
  2. 共享锁和排斥锁的含义及用途?
  3. 乐观锁和悲观锁的含义及用途?
  4. 内连接、外连接、全连接和左连接的语法及用途
  5. 触发器、视图和游标的含义及用途
  6. 三范式的含义及反范式的含义,在建表时用哪种?
  7. 什么是SQL注入?后果?预防?

image.png

传统JDBC

JDBC全称Java Database Connectivity,是Java语言用来规范客户端程序如何访问数据库的应用程序接口。
通过JDBC开发读写数据库
首先引入mysql-connector-java-xxx-bin.jar这个MySQL驱动包
然后,传统JDBC六步骤:

  1. 加载驱动程序;
  2. 获得数据库连接;
  3. 创建一个Statement对象;
  4. 操作数据库,实现增删改查;
  5. 获取结果集;
  6. 关闭资源。

由于JDBC存在的缺陷,很少使用,于是提出了ORM~

ORM

全称Object Relation Mapping,对象-映射-关系型数据库。用于实现面向对象编程语言里不同类型系统的数据之间的转换。提供了实现持久化层的另一种模式。
目前最流行的是:Mybatis和Spring Data JPA
SQL与数据库编程 - 图2

⭐优化数据库部分

这部分大段内容使用的是传统的JDBC,之后找资料补充:配置文件,批处理,防SQL注入
掘金·性能优化之MySQL优化
掘金·MySQL优化面试

⭐事务操作

友情链接:《对线面试官》 MySQL 事务、锁和MVCC

ACID

原子性(Atomicity):要么同时成功,要么同时失败,底层依赖undo log实现(回滚恢复)。
隔离性(Isolation):事务并发执行时,内部操作不能互相干扰,否则会产生下面第三点的常见问题。
持久性(Durability):一旦提交了事务,就将数据持久化到硬盘。持久性由redo log日志保证,当要修改数据时,MySQL首先把这条记录所在页找到,然后把该页加载到内存中,将对应记录修改。为了防止内存修改完MySQL就挂了,MySQL此时还会写一份redo log,记载这次在某个页做了什么修改。
一致性(Consistency):前三者均是为了保障数据一致性的手段。

开启事务,合理地提交和回滚

事务常见问题:脏读、不可重复读和幻读

友情链接:一文详解脏读、不可重复读、幻读

  • 脏读:一个事务读取了另一个事务尚未提交的数据

1090617-20211116140259703-1334255993.jpg

  • 不可重复读:一个事务的操作导致另一个事务前后两次读取到不同的数据

1090617-20211116140359155-111661271.jpg

  • 幻读:一个事务的操作导致另一个事务前后两次查询结果不同

幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。
更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。
1090617-20211116140446009-953158864.jpg
不可重复读侧重表达 读-读,幻读则是说 读-写,用写来证实读的是鬼影。

事务隔离级别

通过事务隔离级别解决上面的读写不一致问题,在InnoDB引擎中,定义了四种隔离级别:
1090617-20211116140507745-1304749327.jpg
首先说读未提交,它是性能最好,也可以说它是最野蛮的方式,因为它压根儿就不加锁,所以根本谈不上什么隔离效果,可以理解为没有隔离。
再来说串行化。串行化就相当于上面所说的,处理一个人请求的时候,别的人都等着。读的时候加共享锁,也就是其他事务可以并发读,但是不能写。写的时候加排它锁,其他事务不能并发写也不能并发读。
最后说读提交可重复读。这两种隔离级别是比较复杂的,既要允许一定的并发,又想要兼顾的解决问题。MySQL默认事务隔离级别为可重复读(RR),oracle默认事务隔离级别为读已提交(RC),
数据库的事务隔离越严格,并发副作用越小,但付出的代价越大;因为事务隔离本质就是使事务在一定程度上处于串行状态,这本身就是和并发相矛盾的。
同时,不同的应用对读一致性和事务隔离级别是不一样的,比如许多应用对数据的一致性没那么个高要求,相反,对并发有一定要求。
后续知识(解决可重复读幻读问题):隔离级别、幻读、Gap Lock、Next-Key Lock

不同的隔离级别对事务间的隔离性不一样,而隔离性是由MySQL的各种锁来实现的,只是它屏蔽了加锁的细节

面试准备要点

https://www.cnblogs.com/JavaArchitect/p/8495874.html