数据库4.0

索引 事务 JDBC~

目录

一、MySQL索引

[1.0 概述](#1.0 概述)

[2.0 相关操作](#2.0 相关操作)

[3.0 注意](#3.0 注意)

[4.0 索引背后的原理的理解](#4.0 索引背后的原理的理解)

[二、 事务](#二、 事务)

[1.0 原子性](#1.0 原子性)

[2.0 隔离性](#2.0 隔离性)

(1)并发执行

[(2) 出现的问题](#(2) 出现的问题)

[3.0 使用](#3.0 使用)

三、JDBC编程

[1.0 概述](#1.0 概述)

[2.0 如何下载驱动包](#2.0 如何下载驱动包)

[3.0 jar如何引入到项目之中](#3.0 jar如何引入到项目之中)

[4.0 jdbc编写流程](#4.0 jdbc编写流程)


一、MySQL索引

mysql面试中考察的重点!

1.0 概述

索引(index) 当作一本书的目录 是用来加快查询机制

select查询查询的时候 先要遍历表 如果表非常大 这样的遍历成本将会非常大 至少是O(N)

数据库的数据存在硬盘上,每次读取一个数据,都需要读取硬盘,这个开销本身就很大

在内存里面速度快 但是在硬盘中不是这样的

索引就产生了~

通过索引来加快查询的速度,避免针对表进行遍历

代价:占用更多的空间,生成索引,是需要一系列的数据结构,以及一系列额外的数据,来存储到硬盘空间中的

可能降低插入 修改 删除的速度 (需要更新索引)

2.0 相关操作

(1) 查看索引 show index from 表名 ;

(2) 创建索引 create index 索引名字 on 表名(列名) ;

(3)删除索引 drop index 索引名 on 表名;

主键 unique 外键 都会自动生成索引 (这些都是要求不能重复的 自己引入索引这个时候根据索引就不需要遍历了)

手动创建的索引,可以手动删除 如果自动创建的索引,是不能删除的!

一个索引是针对一个列来指定的 只有针对这一列进行条件查询的时候,查询速度才能被索引优化

一本书可以有多个目录,一个表也可以有多个索引

3.0 注意

创建索引 也是一个危险操作 创建索引的时候,需要针对现有的数据,进行大规模的重新整理

删除索引 也是一个危险的操作

如果你当前是一个空表或者数据不多 创建索引都没有问题

如果这个表本来就很大,创建索引,有很容易就把数据库服务器给卡住

一般来说,创建索引,都是在创建表的时候就规划好了,一旦表已经使用很久了,有很多数据,需要修改索引,就要慎重了~

非要创建也不是不行 就需要一些其他的小技巧

一个做法是 另外再搞一台机器 部署服务器 也创建同样的表 并且把表上面的索引创建好

再把之前的机器上的数据给导入到新的mysql服务器上面,导入数据的过程中就可以控制节奏

多花点时间没事,补药影响到原来的服务器正常的运转就行

当所有的数据都导入完毕,就可以使用新的数据库,替换旧的数据库~~

数据库和数据太重要了 我们得万分小心 避免数据损失或者丢失

4.0 索引背后的原理的理解

索引也是通过一定的数据结构来实现的 .

红黑树 可以精准匹配 也能范围查询 也能模糊匹配

数据库引入的索引是一个改进的树形结构 B+ 树 (N叉搜索树)

(树的内容之后迭代) B+树的优点

mysql索引实现 也是有一些变数的 不是只有B+树这一情况的

二、 事务

比较经典的面试题

事务的性质:原子性 一致性 持久性 隔离性

原子性:回滚的方式 保证这一系列操作 都能执行正确 或者恢复如初

一致性:事务执行之前 和 之后 数据都不能离谱(约束 一系列的检查机制)

持久性:事务做出的修改 都是在硬盘上面持久保存的 重启服务器,数据仍然是存在的

隔离性:数据库并发执行多个事务的时候 涉及到的问题

1.0 原子性

开发中经常会涉及到一些场景,需要'一气呵成' 的完成一些操作

例如:张三给李四转账500 张三的账户减500给李四

如果执行一半 数据库崩溃了或者断电了 这个时候怎么办呢

此时的数据就会出现不上不下的状态 非常明显的bug

引入事务就是为了避免上述问题~ 事务就可以把多个sql打包成为一个整体

保证这些sql要么全部执行正确 要么看起来一个都不执行

关键操作:翻新~~~ 数据库中称为回滚 也就是回退机制 没有执行成功 回退回来

2.0 隔离性

数据库并发执行多个事务的时候,涉及到的问题~~~

面试的时候 可能会考察 事务性质中比较复杂的一个性质

(1)并发执行

mysql是一个客户端服务器结构的程序

一个服务器可以给多个客户端提供服务 每个客户端都会让数据库执行事务~~~

很有可能,客户端1提交的事务1 执行了一半,客户端2提交的事务也过来了

数据库服务器就需要同时处理这两个事务,并发执行(非常 常见的)

如果我们希望数据库服务器执行效率高,就希望提高并发程度,但是提高了并发程度之后,可能会存在一些问题~~~ 导致数据出现一些'' 错误 '' 的情况

数据正确和效率之间做权衡: 往往提升了效率,就会牺牲正确性,提升了正确性就会牺牲效率

(2) 出现的问题

并发执行的时候会出现什么问题呢?

脏读问题: 一个事务A正在写数据的过程中,另一个事务B读取了同一个数据

接下来事务A又修改了数据 导致B之前读到的数据是一个无效的(过时的) 数据

解决脏读问题,核心思路,是针对写操作加锁

(和别人约好,等我确认写完了,提交到码云上面,你从我的码云上来看)

这样并发程度就降低了~~ 隔离性提高了 效率降低了 数据准确性提高了

不可重复读问题:并发执行事务过程中,如果事务A在内部多次读取同一个数据的时候,出现不同的情况,这种就是不可重复读,事务A在两次读的之间,有一个事务B修改了数据并提交了事务

解决不可重复读问题,核心思路,就是给读操作加锁 (约定同学们读的时候,我也不能写)

这样并发程度又进一步降低了 隔离性也提高了 效率低了 数据的准确性又提高了

幻读问题:一个事务A执行过程中,两次的读取操作,数据内容虽然没有改变,但是结果集变了

约定了读加锁和写加锁 我在写代码的时候,大家不能读,只能读码云上提交的版本

大家在读的时候 我也不能写 此时已经解决了脏读和不可重复读问题

但是 你们看A的时候 我写B的代码啊 这样可以保证,同学们在读的时候,我可以干点啥,不至于完全闲着 此时 虽然我这边没有修改A代码 但是同学们突然发现,码云上一下蹦出来个B代码

数据虽然没有改变 但是结果集变了

通过引入串行化的方式,解决幻读,保持绝对的串行执行事务,此时完全没有并发了 根本上解决

此时的效率是最低的 数据是最准确的 效率是最低的 数据是最准确的

(3)总结

效率和正确性 => 不同的需求场景就有不同的要求

mysql服务器也提供了 隔离级别 让我们针对隔离程度进行设置

应付不同的需求场景情况 有的场景追求是正确性 效率是其次 例如是充值转账一系列相关的场景

有的场景追求的是效率性 正确性是其次 短视频 点赞 投币 转发 评论

隔离文件中 可以直接在mysql配置文件中,修改数据库的隔离级别 满足不同的需求

(4) 隔离级别

四种隔离级别 对应上述的问题

可重复读是默认的隔离级别

脏读 read uncommitted(读未提交) 并发程度最高,速度最快,隔离性最低,准确性最低

不可重复读 read committed(读已提交) 引入了写加锁 只能读 写完之后提交的版本 xxxxxx

repeatable read (可重复读) 引入写加锁和读加锁 写的时候不能读 读的时候 不能写

幻读 serializable(串行化) 严格的按照穿行的方式 一个一个的执行事务

3.0 使用

事务的使用,其实是没啥可说~~ 更主要的是要关注事务 背后的一些原理性质的内容

这个部分会考察面试题

start transaction 开启事务,单独执行的每个sql 都是自成一个体系

此时这些sql之间是没有原子性的

/commit 事务结束了

rollback 主动触发回滚 一般是要搭配一些条件判断逻辑来使用的

sql里也能支持 条件 循环 变量 函数 但是日常开发一般不会这么写

更多的是搭配其他的编程语言

三、JDBC编程

通过Java代码操作mysql数据库

工作中一般不会直接使用idbc 面试也一般不考jdbc

jdbc这套api使用起来是比较繁琐的 因此有一些大佬把jdbc的api又进一步封装,成了一些操作数据库的框架(比如Mybatis ,jpa..........)

1.0 概述

数据库编程,是需要数据库服务器,提供一些API 共程序猿调用的

API: 应用程序编程接口 就是有一组类和函数 提供给程序员调用

各种数据库都有API 提供的api不同 即使有些api功能类似,细节上也会有差异

(这样的做法苦了广大程序员,增加了程序员的学习成本,非常的不友好,这个时候需要有分量的大佬站出来一统江湖 这个大佬就是 Java)

Java设计出了一套api的规范 你们提供的api都要和我这边对接上~~~

程序员只要了解一套api,就可以操作各种数据数据库了 倒逼其他数据库创建了对应的接口

而Java的这套接口就是 JDBC (隔壁C++的程序员又馋哭了 C++官方不给力,各种开源混战)

注意理解 连接的东西就像是转接头一样

2.0 如何下载驱动包

要想在程序中操作mysql 就需要安装mysql的驱动包 并把驱动包引入到项目里

(中央仓库是一个很好的途径)推荐一个:mvnrepository.com

3.0 jar如何引入到项目之中

先把jar包复制到项目目录中 目录标记标记成为库

每次创建工程都需要将这个jar包导入 补药嫌麻烦

实际开发中,一两年都没机会创建项目

准备工作完成 开始编写代码(demo example tutor 翻译过来都为 例子)

4.0 jdbc编写流程

这一套代码都是固定流程 一下子涌入新鲜的类 新鲜的方法 会觉得眼花缭乱

下来之后 把这些代码动手多敲几遍 就会发现这个就是固定的流程 比较简单

(1)创建datasource 数据源

数据源 表示数据的源头 数据库服务器所在的位置

url 表示网络上的资源位置

ip:地址 端口:电话号 127.0.0.1环回 自己把数据发送给自己

根据dataSorce 创建一个datasorce对象调用里面的方法

送快递给xxx地址xxx人

上面是一个准备工作 没有和真正的mysql服务器进行真正的连接

(2)和数据库服务器建立连接

Connection connection = dataSource.getConnection();

即使是使用代码操作数据库 仍然是依赖sql完成的

前面学过的各种sql 在这里都是同样适用的

要注意的点是 选择的是 java.sql

(3) 构造sql 发送给服务器

构造一个sql字符串 String sql = "insert into student values ( 1, '张三' ) " ;

prepared 准备好的/预处理的 statement 语句

PreparedStatement statement = connection.prepareStatement(sql) ;

(4)把sql语句发送给服务器 执行sql

statement.executeUpdate();

excuteQuery() select 读操作

exectedUpdate() insert 写操作

(5) 释放资源 关闭连接

statement.close();

connection.close()

执行完毕之后,最后一个步骤

程序通过代码和服务器进行通信 是需要消耗一定的硬件/软件资源的

在程序结束的时候,就需要告知服务器,释放这些资源/客户端也需要释放资源

完整的代码流程示例:

java 复制代码
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Demo1 {
    public static void main(String[] args) throws SQLException {
        //1.0 先创建一个数据源    描述数据源头  数据库服务器所在的位置
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3307/java109?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("1234");

        //2.0  和数据库服务器建立连接  进行响应和交互操
       Connection connection = dataSource.getConnection();

       //3.0  构造sql  发给服务器
        String sql = "insert into student values(1,'张三') " ;//先构造出字符串的sql
        PreparedStatement statement = connection.prepareStatement(sql);//准备好的/预处理的  语句

        //4.0 把sql发给服务器  返回一个整数 表示影响到的行数
        int n = statement.executeUpdate();
        System.out.println("n="+n);

        //5.0 执行完毕,最后一个步骤 释放资源 关闭连接
        statement.close();
        connection.close();

    }
}

修改和删除,代码写法和插入是非常类似的

从idea获取输入:

String sql = "insert into student values(?,?)"; 使用?作为占位符

PreparedStatement statement = connection.prepareStatement(sql) ;

statement.setInt(1,id); 替换第几个 从1开始

statement,serString(2,name);

(6)使用jdbc执行查询操作

和前面插入不同的地方:

4.0 执行sql

ResultSet resultSet = statement.excuteQuery();

resultSet 就表示查询的结果集合(临死表) 此处需要针对表进行遍历

5.0 遍历结果集合 通过next方法就可以获取到临时表中的每一行数据

while(resultSet.next()){ } //针对这一行进行处理 相当于在临时表内部,有一个光标

取出列的数据

int id = resultSet.getInt("id") ;

String name = resultSet.getString("name");

System.out.println("id="+id +",name="+name); 多了一个遍历结果集的过程

技术表层包含着很多想法、情绪、身体反应以及现实利益等

希望大家客观的认识到这些部之后 迭代自己答案

至此 Mysql基础内容迭代完毕 后续还有Mysql的进阶部分

感谢大家的支持

更多内容还在加载中...........

如有问题欢迎批评指正,祝大家生活愉快、学习顺利!!!

相关推荐
千册15 分钟前
python+pyside6+sqlite 数据库测试
数据库·python·sqlite
java叶新东老师2 小时前
PowerDesigner 画ER图并生成sql 教程
数据库·sql
Jonariguez2 小时前
Mysql InnoDB存储引擎
数据库·mysql
nbsaas-boot3 小时前
SQL Server 窗口函数全指南(函数用法与场景)
开发语言·数据库·python·sql·sql server
Y.ppm3 小时前
数分思维12:SQL技巧与分析方法
数据库·sql
森叶3 小时前
Claude Code 安装向量数据库MCP服务
数据库
bestsun9993 小时前
Time drifts can result in unexpected behavior such as time-outs.
数据库·oracle
waveee1235 小时前
学习嵌入式的第三十四天-数据结构-(2025.7.29)数据库
数据结构·数据库·学习
何传令5 小时前
SQL优化系统解析
数据库·sql·mysql
找不到、了5 小时前
Redis内存使用耗尽情况分析
数据库·redis·缓存