MySQL事务的理解及使用

MySQL事务

事务特性

  • 原子性:事务是一个原子操作。在当原子是不可分割的最小元素,其对数据的修改,要么全部成功,要么全部都不成功。
  • 一致性:事务开始到结束的实践段内,数据都必须保持一致状态。
  • 隔离性:数据库提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。
  • 持久性:事务完成后,它对于数据的修改一是永久性的,即使出现系统故障也能够保持。

事务常见问题

  • 脏读(Dirty Reads)

    原因:事务A读取了事务B已经修改但尚未提交的数据。若事务B回滚数据,事务A的数据存在不一致性的问题。

  • 不可重复度(Non-Repeatable Reads)

    原因:事务A第一次读取最初数据,第二次读取事务B已经提交的修改数据。导致两次读取数据不一致。不符合事务的隔离性。

  • 幻读(Phantom Reads)

    原因:事务A根据相同条件第二次查询到事务B提交的新增或删除数据,两次数据结果集不一致。不符合事务的隔离性。

不可重复读的重点是修改,在一次事务中,同样条件下,两次读取发现值不一样了

幻读的重点是新增或删除,在一次事务中,同样条件下,两次读取发现记录数变了

事务的隔离级别

  • READ UNCOMMITTED(未提交读)

    事务中的修改,即使该事务未提交,对其他的事务也是可见的。可以读取到其他事务中的数据,又被成为脏读,在时机数据库事务中,脏读会破坏数据的一致性,对业务的影响大,所以一般不推荐事务使用READ UNCOMMITED隔离级别。

    #事务 1
    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;#设置会话事务隔离级别为 READ UNCOMMITTED
    start transaction;
    select * from xxx;#此时为空,事务未提交
    #事务 2
    start transaction;
    insert into xxx values(x);#未提交事务中,插入数据
    #事务 1
    select * from xxx;#读取到事务2中未提交的数据
    

    image-20201020201351202

  • READ COMMITTED(提交读)

    在提交读级别中,数据库将保证如果一个事务没有完全执行成功(commit完成),事务中的操作对其他事务是不可见的。在该隔离级别下,虽然杜绝了脏读的发生,但是还是会存在着不可重复读及幻读的问题。

    不可重复读发生在事务A读取了一行数据,事务B接着修改或删除了改行数据并提交,当A事务再次读取同一行数据的时候,发现数据已经修改或者被删除。见下方案例

    #事务 1
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;#设置事务隔离级别为READ COMMITTED
    start transaction;#开启事务
    select * from xxx where id=1;#第一次查询
    #事务 2
    update xxx set xxx=newvalue where id=1;#事务 2更新了第一次查询结果的值
    #事务 1
    select * from xxx where id=1;#事务 1第二次查询结果和第一次不一致
    

    image-20201020215144887

    幻读发生在事务A读取了满足条件的一个数据集,事务B此时插入了一行或者多行满足A查询条件的数据并提交,当事务A再次采用相同的条件进行读取时,得到与第一次不同的结果集。见下方案例

    #事务 1
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;#设置事务隔离级别为READ COMMITTED
    start transaction;#开启事务
    select * from xxx;#第一次查询
    
    #事务 2
    start transaction;#开启事务
    insert into xxx values(2);#添加数据
    commit;#提交事务
    
    #事务 1
    select * from xxx;#两次查询结果记录数不一致
    

    image-20201020221623500

  • REPEATABLE READ(可重复读)

    REPEATABLE READ是MySQL的默认隔离级别,它确保同一个事务的多个实例在并发读取数据时,会看到同样的数据。按照该隔离级别的定义,还是会存在幻读的问题。MySQL通过InnoDB存储引擎的多版本并发控制机制(MVVC)解决了部分该问题的场景,但任然存在。

    #事务 1
    #由于REPEATABLE READ是MySQL的默认隔离级别,因此这里就不设置了
    start transaction;#开启事务
    select * from xxx;#第一次查询
    
    #事务 2
    start transaction;#开启事务
    insert into xxx values(2);#添加数据
    commit;#提交事务
    
    #事务 1
    select * from xxx;#两次查询结果记录数不一致
    

    image-20201020231101206

  • SERIALIZABLE(串行化)

    串行化是最严格的隔离级别,通过给事务中的每次读写操作都加锁,保证了不产生任何脏读、不可重复读以及幻读问题,但是随之引入的是大量的读超时以及锁竞争,导致数据库的性能严重下降。

隔离级别脏读不可重复读幻读
READ UNCOMMITTED允许允许允许
READ COMMITTED不允许允许允许
REPEATABLE READ不允许不允许允许
SERIALIZABLE不允许不允许不允许

事务的控制语句

BEGIN/START TRANSACTION 显示开启事务

ROLLBACK 回滚结束用户的事务,并撤销正在进行的所有未提交的修改

COMMIT COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的

SAVEPOINT point 在事务中创建一个保存点point,一个事务可以有多个保存点

RELEASE SAVEPOINT point 删除一个事务的保存点point

ROLLBACK TO point 回滚事务到保存点point

SET TRANSACTION 设置事务的隔离级别

SET AUTOCOMMIT=1/0(on/off) 开启或禁止自动提交

参考链接
https://zhuanlan.zhihu.com/p/85990712
http://blog.itpub.net/31556440/viewspace-2642668/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值