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

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

目录


前言

锁按照粒度分,可以分为两种:

锁按照类型来分,也可分为两类:

悲观锁和乐观锁

版本号机制

CAS

事务

什么是事务?

事务的特性

数据库中的事务

查询命令

关闭命令

开启命令

事务的管理

数据库中的死锁

数据库中的视图

什么是视图?

操作视图:

视图的注意事项

事务隔离级别

读未提交

读已提交

可重复读

可串行化

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

隔离等级的优先级

数据库使用的隔离级别

MVCC

隐藏字段作用

ReadView

结语


前言


常用的数据库有哪些呢?以博主的认知为例,见过最多的就是以下这三种了:


oracle,sql server和mysql


虽然同为数据库,数据结构也是存在着一些细微的差别的,这个我们后面会简单提到,毕竟都是按照sql的统一规范设计的数据库,才有了相同的增删改查功能,所以他们的差别也大不到哪去,这里先提一嘴,这三者的隔离级别不同。


其实本来也想写写sql语句中的一些坑和注意事项的,但想了想,放在数据结构里略微不合适,还是后期专门开一篇讲讲sql语句中踩到的坑和注意事项吧。



锁按照粒度分,可以分为两种:


表锁行锁从名字也不难推测出它们所处的位置。顾名思义,表锁是加在整张表上的,其他的事务将无法在当前事务执行期间访问整张表,行锁是加在单独的某一行上的,其他事务无法在当前事务执行时访问这一行。这也是我们平时所说的线程安全的一部分,只不过是放在数据库上面的。


锁按照类型来分,也可分为两类:


共享锁


排他锁共享锁也叫share锁/s锁,既可以给表加,也可以给行加,因为其共享特性,所以加上了共享锁的数据,允许其他事务同时访问,但是绝对不允许其他事务给他再加排他锁,却依然可以允许其他事务加共享锁。多用于读操作。


排他锁有些地方也叫独占锁/x锁,被加上排他锁的数据,既不允许其他事务再加共享锁,也不允许其他事务再加排他锁,同时,在当前事务执行结束前,其他事务无法访问。多用于写操作。


数据库中,我们经常使用的读写sql语句为:


select....

insert...

delete...

update...

其中,增删改操作默认给操作的行数据加排它锁,select操作默认不加任何锁。


如果需要在查询时加锁,怎么做呢?


查询加共享锁

select......    所有条件之后 + lock in share mode


查询加排它锁

select......    所有条件之后 + for update


因为我们操作的都是行数据,所以基本上都是加行锁,除非使用模糊查询,才会加表锁。这个和数据库的存储引擎有关。以mysql为例,mysql从5.5开始,存储引擎变成InnoDB,默认加行锁,之前的引擎默认加表锁。


悲观锁和乐观锁


悲观锁和乐观锁不同于行锁和表锁,他们只是两种思想。


悲观锁:当多线程或者事务并发执行的时候,事务会悲观的认为,在自己访问数据期间,其他事务一定会同时访问,为了安全着想,事务再访问数据时,立即给这条数据加锁以保证数据是线程安全的。这很像是一个对自身保护过度的人,所以由此可见,悲观锁的效率一定是偏低的。排他锁符合这种特性,所以排他锁都是悲观锁。


乐观锁:和悲观锁相反,数据访问期间,事务很乐观,认为在自己访问期间不会有其他的事务访问,也不会有线程安全问题,所以就不加锁。但在实际中这是不存在的,一定会存在同时访问的情况,这时候,乐观锁会通过其他的机制来保证线程的安全,分别是版本号机制或CAS(compare and swap  比较并交换)。


假设我有一张user表:

id name age
1 张三 20
2 李四 25

两个线程

线程A:查询张三,并修改其年龄为23

1.查询张三数据

2.执行修改

3.提交事务

线程B:查询张三,并修改其年龄为24

1.查询张三数据

2.执行修改

3.提交事务

若是两个线程同时执行,那么A预期的年龄为23,B预期的年龄为24,不管谁先执行,最后得到的数据,只能是符合其中一个的预期,这样就有问题了。


我们用悲观锁的思想来解决,给行数据加锁,就会变成其中一个先执行,执行完之后另一个线程再执行,这当然可以。但我们想要用乐观锁来做,该怎么做呢?需要使用版本号机制。


版本号机制


依然是这张表,只是多了一个版本号,初始值我们给0.

id name age version
1 张三 20 0
2 李四 25 0

两条线程一起执行

线程A:查询张三,并修改其年龄为23

1.查询张三数据,version=0

2.执行修改,age=23,version=0

3.提交事务,需要对比版本号是否等于查询时的版本号0,相等,执行成功,version+1=1.

线程B:查询张三,并修改其年龄为24

1.查询张三数据,version=0

2.执行修改,age=24,version=0

3.提交事务,需要对比版本号等于产巡视的版本号0,此时版本号为1,不等,执行失败。

版本号机制在提交事务的时候会对查询时的版本号进行对比,对比相等,提交,执行成功,对比 不想等,执行失败,事务回滚。


失败后,因为乐观锁中有一个自旋机制,在失败后会重新发起修改,此时线程A已经执行完毕,线程B中心执行,此时version=1,查询到version=1,提交时,只要没有其他线程参与,version仍为1,提交成功,此时version=2。如果有其他的线程参与导致此次修改再次失败,自旋不会无限自旋,它有一个设置时间,可自定义。


CAS


CAS其实在理解了版本号机制之后就很好理解了。

还是这张user表:

id name age
1 张三 20
2 李四 25

还是这两个线程:

线程A:查询张三,并修改其年龄为23

1.查询张三数据

2.执行修改

3.提交事务

线程B:查询张三,并修改其年龄为24

1.查询张三数据

2.执行修改

3.提交事务

俩线程执行完之后,必然会有其中一个的值被覆盖,这就产生了线程安全问题。在版本号机制中,我们比较的是version,但是在CAS中,我们比较的是值本身,如果修改的时候值和查询时的值不一样,那么进行回滚,自旋机制启动,这时候就和version机制是一样的了。


这样一看,版本号机制和CAS是不是很相似呢?只是比较的对象不一样。


现在,你理解这两种机制了么?


在这里给大家留一个问题,悲观锁和乐观锁哪一个用的多?大家可以评论区讨论下并说说具体原因?


事务


什么是事务?


事务是数据库中执行操作的最小执行单元,不可再分,要么全都执行成功,要么全都执行失败。


事务的特性


原子性

事务是数据库的逻辑工作单位,原子性是指事务包含的所有操作要么全部成功,要么全部失败。


一致性

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。一致性与原子性是密切相关的。


隔离性

一个事务的执行不能被其他事务干扰


持久性

一个事务一旦提交,它对数据库中数据的改变就应该是永久性的

在前面,我们已经接触到了一些特性,比如原子性,其他的特性也都是相关的联的,不可能单个存在。

目录
相关文章
|
1月前
|
Java API Maven
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
108 10
|
1月前
|
XML Java 数据库连接
性能提升秘籍:如何高效使用Java连接池管理数据库连接
在Java应用中,数据库连接管理至关重要。随着访问量增加,频繁创建和关闭连接会影响性能。为此,Java连接池技术应运而生,如HikariCP。本文通过代码示例介绍如何引入HikariCP依赖、配置连接池参数及使用连接池高效管理数据库连接,提升系统性能。
59 5
|
29天前
|
监控 Java API
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
|
19天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
6天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
52 13
|
7天前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
29 5
|
11天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
44 10
|
27天前
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
41 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
5天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
40 2
|
14天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。