一. 索引
字段的索引类似书籍的目录,可以快速查找数据。
创建主键约束(PRIMARY KEY
)、唯一约束(UNIQUE
)、外键约束(FOREIGN KEY
)时,会自动创建对应列的索引。
- 查看索引
show index from 表名;
- 创建索引
create index 索引名 on 表名(字段名);
- 删除索引
drop index 索引名 on 表名;
索引保存的数据结构主要为B+树,及hash的方式,后面我会专门写一个博客,来介绍B+树。
二. 事务
2.1 事务的概念
在讲事务之前,先讲一个场景:转账。
比如,张三要给李四转账500元,那我们就要在数据库里操作:
update account set balance =balance-500 where name ="张三";
update account set balance =balance+500 where name ="李四";
而如果在执行完第一个语句后,出bug了,那么张三少了500元,而李四却没收到!!!
以此,我们引出事务的概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
2.2 事务的特性
- 原子性:通过事务,将多个操作打包到一起;
- 一致性:要么全部成功,要么全部失败;
- 持久性:事务的修改,持久化存在(存入硬盘);
- 隔离性:多个事务并发执行,可能引发一些问题。
下面,来重点解释一下隔离性会出现哪些问题:
- 典型bug1:脏读
即事务1修改了某个数据,但还没有提交,此时被事务2读到,产生错误(事务1可能继续修改数据)。
解决方法:给写操作加锁,即写的时候不能读。 - 典型bug2:不可重复读
即在事务2读取数据的时候,数据被事务3修改,导致事务2两次读到的数据不一样。
解决方法:给读操作加锁,即读的时候不能写。 - 典型bug3:幻读(影响较小)
即在事务2读数据的时候,事务3新增了别的数据,导致事务2两次读到的结果集不一样。
解决方法:串行化:不在执行任何并发。
而不再执行任何并发,就意味着效率会很低。而实际上,效率和准确性,不可兼得。
那么以上的解决办法如何体现到代码上呢,MySQL在配置中提供了隔离级别的选项:
- read uncommitted : 不加锁,并行程度最高,隔离程度最低,数据最不靠谱,可能出现 脏读+不可重复读+幻读;
- read committed:读加锁,可能出现 不可重复读+幻读;
- repeatable read(默认):可重复读,给读/写操作加锁,可能出现幻读;
- serializable:串行化,不执行任何并发,最高等级隔离,效率最低,数据最准确
准确率大于效率的场景很容易想到,就是转账;
而什么时候对效率的要求要大于准确率呢,想像某音点赞的时候,到10w+的时候,点一个赞还是10w+,这个时候就是效率要求高于准确率。
2.3 事务的操作
那么,该如何操作呢:
(1)开启事务:start transaction
;
(2)执行多条SQL语句
(3)回滚或提交:rollback
/commit
;
说明:rollback即是全部失败,commit即是全部成功。
start transaction;
张三账户减少2000
update accout set money=money-2000 where name = '张三';
李四账户增加2000
update accout set money=money+2000 where name = '李四';
commit;
如果这个命令中第一条执行成功,而第二条失败了,则会自动撤销第一条命令。
三. JDBC编程
JDBC,即Java Database Connectivity,即用Java连接数据库进行编程。
JDBC是一种用于执行SQL语句的Java API,它是Java中的数据库连接规范。这个API由java.sql.
,javax.sql
. 包中的一些类和接口组成,它为Java开发人员操作数据库提供了一个标准的API,可以为多种关系数据库提供统一访问。
3.1 JDBC工作原理
JDBC 为多种关系数据库提供了统一访问方式,作为特定厂商数据库访问API的一种高级抽象,它主要包含一些通用的接口类。
JDBC访问数据库层次结构:
JDBC的优势在于它不限定于特定数据库厂商的API,即其通用性。
3.2 JDBC使用
准备
- 1.准备数据库驱动包,并添加到项目的依赖中:到https://mvnrepository.com/中下载MySQL的驱动包。
- 2.在Java项目文件夹中新建lib文件夹,将驱动包加入并解析
使用
- 1.创建数据源
DataSource dataSource= new MysqlDataSource();
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java110?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("1234");
其中127.0.0.1为“环回ip地址”(服务器和客户端都在一个电脑时使用);
3306为下载MySQL时设置的端口号,默认3306;
java110为数据库名,characterEncoding=utf8为设置字符编码,useSSL=false为关闭加密传输。
- 2.建立连接
Connection connection= dataSource.getConnection();
- 3.构造SQL
String sql="select * from classmates";
PreparedStatement statement= connection.prepareStatement(sql);
这里是将sql语句预处理后发送给服务器,以便服务器能直接执行,提高效率。
- 4.将SQL发送给服务器
查询:
ResultSet resultSet=statement.executeQuery();
while(resultSet.next()){
int id= resultSet.getInt("id");
String name=resultSet.getString("name");
System.out.println("id="+id);
System.out.println("name="+name);
}
修改:
int n=statement.executeUpdate();
System.out.println("n="+n);
- 5.释放资源
resultSet.close();
statement.close();
connection.close();
释放资源时,顺序应为创建时相反(类似于回文结构)。
最后,放上jdbc源码链接,以供参考:jdbc编程