前言
CURD操作应该满足什么要求?:
例如:火车票的售票系统
- 买票过程应该是原子的
- 买票互相不能相互影响
- 买完票应该要永久有效
- 买票前、买票后都要是确定的状态
很显然,单凭CURD操作不能保证上述要求,那如何保证呢?
事务
事务就是一组
DML语句组成,这些语句在逻辑上存在相关性;这组DML语句要么全部成功,要么全部失败,是一个整体。而
MYSQL要提供一种机制,保证我们能够叨叨这样的效果;就是事务
事务主要作用于处理操作量大,复杂度高的数据。
例如:银行要完成转账业务,要在数据库中减少一个用户的余额,增加另一个用户的余额;
对于装张这一业务,很显然它要是原子的,并且要么操作成功、要么操作失败。
这样,需要多条MYSQL语句构成,这些所有操作合起来,就构成了一个事务。
MYSQL数据库中,同一时刻,可能存在大量的请求被包装成事务,向MYSQL服务器发起事务处理请求。如果随意的访问同样表中的数据,不加任何保护的情况下,肯定是有问题的。
所以,一个完整的事务,必须具备以下四种属性:
原子性 : 一个事物中所有的操作,要么全部完成,要么全部不完成。
事务在执行过程中发生错误,会被回滚发哦事物开始前的状态,就像这个事物从来没有执行过一样。
一致性 :
在事务开始之前和结束之后,数据库的完整性没有被破坏。写入的记录必须完全符合预设规则。
隔离性 :数据库允许多个并发事务同时对数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据不一致问题。
事务隔离分为不同的级别:读未提交 、读已提交 、可重复读 、串行化
持久性 :事务处理完之后,对数据的修改就是永久的。
1. 事物支持版本
在MYSQL中,使用Innodb数据库存储引擎的数据库或表才支持事务,MYISAM不支持事务。
show engines语句可以查看数据库存储引擎详细信息。
sql
show engines;
show engines \G

2. 事务提交方式
事务的常见提交方式有两种 :
- 自动提交
- 手动提交
查看事务提交方式 :
sql
show variables like 'autocommit';

set修改MYSQL的自动提交方式 :
sql
set autocommit=0; --- 禁止自动提交
set autocommit=1; --- 允许自动提交

常见事务操作
这里事先创建数据表,来进行相关操作。
sql
create table stu(
id int primary key,
name varchar(10),
age int
);
将事务提交方式设置成自动提交方式。(手动开启、结束事务不受自动提交方式的影响)
1. 事务开始与回滚
开始事务 :
sql
start transaction;
bengin;
创建保存点 :
sql
savepoint save1; --- 创建一个保存点save1
回滚事务 :
sql
rollback save1; --- 回滚到保存点save1;
rollback; --- 回滚到事务开始

如果事务隔离级别是读未提交,如果客户端异常退出,事务会自动回滚到事务开始。
2. 单条SQL语句
上述操作是手动开启和结束一条事务,那我们之前操作的单条SQL语句呢?
单条
SQl语句也会被MYSQL包装成事务;如果事务提交方式为允许自动提交 (
autocommit为on),则在单条语句执行完之后,就会被自动提交。如果事务提交方式为禁止自动提交 (
autocommit为off),那在单条语句执行完之后,不会被自动提交,需要手动提交。
总结 :
手动开始事务(
begin、start transaction),事务必须要通过commit提交;不受是否设置autocommit的影响事务可以手动回滚,同时,当操作异常退出,
MYSQL会自动回滚对于
InnoDB,每一条SQL语句都默认被封装成事务,自动提交。(select有些特殊)如果一个事务意见被提交了,则无法回滚。
隔离级别
MYSQL是一个网络服务,在同一时刻可能被多个客户端进程(线程)进行访问,访问都是以事务方式进行访问。
一个事务,可以由多条SQL语句组成;对于一个事务,就要执行前、执行中、执行后三种状态;(如果执行中出现错误,就会回滚到执行前 )对于用户来说就是:一个事务要么不执行、要么执行成功。(原子性)
但是,所有事物都有个执行过程,那么在多个事物各自执行多个SQL的时候,难免会出现相互影响的情况。(例如:我正在查询,另一个用户在进行插入记录)
数据库中,为了保证事务执行过程中尽量不受干扰,就有一个重要特征:隔离性。
隔离级别 : 允许事务收到不同程度的干扰。
- 读未提交 :所有事务都可以看到其他事务没有提交的执行结果。相当于没有隔离性,会出现很多并发问题(脏读、幻读、不可重复读)。
- 读提交 :一个事务只能看到其他已经提交的事务所做的改变。大多数数据库默认的隔离级别;但是在一个事务执行中,多次
select可能查询到不同的结果。- 不可重复读 :
MYSQL的默认隔离级别,确保同一个事物在执行中,多次读取操作数据,会得到同样的数据。- 串行化 : 事物最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读的问题。
查看/修改隔离级别
查看隔离级别:(全局隔离级别、局部隔离级别)
sql
select @@global.tx_isolation; --- 查看全局隔离级别
select @@session.tx_isolation; --- 查看会话隔离级别
SELECT @@tx_isolation; --- 查看当前隔离级别
设置隔离级别:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ
COMMITTED | REPEATABLE READ | SERIALIZABLE}
sql
set [session | global] transaction isolation level {READ UNCOMMITED | READ COMMITTRD | REPEATABLE READ | SERIALIZABLE}
其中:session表示设置当前会话隔离级别、global表示设置全局隔离级别。
READ UNCOMMITED: 读未提交READ COMMITED: 读已提交REPEATABLE READ: 可重复读SERIALIZABLE: 串行化
这里设置了隔离级别,如果没有变化就需要重新连接mysql客户端
1. 读未提交
读未提交,一个事务在执行过程中能够读到其他事务还没有提交的数据。

这里,一个事务读取到其他事务没有提交的数据,称之为: 脏读
2. 读已提交
读已提交,就是一个事务可以读到其他事务已经提交的数据。

这里,在一条事务中,多次select可能查询到不一样的结果,这种现象称之为 :不可重复读
3. 可重复读
可以重复读,简单来说就是一条事务中,多次select查询到的结果是一样的。
也就是一条事务提交的相关操作,这条事务之后的事务才能看到。
4. 串行化
对所有操作全部加锁,进行串行化,不会有问题,但是只要串行化,效率很低,几乎完全不会被采用。
这里可重复读和串行化就不演示了。
一致性
在数据库系统中,一致性是事务的核心目标之一。它指的是事务执行的结果必须确保数据库从一个一致的状态 (满足所有预定义的业务规则)转变到另一个一致的状态。
这里包含两个层面的含义:
- 逻辑层面的用户责任:一致性的具体内涵是由用户的业务逻辑决定的。例如,"银行账户的总余额必须等于各分账户余额之和"或"商品库存不能为负数"。数据库管理系统(如MySQL)本身无法理解这些具体业务规则,它只提供技术手段。因此,用户首先有责任在代码中编写正确的业务逻辑,以确保事务结束后数据符合这些一致性规则。
- 技术层面的系统保障 :虽然业务规则由用户定义,但数据库系统提供了关键的技术机制,来为"一致性"的实现保驾护航。这主要依赖于事务的其他三个特性------原子性(A)、隔离性(I)和持久性(D),即我们常说的 "通过AID来保证C" 。
- 原子性 是保证一致性的关键。它要求一个事务中的所有操作,要么全部完成,要么全部不执行。如果系统在事务执行中途发生故障,原子性机制(如回滚日志)会撤销该事务对数据库已做的任何部分修改,从而防止数据库停留在因事务中断而产生的不一致、不正确的中间状态。
- 隔离性 保证了并发执行的事务不会相互干扰。它确保多个事务同时执行时,其最终效果与它们串行执行的效果相同。这防止了因为交叉执行而导致的中间状态被其他事务读取,从而引发数据不一致。
- 持久性 确保一旦事务提交,其所做的修改就会永久地保存在数据库中,即使系统发生故障也不会丢失。这保证了一致性的状态能够被可靠地保持下去。
本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws