数据库中的事务
- 数据库事务是数据库系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列完成。一个数据库事务通常包含了一个序列对数据库的读/写操作,它的存在有以下两个目的:
- 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
- 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。
当事务被提交给了DBMS(数据库管理系统),则DBMS(数据库管理系统)需要确保该事务中的所有操作都成功完成且其结果被永久保存在数据库中,如果事务中有的操作没有成功完成,则事务中的所有操作都需要被回滚,回到事务执行前的状态;同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立的运行。
但在现实情况下,失败的风险很高。在一个数据库事务的执行过程中,有可能会遇上事务操作失败、数据库系统/操作系统失败,甚至是存储介质失败等情况。这便需要DBMS对一个执行失败的事务执行恢复操作,将其数据库状态恢复到一致状态(数据的一致性得到保证的状态)。为了实现将数据库状态恢复到一致状态的功能,DBMS通常需要维护事务日志以追踪事务中所有影响数据库数据的操作。
事务的特性:ACID
- 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态,一致状态的含义是数据库中的数据应满足完整性约束。
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
- 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。
SQL
SQL国际标准使用START TRANSACTION开始一个事务(也可以用方言命令BEGIN)。COMMIT语句使事务成功完成。ROLLBACK语句结束事务,放弃从BEGIN TRANSACTION开始的一切变更。若autocommit被START TRANSACTION的使用禁止,在事务结束时autocommit会重新激活。
事务的安全问题&隔离级别
安全问题:
读
- 读脏数据
一个事务读到了另一个事务还未提交的数据。 - 不可重复读
一个事务读到了另一个事已提交的数据,导致前后查询结果不一致。 - 幻读
一个事务读到了另一个事务已提交的插入的数据,导致前后查询结果不一致。
幻读和不可重复读类似,但是不可重复读针对的是update,幻读针对的是insert。
写
-
丢失更新
指一个事务去修改数据库,另一个事务也修改数据库,最后的那个事务,不管是提交还是回滚都会造成前面一个事务的数据更新丢失。
解决丢失更新,通常有两种方法:悲观锁和乐观锁。 -
悲观锁
指事务在一开始就认为丢失更新一定会发生,这是一件很悲观的事情。具体操作步骤如下:
- 所有事务在执行操作前,先查询一次数据,查询语句如下:
select * from student for update ; 后面的for update其实是数据库锁机制 、一种排他锁。 - 哪个事务先执行这个语句,哪个事务就持有了这把锁,可以查询出来数据,后面的事务再执行这条语句,不会有任何数据显示,就只能等着。
- 一直等到前面的那个事务提交数据后,后面的事务数据才会出来,那么才可以往下接着操作。
这相当于上卫生间似的,谁先来谁就进去蹲着,后面来的人都只能等着。只有里面的人出来了,外面的人才能进去。
- 乐观锁
乐观锁是指,从来不会觉得丢失更新会发生。那么它的具体做法是什么呢?
要求程序员在数据库中添加字段,然后在后续更新的时候,对该字段进行判定比对,如果一致才允许更新。例子如下:
- 数据库表中,额外添加了一个version字段,用于记录版本,默认从0开始,只要有针对表中数据进行修改的,那么version就+1。
- 开启A事务,然后开启B事务。
- 先执行数据库表操作。因为以前都没有人修改过。所以是允许A事务修改数据库的,但是修改完毕,就把version的值变成1了。
- B事务,这时候如果想执行修改,那么是不允许修改的。因为B事务以前是没有查询过数据库内容的,所以它认为数据库版本还是0。但是数据库的版本经过A修改,已经是1了。所以这时候不允许修改,要求其重新查询 。
- B重新查询后,将会得到version为1的数据,这份数据就是之前A事务修改的数据了,B在进行修改,也是在A的基础上修改的。所以就不会有丢失更新的情况出现了。
隔离级别
设置事务的隔离级别即可解决以上关于读数据中产生的安全问题,但是相对的,事务的隔离级别越高,系统的效率越低。
事务的隔离级别一共有四种,分别是读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)、串行化(Serializable)。
| 隔离级别 | 读脏数据 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交(Read uncommitted) | × | × | × |
| 读提交(read committed) | √ | × | × |
| 可重复读(repeated read) | √ | √ | × |
| 串行化(Serializable) | √ | √ | √ |
本文深入解析数据库事务的ACID特性,包括原子性、一致性、隔离性和持久性,以及事务在并发操作中可能遇到的安全问题,如读脏数据、不可重复读、幻读和丢失更新等。同时,探讨了如何通过设置不同的隔离级别来解决这些问题,如读未提交、读提交、可重复读和串行化。
1799

被折叠的 条评论
为什么被折叠?



