【MySQL基础篇】事务

事务简介

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或或撤销操作请求,即这些操作要么同时成功,要么同时失败。

典型事例:银行转账操作

假设张三向李四进行转账操作首先第一步我们应该查询张三用户的余额,如果余额充足,则张三用户余额减少,最后李四用户余额增加

事务的步骤分为:1、开启事务2、回滚事务(把临时修改的数据恢复回去,能够保证如果出现异常,全部操作都会回滚,保证数据的完整性和一致性)3、提交事务

默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。

事务操作

· 查看/设置事务提交方式

SELECT @@autocommit;

SET @@autocommit=0;

· 提交事务

COMMIT;

· 回滚事务

ROLLBACK;

sql 复制代码
#事务操作
#数据准备
create table account(
    id int primary key auto_increment comment '主键ID',
    name varchar(10) comment '姓名',
    money int comment '余额'
)comment '账户表';
insert into account values(null,'张三',2000),
                          (null,'李四',2000);
#转账操作
select @@autocommit;
set @@autocommit=0;
select * from account where name='张三';
#2、将张三账户余额减1000
update account set money =money-1000 where name='张三';
程序执行错误
#3、将李四账户余额增加1000
update account set money =money+1000 where name='李四';
#提交事务
commit;
#回滚事务
rollback;
#恢复数据
update account set money=2000 where name='张三'||name='李四';

方式二:不设置事务的提交方式

· 开启事务

START TRANSACTION 或 BEGIN;

· 提交事务

COMMIT;

· 回滚事务

rollback;

sql 复制代码
#方式二:
start transaction ;
set @@autocommit=1;
select * from account where name='张三';
#2、将张三账户余额减1000
update account set money =money-1000 where name='张三';
程序执行错误...
#3、将李四账户余额增加1000
update account set money =money+1000 where name='李四';
#提交事务
commit;
#回滚事务
rollback;

事务四大特性:ACID

· 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。

· 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。

· 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。

· 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

并发事务问题

|-------|-------------------------------------------------------|
| 问题 | 描述 |
| 脏读 | 一个事务读到另一个事务还没有提交的数据 |
| 不可重复读 | 一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读 |
| 幻读 | 一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了"幻影" |

事务的隔离级别

|---------------------|----|-------|----|
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| Read uncommitted | √ | √ | √ |
| Read committed | × | √ | √ |
| Repeatable Read(默认) | × | × | √ |
| Serializable | × | × | × |

注意:从上到下隔离级别越来越高, Serializable隔离级别最高但性能最差;Read uncommitted隔离级别最低(数据安全性最差),但性能最优。

#查询事务隔离级别

SELECT @@TRANSACTION_ISOLATION;

#设置事务隔离级别

SET SESSION \| GLOBAL TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

sql 复制代码
#查看事物的隔离级别
select @@transaction_isolation;
#设置事务隔离级别
set session transaction isolation level read uncommitted;
#改回默认值
set session transaction isolation level repeatable read ;

脏读演示:(两个客户端演示)

sql 复制代码
#第一个客户端
mysql> use test
Database changed
mysql> set session transaction isolation level read uncommitted
    -> ;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | 张三 |  2000 |
|  2 | 李四 |  2000 |
+----+------+-------+
2 rows in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | 张三 |  2000 |
|  2 | 李四 |  2000 |
+----+------+-------+
2 rows in set (0.00 sec)

mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | 张三 |  1000 |
|  2 | 李四 |  2000 |
+----+------+-------+
sql 复制代码
#第二个客户端
mysql> use test
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> update account set money=money-1000 where name='张三';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

不可重复读:(此时隔离级别为Read committed)

sql 复制代码
#第一个客户端
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | 张三 |  1000 |
|  2 | 李四 |  2000 |
+----+------+-------+
2 rows in set (0.00 sec)

mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | 张三 |  2000 |
|  2 | 李四 |  2000 |
+----+------+-------+
2 rows in set (0.00 sec)
sql 复制代码
#第二个客户端
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> update account set money=money+1000 where name='张三';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

幻读:(此时隔离级别为Repeatable read)

sql 复制代码
#第一个客户端
 start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | 张三 |  2000 |
|  2 | 李四 |  2000 |
+----+------+-------+
2 rows in set (0.00 sec)

mysql> select * from account where id=3;
Empty set (0.00 sec)
 insert into account(id,name,money) values(3,'王小五',2000);
ERROR 1062 (23000): Duplicate entry '3' for key 'account.PRIMARY'
mysql> select * from account;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | 张三 |  2000 |
|  2 | 李四 |  2000 |
|  3 | 王五 |  2000 |
+----+------+-------+
3 rows in set (0.00 sec)
sql 复制代码
#第二个客户端
 start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into account(id,name,money) values(3,'王五',2000);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)
相关推荐
ClickHouseDB2 小时前
ClickHouse Cloud 与 Snowflake 实时性价比对比:CostBench 测试中的 412 倍差距来
运维·数据库·系统架构
第九序言T2 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
m0_639906942 小时前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
时间售卖铺3 小时前
触发器与函数实战:MySQL高效编程秘诀
运维·数据库·mysql·云原生
qetfw3 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
龙亘川3 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
程序喵大人3 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
Raas1004 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
数智园区合作社4 小时前
问数平台怎么把同一个指标锁成一个数
大数据·数据库·人工智能·ai
lbb 小魔仙4 小时前
Windows搭建PaddleOCR+飞书Webhook自动打卡通知机器人:识别、推送与远程触发完整教程
数据库·人工智能·prometheus·时序数据库