一文带你看看事务是个什么东西?

事务概念及特性

Transaction Control Language 事务控制语言

事务:一个或一组SQL语句组成的一个执行单元,这个执行单元要么全部执行,要么全部不执行。如果单元中某条SQL语句执行失败或产生错误,整个单元将会回滚,即所有收到影响的数据将返回到事务开始以前的状态。

show engines 展示数据库支持的存储引擎,但是不是所有的存储引擎都支持事务,其中innodb支持事务,memory 不支持事务。

事务最经典也经常被拿出来说例子就是转账了。

假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。

事务的四大特性

关系性数据库需要遵循ACID规则,具体内容如下:

事务的特性

  1. 原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  2. 一致性(Consistency): 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;(有点像能力守恒的原则)
  3. 隔离性(ISolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;(多个用户操作同一张表的时候互相不干扰)
  4. 持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

事务的创建

事务的类型有两种,一种是隐式事务,一种是显示事务

  • 隐式事务:事务没有明显的开启和结束的标记。例如:insert、update、delete语句。 这些语句是数据库操纵语言(DML语言 data manipulation language) 一旦执行,他们是由自动提交的功能,

  • 显示事务:事务具有明显的开启和结束的标记。前提:必须先设置自动提交功能为禁用。

关于事务的执行和提交 执行就好像是在内存中执行 提交是把数据保存到本地磁盘里面去了。

显示事务的使用步骤:

步骤1:开启事务

set autocommit=0;  #设置自动提交为禁用,并只针对当前会话有效 也就是关闭自动提交的功能

start transaction; # 开启事务(有些地方可以不写 是可选的) 也是只针对当前会话有效

步骤2:编写事务中的SQL语句(select insert update delete# 这里的sql语句只能是DML语言

	语句1;语句2;…

步骤3:结束事务

commit;提交事务

rollback;回滚事务 #(对事物的操作相当于是失效的,这些临时更改的数据其实本质上是保存到了内存当中,还没有到磁盘里面)

注:

  1. 因为DDL没有事务性(create,alter,drop ,truncate),所以DDL不能回滚。 要实现自动回滚。(begin,commit,rollback),则SQL语句中只能包括DML。 (select insert update delete)
  2. 只针对当前会话有效 指的是 创建的一个数据库的连接 (如果像是使用SQL yog 开启一个连接 打开多个查询窗口 这个仍然是一个数据库的连接)

事务的隔离级别

为什么要有

为什么要有事务的隔离级别,产生的原因就是
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:

隔离级别的类型

在这里插入图片描述

什么是

隔离级别:一个事物与其他事物隔离的程度称为隔离级别。

mysql 默认的数据库事务的隔离级别是 REPEATABLE READ(可重复读)

隔离级别描述
READ UNCOMMITTED(读未提交数据)允许事物读取未被其他事物提交的变更。脏读、不可重复度和幻读的问题都会出现
READ COMMITTED(读已提交数据)只允许事物读取已经被其他事物提交的变更。可避免脏读,但不可重复读和幻读问题仍然可能出现
REPEATABLE READ(可重复读)确保事物可以多次从一个字段中读取相同的值。在这个事物持续期间,禁止其他事物对这个字段进行更新。可以避免脏读和不可重复读,但幻读的问题仍然存在
SERILIZABLE(串行化)确保事物可以从一个表中读取相同的行,在这个事物持续期间,禁止其他事物对该表执行插入、更新和删除才操作,三种都可解决,但性能十分低下。

不同的隔离级别,会对应出现的不同问题
在这里插入图片描述

并发问题的产生一定是设计到多个事务的操作

  1. 脏读 :事务1读取了事务2更新但还没有提交的数据,之后,如果事务2回滚,那么事务1读取的内容就是临时且无效的

  2. 不可重复读: 事务1读取某个字段前后不一致,同一个事物多次查询的结果不一样 (读取相同字段,但是前后的数据不一样)

    【刚开始事务1读取出来的是一个值,之后事务2更改了这个字段,事务1再次读取同一个字段的时候,就和之前的值不相同】

  3. 幻读:对于两个事务A、B。A从一个表中读取了一个字段,然后B在该表中插入了一些新的行,如果A再次读取同一个表,就会多出几行。
    【事务1从一个表中读取了一个字段(比如说结果是3行),然后事务2在该表中插入了一些新的行,之后事务1 再次读取同一个表的时候,就会多出几行。(明明之前是3行 怎么又变多了,就好像是产生了幻觉一样】
    和脏读的区别就是 脏读是更新没提交 幻读是插入数据行

具体的解释如下

  1. 如果将数据库设置为第一个隔离级别最低的事务隔离级别 读未提交,三种现象都可能出现。

  2. 读已提交,不会出现脏读 。其他无法避免 但是假设在事务2的执行过程种中 ,刚开始事务1是没有提交的,查询出来的是一个结果,在事务2执行的过程种,事务1进行了提交,事务2如果还涉及到对相同字段进行查询并且这个被事务1更改过,那么就会出现了不可重复读的问题。

  3. 可重复读的事务,可以解决脏读和不可重复读的问题,但是幻读不可以解决。(如果将事务设置成这个隔离级别,然后分别开启两个事务 事务1更改事务2要查询的某些内容,不管在事务2执行的过程中,事务1是否提交了对事物的更改,事务2 前后读取的数据都是一致的) 如果事务2想要读取事务1已经提交更改的数据,那么必须让事务2也提交事务。之再次查询就是最新的数据内容。
    (为什么没有避免幻读的现象,比如说事务1想要将某一个属性全部设置成一样的,之前按照道理来说,应该更改的数据是3行,但是在这个期间 事务1歇了会(这不重要),然后事务2往这个表里面又加入了一条数据并且提交。那么事务1执行update的时候,发现更改了4条数据,这就是一个出现幻读的场景)

  4. 最高级别 串行化 三种事务并发可能导致的问题都可以进行解决,但是效果性能不佳

    如果一个事务在执行,另一个事务也想要执行,是会被阻塞住的,无法进行一些操作,这就好像是一个锁一样,但是性能很低下

事务务隔离机制的实现基于锁机制和并发调度。其中并发调度使用的是MVVC(多版本并发控制),通过保存修改的旧版本信息来支持并发一致性读和回滚等特性。

因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容):,但InnoDB
存储引擎默认使用 **REPEATABLE-READ(可重读)**并不会有任何性能损失。

InnoDB 存储引擎在 分布式事务 的情况下一般会用到**SERIALIZABLE(可串行化)**隔离级别。

查看MySQL默认隔离级别:select @@tx_isolation;
在这里插入图片描述

设置当前MySQL连接的隔离级别: set session transaction isolation level 隔离级别;

设置数据库系统的全局的隔离级别: set global transaction isolation level 隔离级别
因为上面的隔离级别是只针对当前的会话有效的,所以可以设置全局的隔离级别

回滚点

也就是搭配回滚使用

在这里插入图片描述

set autocommit=0;
start transaction;
sql语句1;
savepoint a;#设置回滚点
sql语句2;
rollback to a;#回滚到保存点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值