数据库中的事务

2 篇文章 0 订阅

一. 数据库中事务的概述

数据库事务(Database Transaction)是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。也可以理解为用户定义的一个数据库操作序列,这些操作序列要么全部执行,要么都不执行,是一个不和分割的工作单位。在数据库中事务可以是一条SQL语句,也可以是多条SQL语句。

二. 数据库中事务的特性

  1. 原子性(Atomicity):原子性是指事务包含所有的操作要么都成功,要么都回滚,因此事务的操作成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
  2. 一致性(Consistency):一致性是指事务必须是数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。如有两个银行账户A和B,两个账户总共有6000,在这种情况下,无论账户A与B之间如何进行转账,两个账户的总额一直是6000,这就体现了数据库事务的一致性。
  3. 隔离性(Isolation):隔离性是当多个用户并发访问数据库同一个数据表时,数据库为每一个用户开启的事务,不能被其他事务所干扰,多个并发事务之间要相互隔离。要达到隔离性,对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就完成,要么在T1结束之后才开始,这样每个事务就感觉不到其他事务在并发的执行。
  4. 持久性(Durability):持久性是指一个事务一旦被提交了,那么对数据库中数据的改变是永久性的,即便是数据库系统遇到故障的情况下不会丢失提交事务的操作。例如:我们在使用JDBC 操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误!

三数据库事务的实现方式

原子性:通过回滚日志——Undo log,将数据修改之前的状态保存在Undo log中,如果操作未完成需要回滚时,就会恢复到Undo log所保存的状态。

一致性:通过重做日志——Redo log,将数据记录修改后的状态保存到Redo log中。

隔离性:在MySQL中,通过锁对资源进行隔离,包括读操作时的共享锁和写操作时的排他锁。

持久性:通过重做日志——Redo log和回滚日志——Undo log共同完成,它们分别操作完成后的持久性和上一次操作完成后的持久状性。

四. 数据库事务实例讲解

        事务场景:小三账户中有6000元,小舞账户中有8000元,这时小三与小舞在不同前提下相互转账。

        1.不使用数据库事务的前提下小三转账10000元给小舞,此时小舞账户增加10000元,但是小三账户不足10000元,同时账户余额不可为负数,故此时的账户数据为:小三账户为6000元,小舞账户18000元。

        2.在操作1的基础上使用数据库事务的前提下小舞转账1000元给小三,此时两个账户的操作将在同一个事务中,故此时的账户数据为:小三账户为7000元,小舞账户为17000元。

        3.在操作2使用数据库事务的前提下小舞转账36000元给小三,同时小三转账600元给小舞,由于小舞账户中不足36000元,故此次转账操作不成功,操作失败导致事务回滚,数据库返回到事务运行前有效的状态,即此时的账户数据为:小三账户为7000元,小舞账户为17000元。

五 操作过程中事务的实现细节

事务场景为小三账户有1000元,小舞账户中也有1000元,此时小三在情人节那一天转账给小舞520元,此时小三账户为480,同时小舞的账户中为1520元。

实现此事务的细节为:

小三账户有1000元的信息在转账之前先保存在Undo log中,当转账完成后会将当前账户剩余的480元的信息保存在Redo log中。

小舞账户有1000元的信息在受到小三的转账之前也会保存在Undo log中,当收到小三的转账后会将总额1520元信息保存在Redo log中。

在整个事务提交之前为了保证数据的持久性,会刷新Redo log并将其持久化保存到磁盘中,而操作的事务并不需要写入磁盘,只要保存在内存中。

六 实现事务隔离性的锁

在MySQL中对数据表资源的读操作需要加上共享锁,保证在读过程中读线程需要查询的数据资源不会被操作写线程所修改。

在对数据表的资源执行写操作的时候就需要加上排他锁,保证在写过程中写线程修改了并未提交的数据不被读线程所读取。

共享锁和排他锁之间的关系共享锁排他锁
共享锁兼容不兼容
排他锁不兼容不兼容

由共享锁和排他锁的排列组合关系中可知,多个读线程可以同时对资源进行读操作,但是写线程和读线程不能同时操作同一资源,写线程与写线程也不能同时操作同一资源。

上述原理对于高并发的场景显得有些太束手束脚了,所以MySQL在对于使用Innodb引擎的数据表提供了MVCC(多版本并发控制)来保证既满足上述原理有能高效执行并发。

MVCC能够在小三转账给小舞的时候,会对数据库进行写操作,这时候数据库中的数据1000会被加上排他锁,会阻塞查询操作,但是MVCC使得innodb引擎能够利用行数据行隐藏字段(db_row_id,db_trx_id,db_roll_ptr,deleted_bit)从Undo-log中读取想要的信息1000元,这样就能够保证读写操作的并发执行。

行记录隐藏字段:

  1. db_row_id:行ID,用来生成默认聚簇索引(聚簇索引,使得数据按顺序保存在物理磁盘上,将相关的数据保存在一起,可以提高查询速度)。
  2. db_trx_id:事务ID,新事物开始时生成,实例内保证全局唯一。
  3. db_roll_ptr:undo_log指针,指向对应记录当前的undo log。
  4. deleted_bit:删除标记位,删除时设置该字段的信息。

七 数据库事务的隔离级别

数据库的隔离级别指的是事务同事务之间的隔离级别,它们由低到高可以为下列四种:

  1. READ UNCOMMITTED: 未提交读
  2. READ COMMITTED: 已提交读
  3. REPEATABLE READ: 可重复读(Innodb数据库默认隔离级别)
  4. SERIALIZABLE: 串行化

不同事务之间常出现的并发访问问题:

脏读:两个不同的事务A和B,A事务对数据表t1进行了写操作,在A事务未提交的情况下,B事务未提交时可以读取A对数据表t1完成写操作之后的数据。

不可重复读:两个不同事务A和B,A事务对数据表t1进行了写操作,B事务未提交时分别对A事务在提交之前和A事务在提交之后对数据表t1进行读操作,可两次的读结果并不相同。

幻读:两个不同的事务A和B,A事务对数据表t1进行了写操作(一般指插入数据),B事务在未提交且执行当前读时可以查询到A事务提交的对数据表t1提交的写操作记录。

事务隔离级别以及各级下的并发访问问题以及避免方式:

事务隔离级别更新丢失脏读不可重复读幻读
未提交读避免允许允许允许
已提交读避免避免允许允许
可重复读避免避免避免允许
串行化避免避免避免避免

事务控制语句:

//显示地开启一个事务
begin / start transaction 

//提交事务,并使已对数据库进行的所有修改持久化。
commit / commit work

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

//savepoint允许事务创建一个保存点,一个事务中可以有多个savepoint。 
savepoint identifier 

//删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出异常。
release savepoint identifier 

//将事务回滚到某个保存点。
rollback to identifier

//用来设置隔离级别
set transaction

//MySQL事务常见的操作
GEGIN:开始一个事务
ROLLBACK:事务回滚
COMMIT:提交事务

//通过set将MySQL事务设置为自动提交模式
set autocommit = 1 //开启自动提交
set autocommit = 0 //禁止自动提交

八 事务保存点SAVEPOINT

savepoint时在数据库事务处理中实现"子事务",也称为嵌套事务。事务可以回滚到savepoint而不影响savepoint创建之前的变化,不需要放弃整个事务。

savepoint的使用

//声明一个savepoint
savepoint savepoint_name;
//回滚到savepoint
rollback to savepoint_name;

删除savepoint

//删除指定保留点
release savepoint savepoint_name;

保留点savapoint会在事务处理完(执行完rollback或commit)之后自动释放。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值