Java开发 - 数据库中的基本数据结构(二)

简介: Java开发 - 数据库中的基本数据结构

数据库中的事务


数据库中的事务提交默认开启,可通过命令查询状态,关闭或者开启:


查询命令


show variables like 'autocommit'


关闭命令

set autocommit=off;


开启命令

set autocommit=on;


事务的管理


开启事务:beigin

提交事务:commit

回滚事务:rollback


尤其需要注意的是,增删改默认开启数据库事务,select不涉及任何事务。


在微服务中,当涉及到多步增删改的操作步骤时,一般我们使用dubbo调用其他模块数据库操作时会用到事务,以保证所有的操作要么一起成功,要么一起失败。此时就会为整个业务实现方法增加事务的注解。


数据库中的死锁


死锁在数据访问安全时时有发生,数据库也是数据访问的一种,虽然数据库提供了一些锁机制来保证线程安全,但,有人的地方就有江湖,数据库也无可避免的就会出现死锁的现象。


下面,我们举个例子来说明数据库中的死锁:


用户表:user1

id name age
1 张三 20
2 李四 30

事务A
1.修改user1的张三为张二
2.删除user2的id为1的王五

<------------------------->

事务B
1.修改user2的王五的年龄为20
2.删除user1的id为1的张三

用户表:user2

id   name age
1 王五 15
2 周六 18

我们可以想象一下,这俩操作会怎么样,上面我们说过,增删改都会增加排他锁,所以第一步操作都可以执行完成,且添加了排他锁,那么在第二步操作的时候,由于排他锁的存在,需要等待排他锁的释放,会导致事务A和事务B相互等待,无法继续执行,死锁产生。


那么出现死锁之后,数据库是怎么解决的呢?


在实际操作用会出现两种情况,一种是提示死锁,另一种是提示锁等待超时,这是因为数据库版本不一致的问题。


在mariadb中,对死锁是这么处理的:当检测到死锁后,让一端的事务回滚,并提示死锁DeadLock,接着让另一端的事务执行成功,一般是让后执行的事务进行回滚,回滚之后的事务执行失败,并且不会再次主动发起自旋执行。


数据库中的视图


什么是视图?


数据库中的视图是一张虚拟表,用于展示结果集,它并不保存数据,而是从已经存在的表中调取数据,后期如果要执行相同的sql,可以直接调用视图名称。听起来有点像我们对方法的封装,这里是对数据库sql语句的封装,只不过数据库没有方法的概念。


使用场景:我们要多次展示数据库中某张表或几张表中相同的数据,一样的sql语句需要多次使用,这时候,就可以为这个sql创建视图,在需要的地方直接调用视图,从视图中获取数据,简化sql语句。


操作视图:


创建视图:


create view view_name as select xx from xxxx_tb where xxxxxx;


也可以进行连表操作。


调用视图:


select xxx from view_name;


删除视图:


drop view view_name;


你会发现视图的操作和数据库的操作是一样的。


视图的注意事项


视图是对sql语句的封装,不是对查询结果集的封装,视图的存在并不存提高任何查询的效率,只是简化了sql语句;

视图一般只用于查询,不对数据进行写操作,所以不应该对视图进行写操作,但是数据库允许这么做。

视图来源于单表

insert操作     成功

delete操作    成功

update操作   成功


视图来源于多表连查

insert操作     失败

delete操作    失败


update操作

修改一张表中数据    成功

修改多张表中数据    失败


视图中不保存真是的数据,而是来源于真实的表中,所以,当真是表中的数据发生变化,视图数据也会发生变化。


事务隔离级别


事务的隔离级别有四种:


read uncommitted  读未提交

read committed   读已提交

repeatable read  可重复读

serializable    可串行化


读未提交


事务的结束表现为两种情况,一种是事务提交,另一种是事务的回滚,读未提交即表现在事务可以读取这两种状态下的数据,从而产生脏读。


什么是脏读?


脏读就是事务读取到了其他事务未提交或未回滚之后的内容,导致最终读取到的数据不存在,这就叫脏读。


我们想想这种情况怎么发生?

时刻 事务A 事务B
t1 begin begin
t2 查询user.name='张三'
t3 修改user.name='李四'
t4 查询到user.name='李四'

t5

由于某些原因导致事务B失败,rollback
t6

commit,此时表中user.name实际为'张三',读到的为'李四'

...

很明显,脏读这种情况不应该出现,所以读未提交这种隔离级别不应该被使用,事实上,也没有数据库使用读未提交的隔离级别。要解决这种情况,产生了另一种隔离级别:读已提交。


读已提交


读已提交的出现就是为了解决读未提交的情况,事务职能读取到其他事务提交后或回滚后的内容,解决了脏读问题,这里应该有掌声👏👏。


不过问题来了,这又产生了新的问题:不可重复读!!!

不可重复读是什么?看下表

时刻 事务A 事务B
t1 begin begin
t2 查询user.name='张三'
t3 修改user.name='李四'
t4 commit

t5

再次查询user.name='李四'
t6

commit

...

两次查询发现查询结果不一样?那么是不是有问题,可能我们看着觉得没错,假设两次分别查询的是银行卡余额,第一次100w,第二次0,我只是查了两次,什么都没干,钱没了,那么你觉得问题大不大? 要不要报警?


在Java中,这就是并发线程的安全问题,所以我们也要避免事务访问期间,其他事务对我们访问的数据进行修改。


根据我们前面学到的内容,我们可以给这条数据加上排他锁,这就解决了这个问题,相信大家已经学会了,此时将产生新的隔离级别:可重复读!


可重复读


可重复读这个隔离级别完美吗?看到这里显然没有结束,所以它一定是不完美的,没错,新的问题又产生了:幻读!


幻读是什么?我们用下面这张表来解读下:

时刻 事务A 事务B
t1 begin begin
t2 查询user表所有数据=2条
t3 添加一个新用户
t4 commit

t5

再次查询useruser表中的数据=3条
t6

commit

...

还以查询银行卡为例,第一次查100w,第二次查0,这是不正常的,因为事务A没有做任何处理。这和不可重复读很相似,但两者也有一定的区别,不可重复读是对数据进行修改,幻读是对数据库进行添加操作,两者都是前后查询到的结果不一致导致的。


我们考虑下幻读应不应该存在? 这种情况可以存在,我认为合法,但是我就需要两次读取到的数据保持一致,该怎么办?给表加排他锁!此时,两次查询结果一致。幻读问题解决!


加了锁,新的隔离级别也就产生了:可串行化!


可串行化


可串行化解决了幻读的问题,但是由于需要给整张表加锁,这样,数据的访问效率就大大降低,现在做开发,谁不使用并发的?所以实际开发中可串行化并不常用,只有在执行一些安全性要求极高的操作时才会使用这一等级。


用一张表来表示他们之间的关系:

隔离等级 产生脏读 产生不可重复读 产生幻读
读未提交 true true true
读已提交 false true true
可重复读 false false true
可串行化 false false false


隔离等级的优先级


和我上面给出的顺序是一致的,优先级由低到高分别是:读未提交-->读已提交-->可重复读-->可串行化。就像道生一,一生二,二生三,三生万物。


数据库使用的隔离级别

oracle和sql server 默认的隔离级别为读已提交。

mysql的 默认隔离级别为可重复读。


MVCC


MVCC是多版本并发控制,是用来实现可重复读的。它解决了并发安全的问题,大大提高了并发执行效率,优于加锁。


MVCC的实现分为三部分:


undolog  ,用于记录一些信息,我们下面会说到;

mysql中的每张表里隐藏的三个字段

row_id,Innodb引擎提供的隐藏主键,表中没有主键时自动创建,从1开始,自增;

DB_trx_id,表示最后操作这条数据的事务的id;

DB_roll_ptr,表示回滚指针,当前事务操作变更数据时,如果失败,需要回滚到之前的那条数据,这里保存的就是操作前数据的地址。

ReadView

目录
相关文章
|
2天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的音乐推荐管理系统
基于Java+Springboot+Vue开发的音乐推荐管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的音乐推荐管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
33 8
基于Java+Springboot+Vue开发的音乐推荐管理系统
|
2天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的母婴商城管理系统
基于Java+Springboot+Vue开发的母婴商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的网上母婴商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
19 7
基于Java+Springboot+Vue开发的母婴商城管理系统
|
3天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的在线摄影预约管理系统
基于Java+Springboot+Vue开发的在线摄影预约管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的在线摄影管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
18 8
基于Java+Springboot+Vue开发的在线摄影预约管理系统
|
3天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的农产品商城管理系统
基于Java+Springboot+Vue开发的农产品商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。 通过学习基于Java的农产品商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
17 5
基于Java+Springboot+Vue开发的农产品商城管理系统
|
1天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的民宿预订管理系统
基于Java+Springboot+Vue开发的民宿预订管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的民宿预订管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
15 2
基于Java+Springboot+Vue开发的民宿预订管理系统
|
1天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的电影订票管理系统
基于Java+Springboot+Vue开发的电影订票管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的电影订票管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
9 1
基于Java+Springboot+Vue开发的电影订票管理系统
|
3天前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的新闻管理系统
基于Java+Springboot+Vue开发的新闻管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的新闻管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
16 3
基于Java+Springboot+Vue开发的新闻管理系统
|
2天前
|
人工智能 前端开发 Java
Java开发工程师转哪个行业比较好?
Java开发工程师转哪个行业比较好?
20 2
|
23小时前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
2天前
|
小程序 前端开发 JavaScript
Java开发工程师转小程序开发的前景如何?
Java开发工程师转小程序开发的前景如何?
12 0