事务

概念

定义

数据库事务访问并可能更新数据库中各种数据项的一个程序执行单元(unit)

组成

一个数据库事务通常包含对数据库进行的一个操作序列

目的

  1. 为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法
  2. 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作相互干扰

总结:事务的目的就是要提供3种方法:1.失败恢复方法,2.保持一致性的方法,3.操作隔离的方法

  • 成功情况下
    • 能将数据从一种状态变为另一种状态,并能够持久化
  • 异常情况下
    • 能将数据恢复到正常状态
    • 要能保证一致性,包含数据的一致性和约束的一致性
  • 并发情况下
    • 并发的操作之间不能产生相互影响

特性

原子性(Actomicity)

事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行

一致性(Consistency)

事务应确保数据库的状态从一个一致状态转变为另一个一致状态,一致状态的含义时数据库中数据应满足完整性约束

隔离性(Isolation)

多个事务并发执行时,一个事务的执行不应影响其他事务的执行

持久性(Durability)

一个事务一旦提交,他对数据库的修改应该永久保存在数据库中

事务隔离

事务并发导致的异常

回滚丢失(Update Lost)

第一类更新丢失,此种更新丢失时因为回滚的原因,所以也叫回滚丢失

事务A 事务B
查询数据得到初始值10 查询数据得到初始值提交
更新为10+1=11 更新为10+2=12
提交 失败回滚
数据回到初始状态10,导致事务A的更新丢失了,由于回滚导致丢失,所以也叫回滚丢失

覆盖丢失(Second Uupdate Lost)

第二类更新丢失,此种更新丢失时因为更新被其他事务给覆盖了,也可以叫覆盖丢失

事务A 事务B
查询数据得到初始值10 查询数据得到初始值10
更新为10+1=11 更新为10+2=12
提交 提交
最终结果变为12,由于事务B是从10开始计算,并不知道数据已经发生了变化,所以导致事务A的更新结果被覆盖了,所以也叫覆盖更新

脏读

此种异常是因为一个事务读取了另一个事务修改了但是未提交的数据

事务A 事务B
查询数据得到初始值10
更新为10+1=11 查询数据得到数据11
更新数据11+1=12
回滚 提交
数据最终变为12,由于读到的数据11被回滚了,结果是错误的,读取到了脏数据

不可重复读

这种异常时一个事务对同一行数据执行了两次或更多次查询,但是却得到了不同的结果

事务A 事务B
查询数据得到初始值10 查询数据得到初始值10
更新为10+1=11 再次读取数据得到11
在一个事务内两次对统一数据查询,得到的结果是不同的,因此叫做不可重复读

幻读

幻读和不可重复读有点像,只是针对的不是数据的值而是数据的数量

事务A 事务B
查询数据有10条
更新全部数据 插入一条数据
查询结果发现有一条没备更新,比原来多了一条
仿佛全表更新语句不正常,自己出现了幻觉,因此叫幻读

事务隔离级别

由低到高分成以下级别:

读未提交

该隔离级别指即使一个事务的更新语句未提交,但是别的事务可以读到这个改变

读已提交

该隔离级别指一个事务只能看到其他事务的已经提交的更新,看不到未提交的更新,消除了脏读和回滚丢失(第一类更新丢失),这时大多数数据库的默认隔离级别,如Oracle、SqlServer

可重复读

该隔离级别指一个事务中进行两次或多次同样的对数据库内容的查询,得到的结果是一样的,但是不保证对数据条数的查询是一样的,指要存在读改行数据就禁止写,消除了不可重复读和覆盖丢失(第二类更新丢失),这是MySql数据库的默认隔离级别

串行化

事务执行的时候不允许别的事务并行执行,完全串行化的读,指要存在读就禁止写,但是可以同时读,消除了幻读。这是事务隔离的最高级别,虽然最安全最省心,但是效率太低,一般不会用

事务隔离级别与并发异常

各种隔离级别解决哪些并发异常

隔离级别并发异常 回滚丢失 覆盖丢失 脏读 不可重复读 幻读
读未提交 × × × × ×
读已提交 × × ×
可重复读 ×
串行化

MySql操作

常用命令

  • 查询当前数据库版本

    1
    select version();  
  • 查看当前会话事务隔离级别

    1
    SELECT @@session.tx_isolation;  
  • 查询全局事务隔离级别

    1
    SELECT @@global.tx_isolation;  
  • 修改隔离级别(以当前会话为例):

    1
    2
    3
    4
    5
    6
    set @@session.tx_isolation='会话级别'   
    \--会话级别可选值:
    READ-UNCOMMITTED 读未提交
    READ-COMMITTED 读已提交
    REPEATABLE-READ 可重复读
    SERIALIZABLE 串行化
  • 开启事务

    1
    start transaction;  
  • 提交事务

    1
    commit  
  • 回滚

    1
    rollback