MySQL面试篇章——MySQL事务

MySQL事务

事务概念

一个事务是由一条或者多条对数据库操作的SQL语句所组成的一个不可分割的单元,只有当事务中的所有操作都正常执行完了,整个事务才会被提交给数据库;如果有部分事务处理失败,那么事务就要回退到最初的状态,因此,事务要么全部执行成功,要么全部失败

事务的几个基本概念:

  • 事务是一组SQL语句的执行,要么全部成功,要么全部失败,不能出现部分成功,部分失败的结果。以保证事务执行的原子操作
  • 事务的所有SQL语句全部执行成功,才能提交(commit)事务,把结果写回磁盘上
  • 事务执行过程中,有的SQL出现错误,那么事务必须要回滚(rollback)到最初的状态

例子扩展:张三给刘超转50元,张三有100元,刘超有200元

  • 业务模拟
try {
	begin; # 开启事务

	update account set money = money - 50 where name = 'zhangsan';

	update account set money = money + 50 where name = 'liuchao';

	commit; // 提交事务
} catch () {
	rollback; // 回滚事务	
}

两个转账一定要在一个事务下,一起成功,或者一起失败,不可以部分转账成功,那就会出现钱丢失的现象

  • MySQL最重要是日志,不是数据
  • redo log:重做日志(保证数据库的永久性)
  • undo log:回滚日志(数据恢复到事务开始前的状态)

ACID 特性

每一个事务必须满足下面的4个特性:

  • 原子性(Atomic)

    事务是一个不可分割的整体,事务必须具有原子特性,即当数据修改时,要么全部执行,要么全不执行,那不允许事务部分的完成

  • 一致性(Consistency)

    一个事务执行之前和执行之后,数据库数据必须保持一致性状态。数据库的一致性状态必须由用户来负责,由并发控制机制实现,就拿网上购物来说,你只有让商品出库,并且让商品进入顾客的购物车才能构成一个完成的事务

  • 隔离性(Isolation)

    当两个或者多个事务并发执行时,为了保证数据的安全性,将一个事务内部的操作与其他事务的操作隔离起来,不被其他正在执行的事务所看到,使得并发执行的各个事务之间不能互相影响

  • 持久性(Durability)

    事务完成(commit)以后,DBMS保证它对数据库中的数据的修改是永久性的,即使数据库因为故障出错,也能够回复数据

ACD:是由MySQL的 redo log 和 undo log 机制来保证的

I:隔离性,是由MySQL事务的锁机制来实现保证的

事务并发存在的问题

事务处理不经隔离,并发执行事务时通常会发生以下的问题:

  • 脏读(Dirty Read):一个事务读取到了另一个事务未提交的数据。例如当事务A和事务B并发执行时,当事务A更新后,事务B查询读取到事务A尚未提交的数据,此时事务A回滚,则事务B读取到的数据就是无效的脏数据。(事务B读取到了事务A尚未提交的数据)

例子:一个事务在进行转账50,另一个事务zhangsan在购买理财产品,转账事务执行到zhangsan转账的时候,另一个事务购买了理财,进行读取zhangsan的金钱发现为50,但是最低需要100能买,所以zhangsan买不了,但是转账事务可能出错了,导致回滚,那zhangsan就有100,但是理财产品显示不能购买,这就是脏读(一定要杜绝)

  • 不可重复读(NonRepeatable Read):一个事务的操作导致另一个事务前后两次读取到不同的数据。例如当事务A和事务B并发执行时,当事务B查询读取数据后,事务A更新操作更改事务B查询到的数据,此时事务B再次去读该数据,发现前后两次读的数据不一样。(事务B读取了事务A已提交的数据)

例子:B查看zhangsan的账户,然后A进行zhangsan账户的转账,并且成功提交,然后B进行再次查询,发现已经改变了数据**(不一定完全错,具体得看业务是否允许不可重复读)**

  • 虚读(Phantom Read)幻读:一个事务的操作导致另一个事务前后两次查询的结果数据量不同。例如当事务A和事务B并发执行时,当事务B查询读取数据后,事务A新增或者删除了一条满足事务B查询条件的记录,此时事务B再次查询,发现查询到前一次不存在的记录,或者前一次查询的一些记录不见了。(事务B读取了事务A新增加的数据或者读不到事务A删除的数据)

例子:B首先按照 age = 20 查询有3条,然后A进行添加一条 age = 20 的一条数据,并且提交成功,之后当B再一次进行查询,发现有4条数据,发现查询到了前一次不存在的数据(删除也可以)(同样,不一定完全错,具体得看业务是否需要解决这些问题)

事务的隔离级别

事务隔离级别的实现原理:锁 + MVCC

MySQL支持的四种隔离级别时:

  • TRANSACTION_READ_UNCOMMITTED(未提交读):说明在提交前一个事务可以看到另一个事务的变化。这样读脏数据,不可重复读和虚读都是被允许的

  • TRANSACTION_READ_COMMITTED(已提交读):说明读取未提交的数据时不允许的。这个级别仍然允许不可重复读和虚读产生

  • TRANSACTION_REPEATABLE_READ(可重复读):说明事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现

  • TRANSACTION_SERIALIZABLE(串行化):是最高的事务级别,它防止读脏数据,不可重复读和虚读

隔离级别脏读不可重复读幻读
未提交读
已提交读×
可重复读××
串行化×××

注意:

  • 事务的隔离级别越高,为避免冲突所花费的性能也就越多
  • 在“可重复读”级别下,实际上可以解决部分的虚读问题,但是不能防止update更新产生的虚读问题,要禁止虚读的产生,还是要设置串行化隔离级别

MySQL的事务处理命令

SELECT @@autocommit; # 查看MySQL是否自动提交事务,0表示手动提交事务,1表示自动提交事务

set autocommit = 0; # 设置事务提交方式为手动提交方式

BEGIN; # 开启一个事务

COMMIT; # 提交一个事务

ROLLBACK; # 回滚一个事务到初始的位置

SAVEPOINT point1; # 设置一个名字为point1的保存点

ROLLBACK TO point1; # 事务回滚到保存点point1,而不是回滚到初始状态

SET transcation_isolocation = 'REPEATABLE-READ'; # 设置事务的隔离级别

SELECT @@transcation_isolcation; # 查询事务的隔离级别
  • 22
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzzan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值