MySQL中的事物(包含事物的相关知识及操作)

MySqL中的事物

1、什么是事物

  • 事物是一组操作的集合,或者说是一组SQL语句的集合
  • 主要用于处理操作量大的,复杂度高的数据

2、为什么要使用事物

  • 事物要保证成批的SQL语句全部执行,要么全都不执行,这样可以保证数据库的完整性
  • 事物可以用来管理增删改这些改变数据的语句

3、事物的特性(ACID)

  • 原子性:事物是操作的最小单位,事物中的操作要么都执行要么都不执行,不可拆分
  • 一致性:事物的操作数据库中的数据,只会使数据库从一个一致的状态到另一个一致的状态
  • 隔离性:事物的执行之间互不影响(与隔离级别有关)
  • 持久性:事物一旦执行完毕后,对数据库是永久性的改变,不可恢复。

事物的操作

事物默认是开启的可以通过show variables like 'autocommit’SQL语句查看

  1. 事物的创建
  • 隐式事物:事物没有开始和结束的标记,比如一条insert,update,delete。也就是说一条SQL语句默认就有隐式事物。
  • 显式事务:事物有开始和结束的标记。比如在一组sql语句的最前面和最后面添加开始和结束的标记
    #首先关闭自动开启的事物
    set autocommit = 0; 
    #开始事物
    start transaction; #可以不写
    #编写多条SQL语句
    ...
    # 关闭事物提交和回滚都会关闭事物根据情况写一条
    # 提交事物
    commit; # 或者rollback;
    
    

事物中的问题

我们可以试想一下,当有多个事物同时对一个数据进行操作的时候,这些事物的操作有些提交,有些没有提交,这就会导致其他事物操作的数据出现问题。

事物的并发问题

  • 脏读:假设有两个事物,一个事物对一条数据进行了更新操作,没有提交,这时另一个事物又来读取了这条数据,这时候该事物读到的数据就是无效的。

举个例子:小明的老婆每个月都会给小明100块零花钱,但是有一次小明的老婆操作失误给小明打了200块零花钱,小明查看银行卡余额发现多了100。这时候小明读到的数据就是脏数据。(小明的老婆在之后会要回这100块钱)

  • 不可重复读:假设有两事物T1、T2,T1事物读取了一条数据,这时候T2事物修改了该条数据,T1在来读取该条数据就会发现值不相同了。
  • 幻读:假设有两个事物T1、T2,T1从一个表中读取了该表中数据的条数,T2在该表中插入几条数据,这时候T1在来读该表,机会发现数据的条数多了几行。

事物中的并发问题有些向多线程中出现的问题,我们在解决多线程中出现的问题时用到了锁,我们在解决事物并发问题时用到了隔离级别。

事物的隔离级别

MySQL中事物有四种隔离级别

  • read uncommitted:读未提交数据,允许事物读取未提交的数据,三种并发问题都会出现
  • read committed:读已提交数据,只允许事物读取已经被提交的数据,解决脏读
  • repeatable read:可重复读,事物可以多次从一个字段中读取相同的值,在这期间禁止任何其他事物的操作。解决脏读和不可重复读(默认)
  • serializable:串行化,事物可以从一个表中读取相同的行,在这期间禁止插入、更新、删除操作解决所有问题。但是效率低下

四种隔离级别的演示

首先要知道几种常见的事物操作

  • 查看隔离级别
    # mysql版本8.0用
    select @@transaction_isolation;
    # mysql版本5.0用
    select @@tx_isolation;
  • 设置隔离级别
    # 设置当前隔离级别
    set session transaction isolation level 隔离级别;
    # 设置全局隔离级别
    set global transaction isolation level 隔离级别;

开启两个命令行窗口,都登陆MySQL,然后进行隔离级别的演示。使用user表,User表结构如下

Snipaste_2020-01-03_23-34-03.png

  • read uncommitted
    # 步骤一修改隔离级别为read uncommitted
    set session transaction isolation level read uncommitted;

Snipaste_2020-01-03_23-06-32.png

    # 步骤二开启事物,并更新name字段,单不结束事物
    set autocommit = 0;
    update user set name = 'lucy' where id = 1;

Snipaste_2020-01-03_23-38-19.png

    # 步骤三打开另外一个命令行窗口也设置隔离级别为read uncommitted ,查询表中的数据
    set session transaction isolation level read uncommitted;
    select * from user;

clipboard.png

  • read committed

    验证步骤和上个隔离级别相似,也是设置隔离级别后更新数但不提交数据,在另一个窗口也设置隔离级别后查询同一张表,发现name没有更新。解决了脏读。

Snipaste_2020-01-03_23-50-35.png

Snipaste_2020-01-03_23-51-20.png

但是不可重复读的问题还是会出现。我们在其中的一个窗口开启事物查询user表发现字段是mike,然后在另一个窗口中修改name的值为john,并提交,时候在在另一个窗口中查询发现name的值在一个事物中不一样了。

Snipaste_2020-01-03_23-59-06.png
Snipaste_2020-01-03_23-59-47.png

  • repeatable read

    设置隔离级别为repeatable read,先在一个命令行窗口中开启一个事物并查询user表但不结束事物,在另一个表中更改name并提交事物。返回查询user表的窗口再次查询发现name没有改变。

    Snipaste_2020-01-04_20-19-45.png

    Snipaste_2020-01-04_20-18-48.png

  • serializable

    更改隔离级别为serializable,现在一个命令行窗口中开启一个事物,然后查询user表但不提交事物。这时候在另外一张表中开启事物后向user表中插入新的一条数据,发现user表中的数据插入不进去。一直等待另一个窗口中的事物提交。

    Snipaste_2020-01-04_20-37-21.png

    Snipaste_2020-01-04_20-36-41.png

事物中的保存点

语法:savepoint [保存点名] ;

注意:savepoint关键字需要搭配rollback关键字使用

例子:

Snipaste_2020-01-04_21-11-15.png

事物中需要注意的小细节

1.在事物中使用truncate清空表中的数据,使用rollback回滚是无效的

  set autocommit = 0;
  start transaction;
  truncate table user;
  rollback;

Snipaste_2020-01-04_20-58-37.png

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值