一、数据库事务概述
通过事务,可以将数据库始终保持一致性,同时还可以通过事务机制恢复到某个时间点。
事务:一组逻辑操作单元,使数据可以从一种状态变换到另外一种状态。
事务处理的原则:保证所有事务都作为一个工作单元来执行。
在一个事务中执行多个操作时
- 要么所有的操作都被提交(Commit),那么所有的修改都会被保存下来。
- 要么放弃所有的修改,整个事务回滚(Rollback)到最开始的状态。
事务的ACID特性
原子性
(Atomicity)
原子性表示事务是一个不可分割的工作单位,要么全部成功提交,要么全部失败回滚。一致性
(Consistency)
是指事务执行前后,数据从一个合法性状态
变换到另外一个合法性状态
,这种状态是语义上的,而不是语法上的,跟具体的业务相关。
事务前后的状态必须是合法、合理的状态隔离性
(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,并发执行的各个事务之间不能互相干扰。
一个事务内部的操作及使用的数据对并发
的其他事务是隔离的
保证操作共享数据的时候是安全的
存在隔离级别的概念持久性
(Durability)
事务一旦提交,那么它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其产生任何影响。
持久性是通过事务日志
来保证的。日志包括了重做日志
和回滚日志
。
即使数据库系统崩溃,数据库重启后也能从重做日志中找到没有更新到数据库系统中的数据,重新执行。ACID是事务的四大特性,在这四个特性中,原子性是基础,隔离性是手段,一致性是约束条件,持久性是用户的目的。
事务的状态
二、事务的使用
显式事务
- 使用
START TRANSACTION
或者BEGIN
,显示开启一个事务 START TRANSACTION
相较于BEGIN
的特别之处是,后面可以跟上修饰符。- 进行一系列的
DML
操作 - 提交事务或终止(回滚)事务
回滚事务的时候,可以回滚到最开始,也可以只回滚到某个保存点的状态
隐式事务
在
AutoCommit
开启的时候,每一条DML指令都会当做是一个事务来进行执行,并且执行完后,会隐式的提交事务。
隐式提交事务的情况:
- 数据库定义语言(DDL)
- 隐式使用或修改MySQL数据库中的表
- 事务控制或关于锁定的语句
- 当我们在一个事务还没有提交或者回滚的时候,就又使用
START TRANSACTION
或者BEGIN
语句开启了另外一个事务。那么这时就会隐式提交上一个事务。
- 当我们在一个事务还没有提交或者回滚的时候,就又使用
三、事务隔离级别
数据并发问题
- 脏写
一个事务在另外一个事务执行的过程中,对同一份数据进行了修改 - 脏读
读取了另外一个事务的操作过程中的中间数据 - 不可重复读
在一个事务中,前后两次查询到的数据不统一、不一致。
另外一个事务进行了相关更新操作 幻读
查询前后,数据库表中多出几条记录
另外一个事务执行了插入的操作
隔离级别
脏写>脏读>不可重复读>幻读
SQL标准
中设立了4个隔离级别
:
READ UNCOMMITTED
:读未提交,在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。不能避免脏读、不可重复读、幻读。READ COMMITTED
:读已提交,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可重复读、幻读问题仍然存在。REPEATABLE READ
:可重复读,事务A在读到一条数据之后,此时事务B对该数据进行了修改并提交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读、不可重复读,但幻读问题仍然存在。这是MySQL的默认隔离级别
。SERIALIZABLE
:可串行化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作。所有的并发问题都可以避免,但性能十分低下。能避免脏读、不可重复读和幻读。
隔离级别越高,并发性能就越低
MySQL中,默认的隔离级别是:可重复读
如何设置数据库的隔离级别
有两种方式来修改数据库的隔离级别
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 隔离级别;
#其中,隔离级别格式:
> READ UNCOMMITTED
> READ COMMITTED
> REPEATABLE READ
> SERIALIZABLE
或者
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别'
#其中,隔离级别格式:
> READ-UNCOMMITTED
> READ-COMMITTED
> REPEATABLE-READ
> SERIALIZABLE
- 如果使用global关键字进行修改的话,那么会作用于系统全局
- 但是已经存在会话无效
- 只对执行完语句后,其他新开的会话起作用
- 如果使用session关键,那么就只会在会话范围内影响
- 对当前会话的所有后续事务有效
- 如果在事务之间执行,则对后续的事务有效
在没有修改配置文件的前提下,无论进行了什么样的修改,在重启了MySQL服务器后,隔离级别还是会还原成默认的REPEATABLE-READ
幻读只能通过加锁的方式进行处理
四、课堂相关知识
事务访问数据方式
对于一个事务来说,是通过三个地址空间同数据库进行交互:
- 保存数据库记录的磁盘块空间——物理数据库
- 缓冲区管理器所管理的内存地址空间——数据缓冲区
- 事务的局部地址空间(也是在内存上的)——事务工作区
故障分类、特征和恢复策略
- 事务故障:在运行的过程中由于某些原因,导致事务没能正常运行到终点就夭折、结束了。
- 特征:系统的软件和硬件都能正常运行,内存和磁盘上的数据都未丢失和破坏。
- 恢复策略:回滚相关事务,清除其执行过程中对数据库进行的所有修改,被称为事务撤销(UNDO)
- 系统故障:指系统在运行的过程中,由于某种原因,导致MySQL系统停止运行,致使所有正在运行的事务都以非正常方式终止。
- 特征:数据库缓冲区的信息全部丢失,但存储在外部存储器(磁盘)上的数据未被损坏
- 恢复策略:
- UNDO所有未完成的事务——原子性的要求
- REDO所有已提交的事务——持久性的要求
- 介质故障:是指系统在运行的过程中,由于某种硬件故障,如磁盘损坏、磁头碰撞,或者操作系统的某种潜在错误,致使存储在外存中的数据部分丢失或全部丢失。这类故障比前两类故障的可能性小得多,但破坏了磁盘上的数据,危害最大。
- 特征:存储在外部存储器中的数据被破坏
- 恢复策略:需要装入发生介质故障前某个时刻的数据库副本,并重做(REDO)自备份相应副本数据库之后的所有成功事务,将这些事务已经提交的更新结果重新写入到数据库中去,不需要进行UNDO操作。
- 其他故障:黑客入侵、病毒等其他原因引起的事务非正常结束。
- 特征:属于是人为的恶意破坏
- 恢复策略:通过数据库的安全机制、审计机制等实现对数据的授权访问和保护。