我们已经知道oracle多版本机制能够提供一致性的答案,而且还有高度的并发性。但是真的就没有其他不好的一面吗?
案例1:
假设有一个资源调度程序(可以用来调度会议室,投影仪等资源),业务规则是:在给定的时间段不能将一种资源分配给多人。这里涉及到资源表(Resources)与资源调度表(Secludes)。
我们一般的实现方式是,先查询某一时间段的某一资源是否已经被分配,如果没有被分配,我们就可以使用。
查看是否被分配SQL语句:
select count(*) from schedules where resource_name = :room_name
and (start_time <= :new_end_time) and (end_time >= :new_start_time)。 ---SQL1
然后插入分配记录(如果得到结果为0)
insert into schedules ( resource_name, start_time, end_time )
values ( p_resource_name, p_start_time, p_end_time ); ---SQL2
但是如果我们让2个人同时预定13:00到14:00期间的投影仪资源,可能都会预定成功。假设一个人是事务A,另外一个人是事务B,在事务A执行SQL1语句的时候,事务B也开始执行SQL1语句(因为oracle里面查询是不会被阻塞的)。那么事务A与事务B查询的结果都是0,于是都可以申请到投影仪资源了。
解决方案:
应该在查询之前先锁定要申请的资源,使得事务A与事务B在执行SQL1与SQL2语句的时候串行。
在执行SQL1语句之前先执行如下SQL语句:
select * from resources where resource_name = :room_name FOR UPDATE; ---SQL3
这样当事务A执行完SQL3之后,事务B执行SQL3的时候就会被阻塞。除非事务B申请资源跟事务A不同。
案例2:热表上超出期望的I/O
在生产环境中在一个大负载条件下,一个查询使用的 I/O 比你在测试或开发系统时观察到的 I/O 要多得多。造成这种现象的原因是:在你测试系统中,由于它是独立的,所以不必撤销事务修改。不过,在生产系统中,读一个给定的块时,可能必须撤销(回滚)多个事务所做的修改,而且每个回滚都可能涉及I/O来获取undo信息并应用于系统。
因为oracle提供多版本机制的原理是,读取数据的时候判断这个数据是不是已经被修改了,如果被修改了就从undo段去获取修改前的数据。如果发现这个修改前的数据还不是想要的数据,继续找更老的数据,直到找到开始执行SQL语句那一刻这个数据的值。
所以在oracle里面如果一个表经常被修改,查询,会发生这样的情况。因为查询的时候,如果被修改的数据越多,需要读取undo段的信息就越长,I/O操作自然也会越多。对于这种热表的查询,最好能够把查询的时间压缩到最短,以便在查询期间,这个数据被其他事务修改的概率最低,从而需要从undo段读取的数据最少,最大限度减少I/O操作的概率。
分享到:
相关推荐
3. **副作用评估**:在执行解锁操作之前,应充分评估可能产生的副作用,并准备好应对措施。 #### 四、最佳实践 1. **定期监控**:建议定期执行锁定对象查询,以便及时发现问题。 2. **优化SQL**:合理设计SQL语句...
至于为何“自己就把积分提上去了”,这可能是指在使用该函数的过程中,用户的积分意外增加,可能是由于某种奖励机制或者是数据库操作的副作用,但这并不是函数本身的功能。 在实际应用中,这样的函数可以集成到业务...
3. **数据库调优**:考虑调整数据库参数,如`_serialize_access`或`_disable_latch_free`, 但要谨慎,因为这些参数修改可能有副作用。 4. **代码审查**:检查PL/SQL代码,确保没有逻辑错误导致不必要的Latch请求。 ...
理解触发器的工作原理,以及在设计数据库逻辑时如何谨慎使用,避免出现副作用。 8. **数据库安全设置**:Oracle 9i提供了用户管理和权限控制机制,包括角色、权限的授予和撤销。了解如何创建和管理用户,设置默认表...
- 隐藏的副作用:由于触发器是在后台自动执行的,可能导致程序逻辑难以理解和调试。 - 数据一致性:过度依赖触发器可能导致数据一致性问题,因为触发器可能在事务中执行,如果触发器失败,可能导致回滚整个事务,而...
- **AFTER** 触发器:在DML语句执行之后触发,可以用来处理事务提交后的副作用。 2. **创建触发器的SQL语法** 使用`CREATE TRIGGER`语句创建触发器,指定数据库名、触发器名、触发时机(BEFORE或AFTER)、触发...
- **Lambda表达式**:1.8引入了Lambda表达式,这是一种简化函数式编程的语法,可以更简洁地表示单行、无副作用的函数。 - **方法引用来代替匿名内部类**:通过方法引用,可以直接引用已有的方法,避免创建匿名内部...
1. Lambda表达式:JDK 8引入了Lambda表达式,这是一种新的语法结构,使得函数式编程风格在Java中成为可能,简化了多参数无副作用的匿名函数的编写,提升了代码的可读性和简洁性。 2. 方法引用和构造器引用:除了...
8. **兼容性**:Byteman支持多种Java虚拟机(JVM)版本,包括OpenJDK和Oracle JDK,并且兼容Java SE和Java EE应用程序。 Byteman的灵活性和易用性使其成为Java开发人员的得力助手,无论是用于常规的故障模拟还是...
- **Lambda表达式**:这是一种简洁的匿名函数表示法,可以简化多参数、无副作用的函数式编程。 - **方法引用和构造器引用**:允许直接引用已有方法或构造器,简化代码并提高效率。 - **默认方法**:在接口中可以定义...
- **forEach()**:对流中的每个元素执行一个操作,通常用于输出或副作用。 - **collect()**:将流转换为其他结构,如收集到集合中。 - **count()**:计算流中元素的数量。 - **findFirst()**:找到流中的第一个...
14. **Lambda表达式(Java 8+)**:这是一种简洁的函数式编程特性,用于表示单行、无副作用的函数,简化了处理集合的操作。 15. **Stream API(Java 8+)**:提供了一种新的处理数据的方式,可以方便地进行过滤、...
4. **代码优化**:讲解如何编写高效、无副作用的Java代码,避免不必要的资源消耗。 5. **并发与多线程**:探讨线程管理和并发控制的最佳实践,减少锁竞争和死锁。 6. **JIT编译器**:解析Just-In-Time(JIT)编译器...
Clojure的数据结构如列表和映射天然支持函数式编程风格,减少了副作用,提高了代码的可读性和可维护性。在JVM上运行的优势让Clojure可以无缝接入Java的库,扩大了其功能范围。 “clojure_master.zip”可能包含的是...
在实际操作中,可能包括药物名称查询、副作用查询、相互作用检查等功能。信息检索系统在这里扮演的角色就是快速、准确地为用户提供所需的数据。 Java在信息检索中的应用主要体现在以下几个方面: 1. **数据存储与...
最后,进行性能调优时,应遵循“测试-修改-测试”的循环,每次优化后都需要验证效果,避免出现意想不到的副作用。并且,了解业务需求和系统负载模式也非常重要,因为不同的业务场景可能需要不同的调优策略。 综上所...
- **变量声明**:避免全局变量,尽量使用局部变量,减少副作用。 - **异常捕获**:具体异常应被具体的catch块捕获,避免使用通用的Exception类型。 - **代码优化**:避免过度优化,但也要注意性能瓶颈,使用适当...
10. **Lambda表达式**:自Java 8起,引入了lambda表达式,使得函数式编程成为可能,简化了多参数和无副作用的函数处理。 11. **模块系统**:Java 9引入了模块系统,有助于提高大型应用的组织和性能。 12. **并发...