MYSQL 事务

一、简介:

MYSQL中,事务其实是一个最小的不可分割的工作单元,事务能够保证一个业务的完整性。

比如我们的银行转账:

	a --> -100update user set money=money-100 where name='a';
​	b--> +100update user set money=money+100 where name='b';

-- 实际的程序中,如果只有一条语句执行成功了,而另外一条没有执行成功?
-- 出现数据前后不一致。
update user set money=money-100 where name='a';
update user set money=money+100 where name='b';
-- 多条sql语句,可能会有要么同时成功、要么同时失败的要求。

-- mysql中如何控制事务?
二、创建例子

mysql 默认是开启事务的(自动提交)。

​ 默认开启事务的作用是什么?

​ --当我们取执行一个sql语句的时候,效果会立即体现出来,不会回滚。

create database bank;
create table user(
	id int primary key,
    name varchar(20),
    money int
);

insert into user values(1,'a',1000);    # 不能回滚
-- 事务回滚:撤销sql语句执行效果,以下语句执行失败
rollback;

-- 设置mysql事务自动提交为 false
set autocommit=0;
-- 上面的操作,关闭了mysql的自动提交(commit)
insert into user values(2,'b',1000);
rollback;    # 回滚一下,零时数据可以撤销
select * from user;    # 表格回到原始状态,第二条insert语句没有提交
							+----+------+-------+
							| id | name | money |
							+----+------+-------+
							|  1 | a    |  1000 |
							+----+------+-------+

insert into user values(2,'b',1000);    # 再一次插入数据
commit;    # 手动提交
rollback;    # 再次撤销将会失败(持久性)
select * from user;    # 表格回到原始状态,第二条insert语句没有提交

-- 自动提交? @@autocommit=1;
-- 手动提交? commit;
-- 事务回滚? rollback;
-- 如果这个时候转账:
-- 事务给我们提供了一个反悔的机会。

set autocommit=1;   # 设置回自动提交
select @@autocommit;    # 显示autocommit状态

begin; 
-- 或者
start transaction; 
-- 都可以帮我们手动开启一个事务

-- 手动开启事务(1)
begin;
update user set money=money-100 where name='a';
update user set money=money+100 where name='b';
rollback;    # 成功

-- 手动开启事务(2)
start transaction;
update user set money=money-100 where name='a';
update user set money=money+100 where name='b';
rollback;    # 成功

-- 手动提交事务(3)
start transaction;
update user set money=money-100 where name='a';
update user set money=money+100 where name='b';
commit;    # 事务开启之后,一旦committ提交后,就不能回滚了
rollback;    # 失败
三、事物的四大特征ACID:

A 原子性:事务最小的单位,不可以再分割。

C 一致性:事务要求,同一事务中的sql语句,必须保证同时成功或同事失败。

I 隔离性:事务1 和 事务2之间是具有隔离性的。

D 持久性:事务一旦结束(commit, rollback),就不可返回。

事务开启:

set autocommit=0;	  # 修改默认提交
begin; 
start transaction;

事务手动提交:

commit;

事务手动回滚:

rollback;

事务的隔离属性:

read uncommitted;    # 读未提交的
read commited;     # 读已经提交的
repeatable read;     # 可以重复读
serializable;     #串行化
1、read uncommitted

如果有 事务a 和 事务b,

a 事务对数据进行操作,再操作的过程中,事务没有被提交,但是 b 可以看见 a 的操作结果。

一个事务可以读取另一个未提交事务的数据。

bank数据库 user库

insert into user values(3, '小明', 1000);
insert into user values(4,'淘宝店', 1000);

–如何查看数据库的隔离级别?

mysql 8.0
-- 系统级别的
select @@global.transaction_isolation;
-- 会话级别的
select @@transaction_isolation;

– mysql 的默认隔离级别为 REPEATABLE-READ

–如何修改隔离级别?

set global transaction isolation level read uncommitted;   # 将系统隔离级别设置为uncommitted

举例:小明买鞋时间

– 转账买鞋子:800块钱

– 小明 -> 成都 ATM

– 淘宝店 -> 广州 ATM

start transaction;
update user set money=money-800 where name='小明';
update user set money=money+800 where name='淘宝店';

– 给淘宝店打电话,说你去查一下,是不是已经到帐了

– 淘宝店在网上发货

–晚上请女朋友请朋友吃好吃的-1800

– 小明在成都rollback

rollback;

– 结账的时候发现钱不够

select * from user;

– 如果两个不同的地方,都在进行操作,如果事务a开启后,他的数据可以被其他事务读取到。

– 这样就会出现(脏读):一个事务读到另一个事务没有提交的数据,就叫做脏读。

– 实际开发是不允许脏读的: 在系统 uncommitted的情况下。

2、read committed:读已经提交的

就是一个事务要等另一个事务提交后才能读取数据。

set global transaction isolation level read committed;
select @@global.transaction_isolation;

举例:报表事件

–bank 数据库 user 表

–小张:银行会计

start transaction;
select * from user;

–小张出去上厕所了,抽烟

–小王:

start transaction;
insert into user values(5,'c',100);
commit;

–小张上完厕所,抽完烟回来了

select avg(money) from user;

–money的平均值不是1000,变少了

–虽然我能读到你提交的数据,但还是会出现问题(由于数据更新导致的,不能重复读取相同的数据。)

–不可重复读现象: read committed

3、repeatable read; # 可以重复读
set global transaction isolation level repeatable read;
select @@global.transaction_isolation;

–在REPEATABLE_READ 隔离级别下又会出现什么问题?

举例:

select * from user;

–张全蛋-成都

start transaction;

–王尼玛-北京

start transaction;

–张全蛋开始插入6号卡,并且自己能看到

insert into user values(6,'d',1000);

–王尼玛看不到6卡,他也试图插入

insert into user values(6,'d',1000)

–因此在王尼玛插入数据时会出现,6卡已经被插入过了

EEROR 1062(23000): Duplicate entry '6' for key 'PRIMARY'

–这种情况叫做幻读!

–事务a操作和事务b同事操作一张表,事务a提交的数据也不能被事务b读到,就可能造成幻读。

4、serializable:串行化
set global transaction isolation level repeatable read;
select @@global.transaction_isolation;
-- 修改隔离级别为串行化

–张全蛋-成都

start transaction;

–王尼玛-北京

start transaction;

–张全蛋

insert into user values(7,'赵铁柱',1000);
commit;    # 已经提交了

–王尼玛

select * from user;

–张全蛋

start transaction;
insert into user values(7,'王小花',1000);     # 会显示插入无法执行
insert into user values(8,'王小花',1000);
-- sql语句被卡住了,语句无法执行
-- 当user 表被另外一个事务操作的时候,其他事务里面的写操作,是不可以进行的。
-- 进入派对状态(串行化),直到王尼玛那边事务结束之后,张全蛋的写入操作才会执行。

–王尼玛

commit;

–张全蛋

-- 王尼玛commit之后,才能执行成功插入
insert into user values(8,'王小花',1000);    # Query OK

–串行化带来的问题是,性能较差!!!

READ-UNCOMMITTED > TEAD-COMMITTED > REPEATABLE-READ > SERIALIZABLE

–隔离级别越高,性能越差

mysql 默认级别是REPEATABLE-READ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 事务是指一组数据库操作,这些操作要么全部执行,要么全部不执行,其目的是保证在并发环境下,数据的一致性和完整性。MySQL 事务具有 ACID 性质,即原子性、一致性、隔离性和持久性。 MySQL 中使用事务需要使用 BEGIN、COMMIT 和 ROLLBACK 语句,其中 BEGIN 表示开启一个事务,COMMIT 表示提交事务,ROLLBACK 表示回滚事务事务的基本语法如下: ``` BEGIN; -- 执行一组数据库操作 COMMIT; -- 提交事务 -- 或者 ROLLBACK; -- 回滚事务 ``` 在 MySQL 中,事务的隔离级别分为四个等级,分别是 Read Uncommitted、Read Committed、Repeatable Read 和 Serializable。隔离级别越高,数据的一致性和完整性越高,但同时也会影响数据库的性能。 MySQL 事务的 ACID 性质有以下含义: 1. 原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部失败回滚,不会只执行其中的一部分操作。 2. 一致性(Consistency):事务执行前后,数据库中的数据必须保持一致性状态,即满足数据库的约束条件和完整性规则。 3. 隔离性(Isolation):事务之间应该是相互隔离的,一个事务的执行不应该被其他事务干扰,保证事务之间的数据相互独立。 4. 持久性(Durability):事务提交后,对数据库的修改应该是永久性的,即使出现系统故障或电源故障,也不应该对数据产生影响。 总之,MySQL 事务是一组数据库操作,具有 ACID 性质,可以通过 BEGIN、COMMIT 和 ROLLBACK 语句来实现,隔离级别越高,数据的一致性和完整性越高,但同时也会影响数据库的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值