事务并发问题及处理方式


一、并发中的问题:
二、事务隔离
三、锁的基本原理
1.共享锁
2.排他锁
3.更新锁
一、并发中的问题:
通常为了获得更好的运行性能,各种 数据库 都允许多个事务同时运行,这就是事务并发。当并发的事务访问或修改数据库中相同的数据时,通常需要采取必要的隔离机制,反之会出现各种并发问题。这些并发问题可归纳为以下三种
a.脏读:即一个事务读取到另一事务未提交的更新数据。
b.不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。也就是说,后续读取可以读取到另一事务已提交的更新数据
c.虚读:一个事务读取到另一事务已提交的insert数据。
二、事务
数据库事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
一个数据库事务通常包含了一个序列的对数据库的读/写操作。它的存在包含有以下两个目的:
1. 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
2. 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

数据库事务拥有以下四个特性:ACID
  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

三、事务隔离
解决并发问题的途径是什么?
答案是:采取有效的隔离机制。
怎样实现事务的隔离呢?
隔离机制的实现必须使用锁。

四、锁的基本原理
a.当一个事务访问某个数据库资源时,如果执行的是select语句,必须为资源加上共享锁,如果执行的是insert,update,delete语句,必须为资源加上排他锁,这些锁锁定正在被操作的资源。
b.当第二个事务也要反问相同的资源时,如果执行的select语句,那么也必须为资源加上共享锁;如果执行的是insert,update,或delete语句,也必须为资源加上排他锁。但此时第二个事务并非就立即能为资源加上锁,当第一个事务为资源加的是共享锁时,第二个事务能够为资源加上共享锁,但当第一个事务为资源加的是排他锁时,第二个事务必须等待第一个事务结束,才能为资源加上排他锁。
1.共享锁(s锁)
共享锁用于读取数据操作,它允许其他事务同时读取锁定的资源,但不允许其他事务更新它。
2.排他锁(X锁)
排他锁用于修改数据的场合,他锁定的资源,其他事务部能读取也不能修改。
3.更新锁(U锁)
更新锁在更新操作初始化截断用来锁定可能要被修改的资源,从而避免使用共享锁造成的死锁现象。
这里面有两个步骤:
1) 扫描获取Where条件时,这部分是一个更新查询,此时是一个更新锁。
2) 如果将执行写入更新。此时该锁升级到排他锁。否则,该锁转变成共享锁。

悲观锁
悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制。悲观锁会完成以下功能:锁住读取的记录,防止其它事务读取和更新这些记录。其它事务会一直阻塞,直到这个事务结束.悲观锁是在使用了数据库的事务隔离功能的基础上,独享占用的资源,以此保证读取数据一致性,避免修改丢失。 悲观锁可以使用Repeatable Read事务,它完全满足悲观锁的要求。

乐观锁
乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西。 如果使用乐观锁,那么数据库就必须加版本字段,否则就只能比较所有字段 ,但因为浮点类型不能比较,所以实际上没有版本字段是不可行的。

锁机制能有效地解决并发事务时的各种问题,但是也会影响到并发的性能。
数据库系统提供了4种可选的事务隔离级别:
  1. a.Read Uncommited:读未提交的数据 (脏读)
  2. b.Read commited:读已提交的数据 (不可重复读)
  3. c.Repeateble Read:可重复读 (幻读)
  4. d.Serialable:串行化



你可能感兴趣的:(Java)