spring学习笔记---数据库事务并发与锁详解
多事务运行并发问题
在实际应用中,往往是一台(或多台)服务器向无数客户程序提供服务,当服务器查询数据库获取数据时,如果没有采用必要的隔离机制,可能会存在数据库事务的并发问题,下面是一些常见的并发问题分类:
1. 第一类丢失更新:撤销一个事务,其他事务已提交的更新数据覆盖
2. 第二类丢失更新:一个事务覆盖另一个事务已提交的更新数据
3. 脏读:一个事务读到另一个事务未提交的数据
4. 虚读:一个事物读到另一个已提交的新插入数据
5. 不可重复读:事务读到另一个事务已提交的更新数据
下面对这几类并发问题进行详细介绍:
1. 第一类丢失更新
产生过程:两个事务更新同一数据,第一个事务被提交,第一个事务被撤销,会把第一个事务所做的更新也撤销,示意图如下所示: 
2. 第二类丢失更新
产生过程:两个事务各自基于最初的查询结果提交数据,实例流程如下图所示: 
3. 脏读
产生过程:事务二查询到事务一未提交数据,事务二根据此数据进行操作,事务一紧接着撤销数据,导致事务二操纵的是“脏数据”,实例流程如下图所示: 
4.虚读(幻象读)
产生过程:对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围。若对数据精度要求不高,则影响不大,实例流程如下图所示: 
5.不可重复读
产生过程:一个事务查询到另一事务已提交的对数据的更新,实例流程如下图所示:  
与脏读区别:脏读->读取前一事务未提交的脏数据,不可重复读->重新读取了前一事务已提交的数据
数据库系统锁的基本原理
1. 锁的多粒度及自动升级:
- 锁的多粒度按类型可分成下面几类:
- 数据库级锁
 - 表级锁
 - 区域级锁
 - 页面级锁
 - 键值级锁:锁定数据库表中带有索引的一行数据
 - 行级锁
 
 - 对数据的封锁力度越大,往往隔离性越高,但并发性能变差。
 - 对数据施行的锁粒度越高,并发性往往越大,但这意味着在大并发量时锁的数量的急剧增多,由此会带来系统资源的严重负载,影响系统系统。常用的数据库都有事务锁自动升级功能,当系统性能因为锁数量过大而急剧变差时,往往会升级使用更粗粒度的锁来扩大封锁面,减少锁数优化系统资源。
 
2. 锁的类型和兼容性:
共享锁
- 加锁条件:读取数据
 - 解锁条件:读取完毕
 - 兼容性:放置了共享锁的资源,能再放置共享锁和独占锁
 - 并发性:多事务访问相同数据,多锁同时读
 
独占锁(排它锁)
- 加锁条件:修改数据且无其他锁存在
 - 解锁条件:事务结束
 - 兼容性:不与其他锁兼容
 
更新锁
- 加锁条件:update操作
 - 加锁更新步骤: 
- 获得一个共享锁,读数据
 - 升级为独占锁,更新数据
 
 - 兼容性:与共享锁兼容,同一资源最多一把更新锁,能有效避免死锁产生,我们知道,共享锁的兼容性是最好的,加入一个数据同时被两把共享锁锁住,如果这时两条线程并发修改数据,由于共享锁的非排他性,可能会同时出现两把独占锁锁住数据,这样就会产生死锁了,而更新锁排斥独占锁,当出现更新操作时,只能将更新锁本身升级为独占锁,而有效避免死锁产生。
 - 并发性:性能一般,多事务访问,单事务修改。 
- 
3. 死锁产生及其解决方法:
- 产生过程:多事务锁定一个资源->试图去锁定对方已锁定的资源->多事务处于等待对方释放锁资源状态,示意图如下所示: 
 - 防止方法 
- 合理安排表访问顺序
 - 对事务要求不高,允许脏读(不加锁)
 - 错开多事务访问相同资源的时间
 - 使用尽可能低的事务隔离级别
 - 使用短事务(操作尽可能少,时间尽可能短)
 - 将大事务分解成多个小事务顺序执行
 
 
4. 悲观锁与悲观锁
- 悲观锁:显式为数据加锁,常见有如下两种加锁方式 
- 显式指定独占锁:select … for update
 - 在数据库增加表明状态的LOCK字段
 
 - 乐观锁:通过版本控制实现,示意图如下所示: 
通过乐观锁的版本控制,我们能够更好地提高并发事务的性能。 
3. 数据库的事务隔离级别
4种隔离级别从高到低依次为: 
- Serializable:串行化 
- Repeatable Read: 可重复读 
- Read Commited:读已提交的数据 
- Read UnCommited:读未提交的数据
它们对并发事务问题的支持如下图所示 
4. spring的事务传播行为
| 事务传播行为类型 | 说明 | 
|---|---|
| PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个,如果已经存在,则加入到事务中这是最常见的选择。 | 
| PROPAGATION_SUPPORTS | 表示事务对当前方法可有可无,如果有,则按该事务执行,如果当前没有事务,就以非事务方式执行。 | 
| PROPAGATION_MANDATORY | 表示当前方法必须在一个事务中执行,而且如果当前没有事务,就抛出异常。 | 
| PROPAGATION_REQUIRES_NEW | 表示当前方法总是需要独立的新事务,如果当前已存在事务,就会把当前事务挂起,直到新的事务提交或者回滚才恢复执行 | 
| PROPAGATION_NOT_SUPPORTED | 表示当前方法不需要事务,如果当前存在事务,就把当前事务挂起。 | 
| PROPAGATION_NEVER | 表示当前方法不需要事务,而且如果当前存在事务,则抛出异常。 | 
| PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行,如果嵌套事务存在,并且外层事务抛出异常回滚,那么内层事务必须回滚,反之,内层事务并不影响外层事务 | 
spring学习笔记---数据库事务并发与锁详解的更多相关文章
- 多事务运行并发问题spring学习笔记——数据库事务并发与锁详解
		
多事务运行并发问题 在实际应用中,往往是一台(或多台)服务器向无数客户程序提供服务,当服务器查询数据库获取数据时,如果没有采用必要的隔离机制,可能会存在数据库事务的并发问题,下面是一些常见的并发问题分 ...
 - java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock
		
原文:java并发编程 | 锁详解:AQS,Lock,ReentrantLock,ReentrantReadWriteLock 锁 锁是用来控制多个线程访问共享资源的方式,java中可以使用synch ...
 - Linux防火墙iptables学习笔记(三)iptables命令详解和举例[转载]
		
Linux防火墙iptables学习笔记(三)iptables命令详解和举例 2008-10-16 23:45:46 转载 网上看到这个配置讲解得还比较易懂,就转过来了,大家一起看下,希望对您工作能 ...
 - (转)live555学习笔记10-h264 RTP传输详解(2)
		
参考: 1,live555学习笔记10-h264 RTP传输详解(2) http://blog.csdn.net/niu_gao/article/details/6936108 2,H264 sps ...
 - (转)使用Spring注解方式管理事务与传播行为详解
		
http://blog.csdn.net/yerenyuan_pku/article/details/52885041 使用Spring注解方式管理事务 前面讲解了怎么使用@Transactional ...
 - 数据库篇:mysql锁详解
		
前言 sql事务的执行,如果需要锁定数据进行更新操作,则必定离不开锁 共享锁和排他锁 表锁 行锁 Record Lock 间隙锁 Gap Lock 行锁+间隙锁 Next-Key Lock 加锁场景( ...
 - Redis高并发分布式锁详解
		
为什么需要分布式锁 1.为了解决Java共享内存模型带来的线程安全问题,我们可以通过加锁来保证资源访问的单一,如JVM内置锁synchronized,类级别的锁ReentrantLock. 2.但是随 ...
 - 学习笔记--Grunt、安装、图文详解
		
学习笔记--Git安装.图文详解 安装Git成功后,现在安装Gruntjs,官网:http://gruntjs.com/ 一.安装node 参考node.js 安装.图文详解 (最新的node会自动安 ...
 - Java8学习笔记(五)--Stream API详解[转]
		
为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...
 
随机推荐
- 在 Ubuntu上使用 MySQL
			
MySQL 安装配置 https://help.ubuntu.com/12.04/serverguide/mysql.html MySQL Manual http://dev.mysql.com/do ...
 - Canvas学习:globalCompositeOperation详解
			
在默认情况之下,如果在Canvas之中将某个物体(源)绘制在另一个物体(目标)之上,那么浏览器就会简单地把源特体的图像叠放在目标物体图像上面. 简单点讲,在Canvas中,把图像源和目标图像,通过Ca ...
 - vmware 虚拟机导入OVF出现路径错误
			
现状: 需要将原有数据中心的VM虚拟机导出本地OVF模板,然后迁移至新的机房虚拟化环境后从新导入. 问题: 导入OVF时候,先出现错误问题1,修复完成后,出现错误问题2 1. OVF迁移至本地以后,导 ...
 - 基于 Web 的 Go 语言 IDE - Wide 1.5.1 发布!
			
Wide 是一个基于 Web 的 Go 语言 IDE, 其目标不是彻底代替本地 IDE,而是做本地 IDE 很难做到的事情: 分享代码:类似 playground,但支持多文件并提供嵌入方式,在其他网 ...
 - php判断网站收录情况
			
php判断网站收录情况 <?php //检测网页是否被百度收录 function checkBaiduIndex($url){ $url='http://www.baidu.com/s?wd=' ...
 - mac ASP.NET5
			
不写1行代码,在Mac上体验ASP.NET 5的最简单方法 昨天微软发布了ASP.NET 5 beta2(详见ASP.NET 5 Beta2 发布),对ASP.NET 5的好奇心又被激发了. 今天 ...
 - centos7 安装 maven 和ant git 以及 rocketmq 4.2安装过程(安装成功,调用失败)
			
1.maven 安装 wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /et ...
 - Java容器之HashMap源码分析
			
在java的容器框架中,hashMap是最常用的容器之一,下面我们就来深入了解下它的数据结构和实现原理 先看下HashMap的继承结构图 下面针对各个实现类的特点进行下说明:1)HashMap: 它是 ...
 - [翻译] BBCyclingLabel
			
BBCyclingLabel BBCyclingLabel is just like a UILabel but allows you to perform custom animations whe ...
 - Python实例---简单购物车Demo
			
简单购物车Demo # version: python3.2.5 # author: 'FTL1012' # time: 2017/12/7 09:16 product_list = ( ['Java ...