JDBC
JDBC
JDBC是什么
Java数据库连接,Java Database Connectivity,简称JDBC,它是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口
它为什么而存在,或者说它可以干什么
它提供了诸如查询和更新数据库中数据的方法,为了解决对象关系映射的问题。
一、安装
mysql官网下载Mysql数据库。
二、架构
JDBC API 与java应用程序进行通信
JDBC Driver 和具体的数据库进行连接
二、URL
URL解释
jdbc : mysql : // 10.164.172.20:3306/cloud_study
jdbc : | mysql : | // 10.164.172.20:3306 | /cloud_study |
---|---|---|---|
协议 | 子协议 | IP和端口 | 数据库名称 |
常见JDBC URL
- mysql: jdbc : mysql : // :/database
- oracle: jdbc :oracle:thin:@::database
- sqlserver: jdbc:Microsoft:sqlserver://:;DatabaseName=datavase
三、API
Driver -> DriverManager ->Conections -> Statement -> ResultSet
- Driver: 通过Class.forName来指定驱动包名
- DriverManager 用该类获取Conection。
- Conections: java程序对后端数据库的物理链接
- Statement: 数据库容器,用来承载数据库操做语句
- ResultSet 代表sql查询的结果集,ResultSet对象是行和列组成的列表
- .next 将光标移动到)下一行
- .previous (将光标移动到)上一行
- .absolute (将光标移动到)某一行
- .beforeFirst (将光标移动到)第一行前面
- .afterLast (将光标移动到)最后一行后面
- .getString(ColumnName/Index)
- .getInt(ColumnName/Index)
- .getObject(ColumnName/Index)
- SQLException 异常
四、构建步骤
示例代码省略了异常处理及数据库信息。
-
装载驱动程序
Class.forName("com.mysql.jdbc.Driver");
-
建立数据库连接
Connection conn = connDriverManager.getConnection(DB_URL,User,Password);
-
执行SQL语句。
Statement state = conn.createStatement();
Result rs = executeQuery("select username from user");
- 获取执行结果。
while(rs.next) {
System.out.println(rs.getString("username"));
}
- 清理环境
conn.close();
state.close();
rs.close();
五、业务场景
- 过滤条件太弱,一次可能读出较多记录。
- 读取数据库中所有记录。
a) 海量数据读取会导致内存溢出。如果一次性读出得内存大小超过JVM设定的大小,则会得到内存溢出的异常。
b) 游标的提出:游标提供一种客户端读取部分服务段结果集的机制。
c) 游标的使用:jdbc:mysql:// :/database?useCursorFetch=true - 存储大对象。
a) 导致的问题:即使读取一行数据也可能导致内存溢出。
b) 解决方法:使用流方式。 - 大量数据插入操作
a) 原因分析:每次发送接受SQL特别花时间。能否每次发送多条SQL?
b) 批处理 Statement , 执行单元:Batch
i. addBatch();
ii. executeBatch();
iii. clearBatch(); - 中文混乱
a) show Variables like ‘%character%‘; 查看数据库和服务器的字符属性
b) show create table user; 查看表和表中每个字段的字符属性
c) 字符集设置 Server->Database->Table->columu .以最后面的为准
d) JDBC设置 DB_URL = DB_URL + characterEncoding=utf8
六、数据池链接
简介
获取connect连接需要发送4次消息,时间开销比较大。连接如下:
MySQL客户端 --------------MySql服务端
| ------------请求建立连接------------->|
| <---------发送随机密码种子--------- |
| -----------发送加密密码-------------->|
| <------------连接建立成功------------|
DBCP目前比较流行的连接池
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。
连接
- 创建连接池对象 BasicDataSource
a) .Url
b) .DriverName
c) .Use
d) .Password - 获取数据库连接
a) .getConnection(); - 释放数据库连接
a) Conn.close; 此处close()是归还给连接池而不是断开连接。 - 高级配置 BasicDataSource
a) .setInitialSize();
b) .setMaxTotal();
c) .setMaxWaitMillis();
d) .setMaxIdle(); 设置最大空闲的线程数量,超过就会被销毁。
e) .setMindle(); 设置最小空闲的线程数量,建议和最大设置成一样。 - DBCP定期检查
.setTestWhileIdle(True); 开启测试
.setMinEvictableIdleTimeMillis(); 最小空闲时间
.setTimeBetweenEvictionRunsMillis(); 检查运行时间的间隔
服务端可以设置最大连接数 超出抛异常 java客户端也要控制不要超出最大连接数。
七、数据库的死锁分析与解决
事务并发执行
事务一 张三需要给李四转账100元钱
事务二 将张三和李四的单位改为Apple
事务持锁
Mysql是加行锁。 事务一加了张三的行锁,事务二要修改单位而加了李四的行锁。造成事务一等待事务二,事务二等待事务一。
死锁
死锁是指两个或者两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。
死锁产生的必要条件
- 互斥
- 并发执行的事务为了进行必要的隔离保证执行正确,在事务结束前,需要对修改的数据库记录持锁,保证多个事务对相同数据库记录串行修改。
- 对于大型并发系统无法避免
- 请求和保持
- 已经持有一个资源锁,等待另一个资源锁
- 死锁仅发生在请求两个或者两个以上的锁对象
- 由于应用需要,难以消除。
- 不剥夺
- 已经获得所资源的事务,在未执行前,不能被强制剥夺,只能使用完时,由事务自己释放。
- 一般用于已经出现死锁时,通过破坏该条件达到解除死锁的目的。
- 数据库系统通常通过一定的死锁检测机制发现死锁,强制回滚代价相对较小的事务,达到解除死锁的目的。
- 环路等待
- 发生死锁时,必然存在一个事务—锁的缓刑链
- 按照同一顺序获取锁,可以破坏该条件。
- 通过分析死锁事务之间的锁竞争关系,调整SQL的顺序,达到消除死锁的目的。
Mysql 中的锁
排他锁(X)和共享锁(S)
已有锁↓\欲加锁→ | X | S |
---|---|---|
X | 冲突 | 冲突 |
S | 冲突 | 兼容 |
加锁方式
- 外部加锁
i. 由应用程序添加,锁依赖关系较容易分析
ii. 共享锁(S):select * from table lock in share mode
iii. 排他锁(X):select * form table for update - 内部加锁
i. 为了实现ACID特性,由数据库系统内部自动添加
ii. 加锁规则繁琐,与SQL执行计划、事务隔离级别、表索引结构有关。
哪些SQL需要持有锁
- 快照读(读取的是记录数据的可见版本(可能是过期的数据),不用加锁)
i. Innodb实现了多版本控制(MVCC),支持不加锁快照读。
ii. Select * from table where……
iii. 能够保证同一个Select结果集是一致的
iv. 不能保证同一个事务内部,Select语句和其他语句的数据一致性,如果业务需要,需通过外部显式加锁。 - 当前读(读取的是记录数据的最新版本,并且当前读返回的记录都会加上锁,保证其他事务不会再并发的修改这条记录)
i. Select * from table lock in share mode
ii. Select * from table for update
iii. Updata from table set
iv. Insert into……
v. Delete from table……
SQL加锁分析
可以给读操作上共享锁,给修改操作上排他锁
分析死锁的常用方法
Show engine innodb status 展示回滚的事务和sql语句