一、并发问题的产生
多线程/进程同时操作(读/写)同一数据
二、并发问题的种类
- 丢失更新(lost update)
- 第一类更新丢失(回滚丢失): 当2个事务更新相同的数据源,如果第一个事务被提交,而另外一个事务却被撤销,那么会连同第一个事务所做的跟新也被撤销。也就是说第一个事务做的跟新丢失了。
- 第二类更新丢失(覆盖丢失): 第二类更新丢失实在实际应用中经常遇到的并发问题,他和不可重复读本质上是同一类并发问题,通常他被看做不可重复读的特例。当2个或这个多个事务查询同样的记录然后各自基于最初的查询结果更新该行时,会造成第二类丢失更新。因为每个事务都不知道不知道其他事务的存在,最后一个事务对记录做的修改将覆盖其他事务对该记录做的已提交的跟新。
- 脏读(dirty read)
- 脏读(事务没提交,提前读取):脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
- 不可重复读(non-repeatable read)
- 不可重复读(两次读的不一致) :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
- 幻读(phantom read)
- 幻读(发生在其他事务插入或删除后):是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
三、解决方案
- 隔离——使数据局部化(即,使用非共享数据、线程独享),则线程安全
- 识别不变的数据——尽量使用常量
- 加锁——对不得不共享的可变数据进行加锁
四、乐观锁策略——冲突检测
乐观锁策略通常是建立在数据的某种版本标记上。为了检测“丢失更新”,系统核对将要更新的数据的版本标记和共享数据的版本标记,如果两者一样,系统更新数据并更新版本标记,否则,只能放弃本次更新,从头再来。
五、悲观锁策略——冲突避免
读锁(共享锁S):对读锁开放,对写锁封闭(lock table 表名 in share mode)
写锁(排他说X):对读锁和写锁都封闭(select * from 表名 where 条件 for update)
六、死锁——悲观锁会导致死锁
死锁解除方案:死锁超时控制(会导致误伤持锁时间长的)、死锁检测机制
死锁预防方案:
- 强制在开始时就获得所有可能需要的锁,此后就不允许再获得更多的锁。
- 规定每个人获取锁的顺序。例如按字母顺序。
- 当取不到锁的时候,自动牺牲。
- 。。。。
七、事务——处理并发问题的主要工具
ACID属性:原子性(Actomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
使用事务时,要防止锁升级(lock escalation),如果一个事务锁住了一个表中的许多行,则数据库可能无法处理那么多锁,只能将锁升级到锁住整个表。
八、事务隔离级别——事务之间用锁相互隔开
隔离级别就是对事务并发控制的等级。ANSI/ ISO SQL将其分为串行化(SERIALIZABLE)、可重复读(REPEATABLE READ)、读已提交(READ COMMITED)、读未提交(READ UNCOMMITED)四个等级。为了实现隔离级别通常数据库采用锁(Lock)。一般在编程的时候只需要设置隔离等级,至于具体采用什么锁则由数据库来设置。
九、JDBC定义的事务隔离级别
-
Connection.TRANSACTION_NONE说明不支持事务。
-
Connection.TRANSACTION_READ_UNCOMMITTED说明在提交前一个事务可以看到另一个事务的变化。这样脏读、不可重复的读和虚读都是允许的。
-
Connection.TRANSACTION_READ_COMMITTED说明读取未提交的数据是不允许的。这个级别仍然允许不可重复的读和虚读产生。
-
Connection.TRANSACTION_REPEATABLE_READ说明事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现。
-
Connection.TRANSACTION_SERIALIZABLE是最高的事务级别,它防止脏读、不可重复的读和虚读。
十、Spring事务隔离级别的定义和配置
-
TransactionDefinition.ISOLATION_DEFAULT这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
-
TransactionDefinition.ISOLATION_READ_UNCOMMITTED这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读.
-
TransactionDefinition.ISOLATION_READ_COMMITTED保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
-
TransactionDefinition.ISOLATION_REPEATABLE_READ这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
-
TransactionDefinition.ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"isolation="READ_COMMITTED"/>
</tx:attributes>
</tx:advice>
十一、几大数据库的默认事务隔离级别
隔离级别每种数据库都不一样,如果不指定这个属性的话,就是 default
- SQL Server :Read Commited
- Oracle: Read Commited
- MySQL : Repeatable Read
附录一:Oracle的锁
Oracle锁分为两大类:数据锁(DML锁)和字典锁。字典锁包括语法分析锁和DDL锁,有DBMS控制,用户无权控制。
Oracle 5种数据锁:共享锁、排他锁、行级共享锁(RS锁)、行级排他锁(RX锁)、共享行级排他锁(SRX锁)。加锁粒度包括行级和表级。
数据锁相容矩阵:
S X RS RX SRX
S Y N Y N N
X N N N N N
RS Y N Y Y Y
RX N N Y Y N
SRX N N Y N N
一般情况下,Oracle自行加锁,用户也可以通过lock table等语句进行加锁。
Oracle默认情况下,读数据不加锁,而是通过回滚段防止脏读和保证可重复读。
Oracle具有死锁检查功能,周期性检查系统是否有死锁,如果存在死锁,则撤销执行更新操作次数最少的事务。
附录二:JDBC事务隔离级别的测试
@Test
public void testDbTransactionIsolation() throws ClassNotFoundException,
SQLException {
Connection cn = getConnection();
System.out.print("默认的事务隔离级别是:");
printTransactionIsolation(cn);
setTransactionIsolation(cn, Connection.TRANSACTION_NONE,
"TRANSACTION_NONE");
setTransactionIsolation(cn, Connection.TRANSACTION_READ_UNCOMMITTED,
"TRANSACTION_READ_UNCOMMITTED");
setTransactionIsolation(cn, Connection.TRANSACTION_READ_COMMITTED,
"TRANSACTION_READ_COMMITTED");
setTransactionIsolation(cn, Connection.TRANSACTION_REPEATABLE_READ,
"TRANSACTION_REPEATABLE_READ");
setTransactionIsolation(cn, Connection.TRANSACTION_SERIALIZABLE,
"TRANSACTION_SERIALIZABLE");
cn.close();
}
private void setTransactionIsolation(Connection cn, int level,
String levelDiscription) {
try {
System.out.print("设置事务隔离级别为:" + levelDiscription + ",");
cn.setTransactionIsolation(level);
System.out.print("设置成功,");
printTransactionIsolation(cn);
} catch (Exception e) {
System.out.println("设置失败:" + e.getMessage());
}
}
private void printTransactionIsolation(Connection cn) throws SQLException {
int level = cn.getTransactionIsolation();
if (level == Connection.TRANSACTION_NONE)
System.out.println("TRANSACTION_NONE");
else if (level == Connection.TRANSACTION_READ_UNCOMMITTED)
System.out.println("TRANSACTION_READ_UNCOMMITTED");
else if (level == Connection.TRANSACTION_READ_COMMITTED)
System.out.println("TRANSACTION_READ_COMMITTED");
else if (level == Connection.TRANSACTION_REPEATABLE_READ)
System.out.println("TRANSACTION_REPEATABLE_READ");
else if (level == Connection.TRANSACTION_SERIALIZABLE)
System.out.println("TRANSACTION_SERIALIZABLE");
}
分享到:
相关推荐
这个Java实战项目提供了详细的步骤和学习笔记,涵盖了从需求分析、架构设计到代码实现的全过程,是提升Java并发编程和分布式系统设计能力的宝贵资源。通过实际操作,你可以深入了解SSM框架的使用以及在高并发场景下...
SSM实战项目——Java高并发秒杀API是一个深入学习Java后端开发的重要实践,它涵盖了Spring、SpringMVC和MyBatis三大框架的整合应用,以及如何处理高并发下的秒杀场景。在这个项目中,我们将深入理解如何设计并实现一...
3. **Redis 架构模式**: - 单机模式:简单易用,适用于小规模应用。 - 主从复制:数据备份,提高可用性,读写分离。 - Sentinel(哨兵):监控、故障检测和自动故障转移,提升高可用性。 - Cluster(集群):...
笔记首先可能会介绍Oracle的基本架构,包括数据库实例与数据库的区别,以及SGA(System Global Area)和PGA(Program Global Area)等内存结构的作用。学习者将了解到数据存储在数据文件中,控制文件用于记录数据库...
《有道笔记——深入解析源码与工具应用》 在IT行业中,有道笔记作为一款深受用户喜爱的在线笔记工具,其背后的技术架构和源码实现一直是开发者关注的重点。通过分析有道笔记的相关资料,我们可以深入理解其在数据...
这种组合被称为“SSH”架构,为大型企业应用提供了稳定、高效的解决方案。 总结来说,J2EE三大框架——Spring、Hibernate和Struts各自承担着不同的职责,协同工作以提升Java企业级应用的开发效率和质量。掌握这三个...
【EJB容器的实现方式研究学习笔记】 EJB(Enterprise JavaBeans)容器是J2EE(Java 2 Platform, Enterprise ...这种深入研究有助于提升EJB容器的性能和灵活性,对于开发高效、可靠的分布式企业应用具有重要意义。
Spring 5 框架是Java开发中的一个核心组件,尤其在企业级应用中广泛使用。这个框架以其灵活的依赖注入、AOP(面向切面编程)、MVC(模型-视图-控制器)架构模式以及丰富的生态系统而闻名。Spring 5针对Java 8进行了...
笔记可能详述了这些结构的定义、操作及它们在实际问题中的应用。案例可能涉及如何用代码实现这些数据结构,并通过实例展示其优势。 2. **编程语言基础**:如果是编程语言课程,第二章可能深入讲解变量、控制结构...
SSH框架是Java开发中常用的三大框架——Struts、Spring、Hibernate的组合,它们协同工作,为Web应用程序提供了强大的模型-视图-控制器(MVC)架构支持。在本压缩包中,你将找到关于SSH框架在实际应用中与SQL Server...
### 深入解析《ejb学习笔记5》——消息驱动Bean详解 #### 消息驱动Bean概述 消息驱动Bean(MDB,Message Driven Bean)是Enterprise JavaBeans(EJB)框架中的一个重要组成部分,主要用于接收并处理来自消息中间件...
【TiDB 学习笔记】 1、TiDB Server TiDB 是一个分布式 NewSQL 数据库,设计灵感来源于 Google 的 Spanner 和 F1,它具备水平扩展性和强一致性的分布式事务能力。TiDB 将关系型数据库中的表转换为键值对进行存储,...
:“后端——核心服务、APIs与REST接口”这部分内容主要探讨的是构建应用程序时后台系统的设计与实现,包括提供核心业务逻辑的服务、应用程序接口(APIs)以及基于 Representational State Transfer (REST) 架构风格...
其次,深入探讨Qt的模型视图架构,这是一种设计模式,使得数据和显示分离,方便数据管理。书中将展示如何使用QAbstractItemModel、QTableView、QListView等类实现自定义数据模型,并进行数据绑定。 接着,讲解Qt的...
│ │ 9.JAVA并发编程之多线程并发同步业务场景与解决方案.wmv │ │ │ ├─10.微服务架构之Spring Cloud Eureka 场景分析与实战 │ │ 10.微服务架构之Spring Cloud Eureka 场景分析与实战.wmv │ │ │ ├─11....
- **计算机的应用领域**:科学计算、事务处理、过程控制、辅助工程、人工智能和网络应用。 - **计算机系统的组成**:由软件和硬件两大部分构成。 - **计算机硬件的层次结构**:芯片、板卡、设备和网络。 - **奔腾...
在实际面试中,面试官可能会通过设计场景题来考察你的数据库实战能力,比如如何设计一个高并发下的数据库架构,如何解决数据一致性问题,或者在特定场景下如何选择合适的数据库引擎。 通过以上分析,我们可以看出,...
2. **Spring**:Spring作为Java企业级应用的基石,提供了依赖注入、面向切面编程、声明式事务管理等功能。阅读Spring源码可以让我们深入理解IoC(控制反转)和AOP(面向切面编程)的概念,以及Spring如何实现这些...
5. 应用与前景 随着互联网的普及,基于WEB的教学互动平台将更加广泛应用于各类教育机构,打破时间和空间的限制,提高教学效率,推动个性化学习的发展。未来,该系统还可进一步集成人工智能技术,实现智能推荐、...
oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 第一章 Oracle入门 一、 数据库概述 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今五十年前。简单来说是本身可视...