数据库事务

事务四大特性(ACID)

1、原子性(Atomicity) :事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。
2、一致性(Consistency) : 事务必须是使数据库从一个一致性状态变到另一个一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
3、隔离性(Isolation) :事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
4、持久性(Durability) :对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

事务的并发问题

<一> 读并发

读上有三类并发问题:脏读、不可重复读、幻读。
脏读
A 事务读取了 B 事务未提交的数据。
A 事务修改了某数据,但还未提交。此时, B 事务读取了该数据。但此时 A 事务又发生了回滚。那么, B 事务读取到的就是个“不存在”的脏数据。
不可重复读
读取了已提交的事务。 A 事务先读取了一个数据,而后 B 事务修改(update 或 delete)了该数据并提交。此时 A 事务再次读取该数据时,该数据已经被修改或不存在。即无法再读到原来相同的数据。
幻读
也叫虚读。读取了已提交的事务。与不可重复读不同的是,发生了插入(insert)操作。A 事务先进行了某一条件的检索操作,而后 B 事务插入了若干数据并提交。这些数据存在符合 A 事务检索条件的数据。此时 A 事务再做相同检索,其检索结果就会与第一次的不同。在第二次读取出了“幻影”。

事务的隔离级别

为了防止读并发问题的发生,标准 SQL 定义了四个隔离级别。**级别由低到高分别为:读取未提交、读取已提交、可重复读、串行化。**随着隔离级别的提高,其防止并发的效果也是
逐步提高,但其系统开销也是逐步提高的,代码的执行效率是逐步降低的。

读取未提交:不防止任何并发问题
读取已提交:防止脏读,可能出现不可重复读与幻读
可重复读:防止脏读与不可重复读,可能出现幻读
串行化:不存在并发问题

MySql 默认的事务隔离级别为可重复读,即防止了脏读与不可重复读,但可能会存在幻
读。 通过 select @@global.tx_isolation;可以查询 MySql 默认的事务隔离级别。

java.sql.Connection接口中定义了五个以 TRANSACTION 开头的常量,代表五个隔离级别(对应标准SQL的四个事务隔离级别,及不支持事务项)

<一> 写并发

第一类丢失更新,也称为回滚丢失更新。 A、 B 事务同时读取某数据,并均做修改。 A 事务先进行了提交,而 B 事务又做回滚。此时, A 事务提交的更新数据丢失。
第二类丢失更新,也称为提交丢失更新。 A、 B 事务同时读取某数据,并均做修改。 A 事务先做了提交,然后 B 事务也做提交。此时, A 事务提交的更新数据会被 B 事务的提交给覆盖。

加锁机制
通过加锁可以解决写并发问题。锁可以分为两类:

乐观锁(Optimistic lock):每次访问数据时,都会乐观的认为其它事务此时肯定不会同时修改该数据。但在真正修改时,会在代码中先判断数据是否已经被其它事务修改过。所以锁是加在代码中的。
悲观锁(Pessimistic lock):每次访问数据时,都会悲观的认为其它事务一定会同时修改该数据。所以,其在访问数据时,在数据库中就会先给数据加锁,以防止其它事务同时修改该数据。所以锁是加在数据库中的。

乐观锁
乐观锁是加在代码中的锁机制,一般充当乐观锁的有两类数据: 版本号与时间戳。它们的工作原理是相同的。
A、 B 事务从 DB 中读取数据时同时会读出一个数据版本号。当 A 事务将修改过的数据写入到 DB 中时,会使版本号增 1。当 B 事务发生回滚或覆盖时,会首先对比自己数据的版本号与 DB 中数据的版本号。若它们相等,则说明 DB 中数据没有发生变化, B 事务可以将数据回滚到原始状态,或将修改写入到 DB 中。若小于 DB 中的版本号,则说明其它事务已经修改过该数据,将抛出异常。

悲观锁

悲观锁是加在 DB 中的锁机制,又分为两种: 写锁,又称为排他锁。当 A 事务对某数据加上排他锁后, A
事务将独占该数据,可对该数据进行读、写操作。但其他事务是不能再为该数据添加任何锁的,直到 A 事务将排他锁解锁,将数据释放。
在 SQL语句中,若要为本次操作(事务)添加排他锁,则可在正常的 SQL 语句最后添 加上 for update 即可。例如: select * from student where age <20 for update
读锁, 又称为共享锁。当 A事务对某数据加上共享锁后,只能对数据进行读操作。但其 他事务也同时可以为该数据添加共享锁,读取该数据。但不能添加写锁,直到所有事务将其共享锁解锁,将数据释放,才可再对数据添加排他锁。
在 SQL 语句中,若要为本次操作(事务)添加共享锁,则可在正常的 SQL 语句最后添加上 lock in share mode 即可。例如: select * from student where age <20 lock in share mode

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值