【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)
相关推荐
勿语&10 分钟前
Docker搭建Mysql主从复制
mysql·docker·容器
夏季疯13 分钟前
学习笔记 韩顺平 零基础30天学会Java(2024.8.26)
java·开发语言·数据结构
m0_6530313615 分钟前
如何考取PostgreSQL认证证书?
数据库·postgresql
Ricky 。15 分钟前
C#复习之索引器
数据结构·c#
莲雾flops16 分钟前
集合及数据结构第十二节(下)————哈希表、字符串常量池和练习题
java·开发语言·数据结构·学习·哈希算法·散列表
一心赚狗粮的宇叔17 分钟前
C#编译成32和64位的区别
汇编·学习·c#·jenkins·wpf
软件测试曦曦20 分钟前
Python自动化测试【selenium面试题】
开发语言·自动化测试·软件测试·python·功能测试·selenium·程序人生
还在学习进步22 分钟前
Unable to delete file: .....(路径) signing-config.json无法删除
android·java·安卓
德迅云安全-初启30 分钟前
什么是 SQL 注入,有哪些类型,如何预防?
数据库·sql
fastjson_33 分钟前
jenkins 开启控制台详细日志
开发语言