数据库事务

139 阅读4分钟

数据库事务的四大特性(ACID)

  1. Atomic 原子性

    • 定义:原子性是指事务是一个不可分割的工作单位。事务中的操作要么都发生,要么都不发生。
    • 实际案例:转账,A加钱,B减钱,要么同时成功,要么同时失败
  2. Consistency 一致性

    • 定义:一致性指的是事务前后数据的完整性必须保持一致
    • 实际案例:加钱和减钱,操作前、后钱的总和要一致
  3. Isolation 隔离性

    • 定义:隔离性指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发事务之间的数据要相互隔离
    • 实际案例:好几个同时人给A转钱,或者好几个人同时给B转钱,多个事务并发执行,并不会影响一致性
  4. Durability 持久性

    • 定义:持久性指的是一个事务一旦被提交了,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对其有任何影响
    • 实际案例:转钱了,数据库突然宕机了,恢复之后,这笔交易还存在

数据库安全性问题

如果不考虑隔离性,会引发以下3种安全性问题:

  • 脏读:A事务读取了B事务修改了的数据但还未提交的数据,当B事务数据回滚,则A事务读到的数据是无效的

    • 例子:A事务中,读取小明的工资,此时财务小红在B事务中,不小心将小明的工资错写为5000,A事务中就读取到5000,小明正高兴,财务小红发现了,马上回滚,小明A事务中读取的数据就为脏读。
  • 不可重复读:在同一个事务中,第一次读取数据,另外读取到了另一个数据已经更新的数据,2次读取的结果不一致

    • 例子:A事务中,读取小明的工资为1000,此时事务还未完成,B事务将小明的工资改为了2000,并提交了事务,A事务再次查询小明工资时,工资就变成了2000,同一个事务中,2次读取结果不一致,导致了不可重复读。
  • 幻读:A事务先读取数据,B事务再提交插入的数据,而导致A事务在后来的查询中,2次查询结果的条数不一致

    • 例子:例如查询工资是1000的员工,目前有10个人,A事务第一次查10条记录,而此时B事务插入了一条记录,工资也是1000,A事务再次查询的时候,就查出了11条记录,2次查询的数据条数不一致。
    • 例子:A事务中,先查询id为1的用户,没有查询到,再插入一条记录,在插入之前,事务2插入了一条id为1的记录,导致A事务插入时,产生主键重复而失败,第一次查询是不存在,插入时却已存在,就像见鬼了一样,这其实是产生了幻读。

而隔离级别就是用来解决以上3种安全性问题!

数据库隔离级别

注意:我们讨论隔离级别的场景,主要是在多个事务并发的情况下,因此,接下来的讲解都围绕事务并发。

  1. READ_UNCOMMITED:允许你读取还未提交的改变了的数据,可导致脏读、幻读、不可重复读
  2. READ_COMMITTED:允许在并发事务已经提交后读取。可防止脏读,但幻读和不可重复读任可发生(Oracle、Sql Server默认使用该隔离级别)
  3. REPEATABLE_READ:对相同字段的多次读取是一致性的,除非数据被事务本身改变,可防止脏读、不可重复读,但幻读仍可发生(MySQL默认使用该隔离级别)
  4. SERIALIZABLE:完全服从ACID的隔离级别,确保不发生脏读、幻读、不可重复读,这在所有的隔离级别中性能是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的

事务的传播行为

主要是为了处理业务层复杂调用时,事务的传播处理。事务的传播行为分为7种,常用为前2种:

  • PROPAGATION_REQUIRED:支持当前事务。如果不存在就新建-个
  • PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务
  • PROPAGATION_MANDATORY:支持当前事务,如果不存在,抛出异常
  • PROPAGATION_REQUIRES NEW:如果有事务存在,挂起当前事务。创建一个新的事务
  • PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果有事务存在,挂起当前事务
  • PROPAGATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常
  • PROPAGATION_NESTED:如果当前事务存在,则嵌套事务执行

一般使用前2种,就是PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS。

  1. 增删改:就是PROPAGATION_REQUIRED,有事务则加入,没有在则创建
  2. 查:PROPAGATION_SUPPORTS,没有事务,那就不使用事务