数据库事务:ACID特性与实战应用

一,初步认识事务

事务是把一组sql语句打包为一个整体,在这组sql的执行过程中,要么全部成功,要么全部失败

举个栗子:我的账户有500元,小帅账户有 200 元,我要转200元给小帅

转账必须做 2 步:1 从我的账户扣200 → 剩300.

2小帅账户加 200 → 剩 400

但如果产生:扣了我的钱,还没给小帅加钱,突然断电!这就是没有事务的后果(灾难)我平白无故少了200,小帅也未收到

有事务时(安全):事务会自动撤销所有操作,回到转账开始前的状态:我还是500,小帅也有200。钱一分没少,操作等于没发生

二,事务的ACID特性

2.1 Atomicity(原子性)

支持事务的数据库中最基本的一个特性,一组sql要么全都执行成功,要么全都不执行,不会出现只执行一半的情况,如果说事务执行过程中出现错误,事务就会回滚到事务开始的状态,就像这个事务没有执行过一样

2.2 Consistency(一致性)

事务执行完成后,保证数据正确并且符合预期

2.3 Isolation(隔离性)

多个事务之间不能相互影响

2.4 Durabbility(持久性)

事务一旦提交,就需要保存在存储介质中,不论数据库是否损坏,都不会影响数据的安全(不能丢失)

事务最终要保证一致性,一致性是由原子性,隔离性和持久性来实现的

三,使用事务

3.1 查看支持事物的存储引擎

要使用事务那么数据库就要支持事务,在MySQL中支持事务的存储引擎是InnoDB,可以通过
show engines; 语句查看

3.2 控制事务语法

复制代码
# 开始⼀个新的事务
START TRANSACTION;
# 或
BEGIN;

# 提交当前事务,并对更改持久化保存
COMMIT;

# 回滚当前事务,取消其更改
ROLLBACK;

无论提交或是回滚,事务都会关闭

举个栗子:

提交时:commit后数据持久化到硬盘

回滚时:rollback后回到事务开始时

3.3 保存点

在事务执行的过程中设置保存点,回滚时指定保存点可以把数据恢复到保存点的状态

1.在要保存的内容后设置:savepoint savepoint1;

2.以 rollback to savepoint1; 回滚到指定地方

3.4 自动/手动提交事务

默认情况下,mysql是自动提交事务,在发生异常时自动回滚,可用show variables like 'autocommit';来查看当前事务是否提交

通过以下语句设置事务为手动提交或自动提交

设置事务自动提交

mysql> SET AUTOCOMMIT=1;
mysql> SET AUTOCOMMIT=ON;

设置事务手动提交

mysql> SET AUTOCOMMIT=0;
mysql> SET AUTOCOMMIT=OFF;

注:只要使⽤ START TRANSACTION 或 BEGIN 开启事务,必须要通过 COMMIT 提交才会持久 化,与是否设置 SET autocommit 无关。 手动提交模式下,不用显示开启事务,执行修改操作后,提交或回滚事务时直接使用commit 或 rollback 。已提交的事务不能回滚

四,事务的隔离性和隔离级别

4.1 什么是隔离性

事务的隔离性:mysql可同时被多个客户访问,为了保证不同客户端在对同条数据修改时出现的互相影响的情况,事务之间就需要互相隔离,也就是隔离性

4.2 隔离级别

在mysql的InnoDB引擎中有四种隔离级别:

read uncommitted 读未提交

read committed 读已提交

repeatable read 可重复读(默认)

serializable 串行化

4.3 查看和设置隔离级别

4.3.1 查看

事务的隔离级别分为全局作用域和会话作用域,查看不同作用域事务的隔离级别有不同的方式

全局作⽤域

SELECT @@GLOBAL.transaction_isolation;

会话作⽤域

SELECT @@SESSION.transaction_isolation;

4.3.2 设置

设置事务的隔离级别和访问模式

通过GLOBAL|SESSION分别指定不同作用域的事务隔离级别

SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level|access_mode;

隔离级别

level: {
REPEATABLE READ # 可重复读
READ COMMITTED # 读已提交
READ UNCOMMITTED # 读未提交
SERIALIZABLE # 串行化

访问模式

access_mode: {
READ WRITE # 表示事务可以对数据进行读写
READ ONLY # 表示事务是只读,不能对数据进行读写

4.4 read uncommitted 读未提交与脏读

由于在读取数据时不做任何限制,所以并发性能很高,容易出现数据安全问题,如:在事务1执行了update语句,但未执行commit时,会在事务2中被读取到,如果事务1在此时回滚,那么事务2刚才读的数据没有任何意义,这个现象叫做脏读。在业务中发生这种问题通常会有很严重的后果,所以应避免使用read committed读未提交这种的隔离级别

4.5 read committed 读已提交和不可重复读

为解决脏读,把事务隔离等级设为read commited,这时可能会产生不可重复读现象,如事务1先对某条事务进行查询,之后事务2对此事务进行修改,事务1在读此事务时,得到事务2修改后的结果,导致事务1前后两次读取不一样,这个现象叫不可重复读

4.6 repeatable read 可重复读与幻读

为解决不可重复读问题,可把事务隔离等级设为repeatable read,这时同一事务任何时候读取数据都是相同的,但是会出现新的问题,如事务1查询了一个区间的记录得到结果集1,事务2向这个区间的间隙中写入了一条记录并提交,事务1在查询这个区间的结果集时会查到事务2写的结果集2,两次结果集不一样,这就是**幻读。**但mysql中的InnoDB存储引擎用了next-key锁解决了大部分幻读问题

4.7 serializable 串行化

进一步提高事务的隔离级别,此时所有事务串行执行,可以解决所有并发中的安全问题

4.8 不同隔离级别的区别

五,JDBC

我们前面提到的都是用mysql来操作数据库,接下来来介绍用程序操作数据库

JDBC是java程序和数据库间的桥梁,包含了一套java定义的用于执行sql语句的接口,使开发者可以编写数据库的程序。

JDBC的主要作用:与数据库建立连接,发送sql语句和处理数据执行结果

JDBC的使用

JDBC使用过程可以概括为:加载数据库厂商的驱动包,建立连接,创建Statement,执行sql,处理结果释放资源和关闭链接

六,小结

这节概念性比较强,大家可以细细研究。如果方便的话请给我点点赞,谢谢啦

相关推荐
HYNuyoah2 小时前
docker网站配置迁移(旧换新)
java·docker·容器
zzginfo2 小时前
JavaScript 中 Array 、 Set 、 WeakSet 区别
开发语言·javascript·ecmascript
ch.ju2 小时前
Java程序设计(第3版)第二章——表达式和算术运算符
java
发发就是发2 小时前
顺序锁(Seqlock)与RCU机制:当读写锁遇上性能瓶颈
java·linux·服务器·开发语言·jvm·驱动开发
我命由我123452 小时前
Android Jetpack Compose - ModalNavigationDrawer、NavigationRail、PullToRefreshBox
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
农村小镇哥2 小时前
PHP递归遍历+MYSQL介绍+MYSQL基本操作
开发语言·mysql·php
llm大模型算法工程师weng2 小时前
Python爬虫实现指南:从入门到实战
开发语言·爬虫·python
东北甜妹2 小时前
Redis Cluster 集群
数据库
Byron__2 小时前
HashSet/LinkedHashSet/TreeSet 原理解析
java