mySQL—mySQL事务

mySQL事务确保了数据库操作的原子性、一致性、持久性和隔离性。事务是一组不可分割的操作,如转账示例中,保证了要么全部成功要么全部失败。事务的特性包括原子性,确保操作全部完成或不执行;一致性,保证事务结束时数据库完整性不受破坏;持久性,事务提交后变更永久保存,即使数据库故障;以及隔离性,防止并发事务间的干扰。事务有四种隔离级别:读未提交、读已提交、可重复读和串行化,每种级别有不同的并发问题解决方案。
摘要由CSDN通过智能技术生成


————————————————————————————————

什么是事务?

事务是逻辑上的一组操作,要么都执行,要么都不执行。
事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。

事务就是保证这两个关键操作要么都成功,要么都要失败。

事务定义:

  • 事务是一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务 ,该业务是一个最小的工作单元)
  • 一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。
  • 事务只和DML语句有关,或者说DML语句才有事务。(这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。)

设置事务的目的:

保证多条SQL语句要么同时成功,要么同时失败

事务提交:

要达到目的,需要使用事务,事务不能再分,如下:
在这里插入图片描述

id  money
1    600
2    200
---------------------------------------------
#非事务提交——>提交成功
update action set money = 500 where id = 1;
update action set money = 300 where id = 2;
#非事务提交——>提交失败
update action set money = 500 where id = 1;
update action set money = 300 where id = 2 aa;
-- 如果是同时执行两条SQL语句:
-- 那么其中一条执行成功
-- 但是另一条可以能因为种种原因执行失败
---------------------------------------------
#使用事务——>提交成功
START TRANSACTION;
update action set money = 500 where id = 1;
update action set money = 300 where id = 2;
COMMIT;
#使用事务——>提交失败
START TRANSACTION;
update action set money = 500 where id = 1;
update action set money = 300 where id = 2bb;
COMMIT;

事物的特性

原子性(A)

原子性——>当前事务是不可再分的。事务的原子性确保动作要么全部完成,要么完全不起作用;

提交分类:

  • 没有事务——》直接提交
  • 有事务——》进行两阶段提交

SQL语句先提交到redolog日志池,日志池中存储的是undolog日志,多条SQL语句先后提交到undolog日志当中,检测到undolog日志没有问题后,再执行commit,再操作数据。
如果undolog日志有问题,就不能修改数据。
在这里插入图片描述

一致性(C)

一致性——>事务结束时,数据库完整性不能得到破坏(转账之前两者钱数和为600,转账后也要是600),前边我们实现了原子性、持久性、隔离性都是为了保证一致性。

保证原子性、持久性、隔离性都是为了保证事务的一致性
事务结束时,数据库完整性不能得到破坏(转账之前两者钱数和为600,转账后也要是600)

持久性(I)

持久性——>当我们的事务一旦提交,那么他对数据库的改变就是永久的,即使数据库发生故障也不应该对其有任何影响。

持久性危机

——>假设: SQL提交到undolog日志后,出现未知错误,没有执行commit,此时,由于用户已经提交了SQL语句生成了undolog日志,所以用户会收到成功的消息,但是此时数据库并没有成功修改数据,这就造成了持久性危机。(造成持久性危机是因为两段式提交)

持久性危机如何解决?

——> 在数据提交之前进行刷脏
用户提交SQL语句到undologe日志,执行commit后,将sql语句提交到数据缓冲池,数据池会定时对数据缓冲进行刷脏,执行里面还没有执行的语句。

为什么用数据缓冲池能保证持久性?

因为如果在sql语句生成undolog日志之后出现未知错误,此时用户得到成功消息,数据库未改变,那么等未知错误解决之后,通过定期刷脏,还可以根据undolog日志执行提交的sql语句,这样就解决了持久性危机。

隔离性(D)

隔离性——>并发执行的事务是不能相互干扰的

事务的隔离等级

  • 读未提交 read uncommitted
  • 读已提交 read committed
  • 可重复读 repeatable read
  • 串行化 serializable

(1) 读未提交

  • 事物A和事物B,事物A未提交的数据,事物B可以读取到。
  • 这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别。
  • 三种并发问题都没解决。
    在这里插入图片描述
    如果A读取B后,但是B下一步不执行提交,而是执行回滚,那么就会出现脏读

如何解决脏读??——>读已提交

# 1.创建表:
create table t_user(id int primary key auto_increment,username varchar(255));
# 2.设置读未提交的隔离级别
set global transaction isolation level read uncommitted;
    -- 查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;
-- 注:MySQL8中隔离级别的变量跟之前的版本不一样,
-- 之前是tx_isolation,MySQL8改成了transaction_isolation。

(2)读已提交

  • 只能读取到已经提交的数据
  • 事物A和事物B,事物A提交的数据,事物B才能读取到
  • 这种隔离级别高于读未提交
  • 换句话说,对方事物提交之后的数据,我当前事物才能读取到
  • 这种级别可以避免“脏数据”
  • 这种隔离级别会导致“不可重复读取”
  • Oracle默认隔离级别—>读已提交
    在这里插入图片描述
    可以看出,插入但没有提交,是读不出来的,提交之后才能读出来。

解决了脏读问题,产生了不可重复读问题

# 设置读已提交的隔离级别
set global transaction isolation level read committed;
    -- 查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

(3)可重复读

  • 事务A和事务B,事务A提交之后的数据,事务B读取不到
  • 事务B是可重复读取数据
  • 这种隔离级别高于读已提交
  • 换句话说,对方提交之后的数据,我还是读取不到
  • 这种隔离级别可以避免“不可重复读取”,达到可重复读取
  • MySQL默认级别 ——>可重复读
  • 虽然可以达到可重复读取,但是会导致“幻像读”
    在这里插入图片描述
    可见,无论是删除还是添加,commit后都是成功的,但是另一边却还是读出原来的数据,这就是可重复读,读取的是备份数据不是真正的数据。
    这样会造成幻读
# 设置可重复读的隔离级别
set global transaction isolation level repeatable read;
    -- 查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

(4)串行化

事务A和事务B,事务A在操作数据库时,事务B只能排队等待
这种隔离级别很少使用,吞吐量太低,用户体验差
这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行,而不并发。
在这里插入图片描述

# 设置串行化的隔离级别
set global transaction isolation level serializable;
    -- 查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

隔离级别出现的问题

脏读:

脏读:事务A读取到了事务B修改但是还没有提交的数据
(可以理解为:读取到了undolog日志中的数据,没读取到刷脏后的数据)

如何解决脏读??——>读已提交
在这里插入图片描述

不可重复读:

事务A读取到了事务B提交后的数据,对于数据A来说,读取数据在事务B提交前后的结果是不一样的;
即:对于事务A来说,只能读取事务B已经提交的结果,(假设事务A不知道事务B的存在)所以事务A在 事务B还未提交的时候和在事务B提交之后两个时间点,用同样的sql语句读取到了不同的内容,造成不可重复读。
如何解决不可重复读??——>可重复读

幻读

幻读:当事务A要去查询表当中的数据,与此同时第二个事务对表进行了增删改操作,那么对于事务A来说,查询不到事务B的任何操作。(就跟出现了幻觉一样)

如何解决幻读??——>串行化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值