`
ahuaxuan
  • 浏览: 638106 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

关键字:查询,事务,粒度

阅读更多
[size=medium]/**

*作者:张荣华

*日期:2008-08-22

**/

在那遥远的过去,俺曾经写过一篇关于事务的文章,原文地址见: http://ahuaxuan.iteye.com/blog/95124.文章大意是这样的:在spring+hibernate的场景下,readonly的事务会有特别的优化.因为readonly的事务在提交的时候不会flush 一级缓存中的几个队列(包括,更新队列,插入队列等).看了那篇文章的同学会以为:ok,只读的时候我只要readonly就行了. 不过那篇文章中我并没有考虑到所有的场景,所有再写一篇文章,算是对整个概念(查询操作是否需要事务)的一个完善.

还是老路子,我先描述一下我遇到的一个项目的问题:
1 代码逻辑,下面是一段伪代码
/**
	 * 该方法上加事务,传播途径为required
	 * @param params
	 * @return
	 */
	public List<object> getObject(Map<String, String> params)	 {
		//先从memcached中取得数据
		List<object> o1 = memcachedClient.getFromCache(params);
		
		
		if (o1 == null) {
			ol = ObjectDao.getfromDB(params);
			memcachedClient.putToCache(params, o1);
		}
		
		return o1;
	}


这段代码逻辑非常简单,先从memcached中取数据,取不到就从db取,然后再放到memcached中,无可挑剔(不过要注意我的注释,这个方法上加了required的事务)

就是这段代码,放到tomcat中,我的同事william测出来的结果是,单线程请求(tomcat的thread pool中在同一时间只有一个处理请求的线程被调用):ab  -c 1 –n 1000 http://xxxx.xxx.xxx/xxx
结果是每秒中只能处理20个请求,  我的天啊, 20个,改多线程呢,: ab  -c 100 –n 1000 http://xxxx.xxx.xxx/xxx, 一百个线程请求1000次,晕倒,还是每秒只能处理20多个请求.

估计有些人会觉得很奇怪,这么简单的逻辑怎么会这么慢,我但是也很奇怪,不过突然大脑中一个概念闪过”连接池”(难道这就是传说中的灵感),打开配置一看,果然,连接池配置的连接数只有20.

“每秒钟处理20个请求,20个connection,加了事务”
“每秒钟处理20个请求,20个connection,加了事务”
“每秒钟处理20个请求,20个connection,加了事务”

多想了两遍之后(快分裂了),答案出来了:

在getObject方法上加上事务之后,所有的调用都会新建事务对象,然后放到当前线程中,而新建该事务对象的基础是connection,同时这个connection也会被保存在当前线程中,这样造成的结果是只有等到拥有connection的请求退出事务之后,connection才能重新回到线程池,换句话说,getObject方法是依赖于connection的,getObject能够被调用的次数取决于线程池中线程的数量

于是把线程池开到100,同样运行ab,结果果然好了很多,现在每秒能够处理的请求达到了120+,connection的数量变成原来的5倍,每秒处理的请求数也变成了原来的5倍.

看上去为这个get方法配置事务导致了该方法依赖于db connection是真正的原因,
从我们的逻辑上看该方法确实是不需要事务,但是由于我们的习惯,就顺利成章的给配置了一个,但是这个小小的配置确带来了巨大的影响.

不过有时候,我们以为找到了所有的问题,但是往往有更深层次的问题隐藏其中,比如说多次查询不加事务可能产生幻读的情况(不过如果你的应用对幻读的要求不高的话也没有什么问题).

那么也许我们可以这样结论,只要查询的操作在高性能需求的场景下千万不要加事务,即使是readonly的也不行,其他场景加上吧,不加可能会有些问题,比如说前面提到的幻读(这次我的结论好像底气不足,因为我还没有对它有过特别彻底的研究).

结论下来了,我们看看如何优化,其实在我举的这个场景中,是既可以保证事务,又能提高效率的,就是缩小事务的粒度,如果我在ObjectDao.getfromDB(params);加上事务的话,依赖于connection的只有ObjectDao.getfromDB(params);这个方法了,而这个方法只有o1 == null的时候才会被调用,绝大多数情况下它是不会被调用的.这样既一定程度上保证了事务又提高的程序的速度.

那么我们还可以下一个结论,就是某些场景下缩小我们事务的粒度能够很大程度提高程序的性能.



注明:由于ahuaxuan水平有限,文中不妥之处还望不吝指正,谢谢。



[/size]
分享到:
评论
52 楼 java55 2008-10-07  
ahuaxuan 写道
[size=medium]/**


就是这段代码,放到tomcat中,我的同事william测出来的结果是,单线程请求(tomcat的thread pool中在同一时间只有一个处理请求的线程被调用):ab  -c 1 –n 1000 http://xxxx.xxx.xxx/xxx
结果是每秒中只能处理20个请求,  我的天啊, 20个,改多线程呢,: ab  -c 100 –n 1000 http://xxxx.xxx.xxx/xxx, 一百个线程请求1000次,晕倒,还是每秒只能处理20多个请求


用ab这个命令进行的请求不会去真的执行代码吗?为什么我每次执行的print的信息都不显示出来呢?还有debug也没什么反应呢?
51 楼 anonymity 2008-09-27  
在spring的事务说明中,PROPAGATION_SUPPORTS是当前线程处于事务中则使用事务,否则不使用。不知道这个和楼主所说的线程、事务是否有关系。
50 楼 ahuaxuan 2008-09-24  
pangkc 写道
应该是粗粒度的事务,和 大量的并发,才会造成connection耗尽的情况
如果一个事务,耗时时间几乎不计,那再多的并发也不会造成connection耗尽,不考虑tomcat之类容器的原因,
再粗粒度的事务,没有并发,也不会造成connection耗尽



你的理解是正确的

不过是否需要加锁看业务来决定,其实在本文章的这个场景中,即使在方法上加锁也没有多大影响,因为资源竞争的情况很少.

如果是资源竞争很厉害我们还可以使用双重检查

-----------------------------------------------------------------------------------------

cuiyi.crazy 写道
而你在开贴的结论中提到
ahuaxuan 写道


而这个方法只有o1 == null的时候才会被调用,绝大多数情况下它是不会被调用的.这样既一定程度上保证了事务又提高的程序的速度.

实际上所说的加锁,也是保证不多次读取数据库,而直接从缓存获得的一种保障;
这个connectoin耗尽的根本原因在cache中的命中率不高而导致

不好意思,到现在才仔细看你的回帖,

不过你还是错的,即使缓存命中率100%,还是需要用到connection,所以资源还是会耗尽,你再仔细想想吧.
49 楼 pangkc 2008-09-24  
应该是粗粒度的事务,和 大量的并发,才会造成connection耗尽的情况
如果一个事务,耗时时间几乎不计,那再多的并发也不会造成connection耗尽,不考虑tomcat之类容器的原因,
再粗粒度的事务,没有并发,也不会造成connection耗尽
所以抛开两者任何一个来说都是不客观的
opensessioninview 也是同样的道理,每个session占用的connection时间过长,请求一旦过多,就造成请求延迟的情况
楼主的代码没有错,通常我们遇到的逻辑处理不可能也不应该在底层加锁来解决,试想,是让并发的这些线程在第一次访问的时候都访问数据库好,  还是所有的线程在访问底层代码的时候都加锁好,毫无疑问肯定是前者好
前面那位兄弟提到的FutureTask,可能适合你的特殊的业务逻辑,并不适合所有的开发环境当中
个人理解
48 楼 sunxing007 2008-09-11  
我以前很少研究事物。
楼主建议缩小事务粒度,但是我们使用transaction最初的目的是为了减少原来jdbc事务繁琐的代码,我看了一些书,说要是把事务粒度界定在dao方法上,无法保证多个dao方法的事务完整性,放在service上的话,因为事物是persistance层的,显然有点破坏了分层。
那该怎么办呢?
47 楼 cuiyi.crazy 2008-09-06  
nihongye 写道

屏蔽网络的影响,看机器在多少个并发的时候达到最好的性能,这个并发数应该就是连接数了。

这个是performance tuning用的,不是解决问题用的吧
46 楼 cuiyi.crazy 2008-09-06  
ahuaxuan 写道

ps:关于并发问题,我已经在第三页做了较为详细的阐述,看贴要仔细,思考要深入,发言要谨慎


实在不好意思,现在才完全读完第3页、第4页,多想了一些东西,然后也做了小程序来验证....
读技术帖子向来很慢,见笑了....     解决问题是一回事,更合理又是一回事...
之前有跑题,收住

但是事务仅仅发生在有事务资源参与的部分,貌似不应该太多次调用到getfromDB方法,缓存的命中率是否也有一定问题?

而你在开贴的结论中提到
ahuaxuan 写道

而这个方法只有o1 == null的时候才会被调用,绝大多数情况下它是不会被调用的.这样既一定程度上保证了事务又提高的程序的速度.

实际上所说的加锁,也是保证不多次读取数据库,而直接从缓存获得的一种保障;
这个connectoin耗尽的根本原因在cache中的命中率不高而导致

ahuaxuan 写道

而新建该事务对象的基础是connection,同时这个connection也会被保存在当前线程中,这样造成的结果是只有等到拥有connection的请求退出事务之后,connection才能重新回到线程池,换句话说,getObject方法是依赖于connection的,getObject能够被调用的次数取决于线程池中线程的数量

这个分析,相当好,也是我多次读这个文章中一再受益的
45 楼 nihongye 2008-09-04  
问的好,答案你也知道,我就不重复一些yy废话了。实际点要看具体的测试,毕竟不是常说数据库与代码的执行不是一个数量级吗。
44 楼 downpour 2008-09-03  
nihongye 写道
downpour 写道
nihongye 写道
按我说就把容器的output buffer设置大,然后用filter保证connection open in view.
请求到页面渲染的时间是固定的,只要保证请求的处理时间内能有空余的connection就ok了,这个connectin的数量应该不需要很大。反而事务粒度设置很小,每个请求假设要拿100次连接,连接池的锁竞争开销不小。
(这个方法纯属猜测,因为servlet规范没说清楚dochain后的执行与完成响应输出之间的先后关系)


对于大型网站来说,并发的request可能上百,如果connection都在filter里面打开并维持到render结束,连接池岂不是要设置很多connection数才够?

屏蔽网络的影响,看机器在多少个并发的时候达到最好的性能,这个并发数应该就是连接数了。



问题是,一个数据库可能要被很多个应用使用,按照你这种方式来确定连接数的话,恐怕就数据库层面很难权衡。为什么允许你某个应用有那么多个连接数来连我?

我碰到的实际情况是,有一些客户根本对数据库连接数相当关心,一个应用顶多给你50个连接,请问此时你如何解决这个问题。
43 楼 nihongye 2008-09-03  
downpour 写道
nihongye 写道
按我说就把容器的output buffer设置大,然后用filter保证connection open in view.
请求到页面渲染的时间是固定的,只要保证请求的处理时间内能有空余的connection就ok了,这个connectin的数量应该不需要很大。反而事务粒度设置很小,每个请求假设要拿100次连接,连接池的锁竞争开销不小。
(这个方法纯属猜测,因为servlet规范没说清楚dochain后的执行与完成响应输出之间的先后关系)


对于大型网站来说,并发的request可能上百,如果connection都在filter里面打开并维持到render结束,连接池岂不是要设置很多connection数才够?

屏蔽网络的影响,看机器在多少个并发的时候达到最好的性能,这个并发数应该就是连接数了。

42 楼 downpour 2008-09-03  
nihongye 写道
按我说就把容器的output buffer设置大,然后用filter保证connection open in view.
请求到页面渲染的时间是固定的,只要保证请求的处理时间内能有空余的connection就ok了,这个connectin的数量应该不需要很大。反而事务粒度设置很小,每个请求假设要拿100次连接,连接池的锁竞争开销不小。
(这个方法纯属猜测,因为servlet规范没说清楚dochain后的执行与完成响应输出之间的先后关系)


对于大型网站来说,并发的request可能上百,如果connection都在filter里面打开并维持到render结束,连接池岂不是要设置很多connection数才够?
41 楼 nihongye 2008-09-03  
按我说就把容器的output buffer设置大,然后用filter保证connection open in view.
请求到页面渲染的时间是固定的,只要保证请求的处理时间内能有空余的connection就ok了,这个connectin的数量应该不需要很大。反而事务粒度设置很小,每个请求假设要拿100次连接,连接池的锁竞争开销不小。
(这个方法纯属猜测,因为servlet规范没说清楚dochain后的执行与完成响应输出之间的先后关系)
40 楼 ahuaxuan 2008-09-03  
cuiyi.crazy 写道

但是我觉得楼主是在无视这个并发问题下讨论事务,就是说楼主有新的关注点--事务,我现在读第3页,先发个帖子,接着读

你这个回答简直太搞笑了,“我有新的关注点--事务”,难道你没有看原文吗??????????
我原来的关注点就是事务,被人引导并发上去了,你看不出来吗??

本来我以为这种问题挺简单的,发了文章之后我都后悔,觉得太简单了,没想到还有这么多人到现在还是搞不清楚

----------------------------------------------------------------------
我在第四页的回帖已经说了很清楚了,即使加上并发connection还是会被耗尽的,因为并发不是connection耗尽的原因,为什么怎么说都不明白呢

ps:关于并发问题,我已经在第三页做了较为详细的阐述,看贴要仔细,思考要深入,发言要谨慎
39 楼 cuiyi.crazy 2008-09-03  
ahuaxuan 写道
wym0291 写道
楼主,你没发现你这个getObject方法本身就是一个错误么?而你却把这个方法代码级的错误延伸到事务上去了,佩服佩服。。。。。

你从什么地方看出来这个getObject方法本身是错误的????
错在哪里,我也挺佩服你的,大家都没有看出来,就你看出来了.

wym0291 写道
首先,你这个方法的正确逻辑应该是第一次执行时,缓存中没有数据,然后从数据库中去查数据并放入缓存。之后的方法执行都会直接从缓存中获得数据。也就是说,应该只有一个connection对象会被使用一次。而你得出的结论确实有多个connection被使用。你不觉得这首先就是你方法的代码级别出现了错误,造成了这个后果么?

从你这段话里可以看出来你还不明白我在说什么,我很少用"建议"这个词,因为这让人有种据高凌下的感觉,但是我真的建议你再把文章看两遍



wym0291 写道

再看代码。因为没考虑到并发问题,你这个方法代码在多线程情况下,明显会造成多次重复的查询数据库,而这个查询数据库的动作原本只应该执行仅一次而已。

这里即使有产生并发,最多就是多查两遍数据库, 查完之后就不会再查了,显然这个是小问题,因为这并发的几次查询都是一样的数据.如果加同步,那么不管是查数据库还是缓存都有锁的开销,显然我的选择是在真正并发的时候拿掉锁,宁可多查两遍数据库



0291是对的,楼主仔细想想吧
0291分析的很对很到位
缓存的更新在没失效确实只有一次
锁还是比查数据库快的

但是我觉得楼主是在无视这个并发问题下讨论事务,就是说楼主有新的关注点--事务,我现在读第3页,先发个帖子,接着读
38 楼 fengzl 2008-09-02  
把方法拆分好了,将从缓存取数据的方法和从数据库取数据的方法分离
37 楼 ahuaxuan 2008-09-02  
wym0291 写道
呵呵,确实是我偏离了你的论题,sorry


不过我想了想,这样的讨论对这篇文章来说未必是坏事,至少在文章开头描述的场景在互连网应用中是非常常见的,讨论得全面一点对所有人来说都是一件好事,参与讨论得人对这样得场景更加了如指掌,而看贴得人对这样得场景要注意什么问题也心里有数了

谢谢大家参与讨论
36 楼 wym0291 2008-09-02  
呵呵,确实是我偏离了你的论题,sorry
35 楼 ahuaxuan 2008-09-02  
wym0291 写道
另外,楼主说自己是8个TOMCAT实例,并发很大,运行良好。。。。。

呵呵,其实,在RUP精化阶段,做性能模型分析时,你代码的这种问题肯定会被作为重要的性能问题被提出。

不过话题真是扯远了,我开始的意思只是觉得应该换一个更直观,没有明显问题的代码做演示会更好一点,不然问题代码会给很多新人留下印象,之后在开发时会直接使用。可能是表达能力不行,让楼主误会了,抱歉抱歉。


那我在说明一下吧,事实上这个代码不是我写的,因为出了问题原因是我找到的,但是原因不是在你说的并发问题上,确实是在事务粒度上,后来缩小了事务的粒度,问题立刻解决了。

我刚才说了,使用你的并发代码,并不能解决这个问题,因为主要问题不在并发上。
34 楼 wym0291 2008-09-02  
另外,楼主说自己是8个TOMCAT实例,并发很大,运行良好。。。。。

呵呵,其实,在RUP精化阶段,做性能模型分析时,你代码的这种问题肯定会被作为重要的性能问题被提出。

不过话题真是扯远了,我开始的意思只是觉得应该换一个更直观,没有明显问题的代码做演示会更好一点,不然问题代码会给很多新人留下印象,之后在开发时会直接使用。可能是表达能力不行,让楼主误会了,抱歉抱歉。
33 楼 ahuaxuan 2008-09-02  
terranhao 写道
貌似他是这个意思:正确的逻辑应该是无论如何怎么并发,都只需要从连接池获取一个connection.只用一个connection更新你的cache,然后所有的并发调用都是从cache里获取数据。
但是你的代码实际上在并发的时候获取了多个connection.这就是不对的。不知道我解释清楚了没有
他的意思就是,你实际上逻辑没有考虑清楚,才会犯后面的连接被耗尽的错误。
反正我就是这么理解的,错了请拍砖
我确实是看过了你们的帖子,要不我也不会来吹水,这不是我的风格。

这就是我们理解不一样的地方了,我不认为代码有错(当然并发的问题我没有写在代码里),我认为是事务的粒度不对才导致connection耗尽的,逻辑上唯一不严谨的就是并发问题没有阐述出来,不过我已经在前面的回帖中追加了这部分阐述
terranhao 写道

但是你的代码实际上在并发的时候获取了多个connection.这就是不对的。

这个并不是我们的java代码控制的,这个是写在配置文件中的,其实这就是事务粒度的问题,跟代码没有什么关系,我的代码在并发的时候并没有获取多个connection,你想想啊,我getFromDb又不是每次都查,我的代码怎么会每次都获取connection呢,我觉得你还是没有真正的理解问题的原因,这不是代码造成的


----------------------------------------------------


wym0291 写道
呵呵,怪我多嘴,得罪之处还请谅解。至于你说的解决方法,其实在JDK5刚出来那时已经变成一种比较大众的方法了。

下面是不严谨的,简单的代码,只为了说明一下避免多次查询数据库的逻辑,没有考虑数据库更新后的缓存同步问题,这个问题的解决方法比较多,就不在代码里写了,免得班门弄斧。

ConcurrentHashMap<Map<String, String>, FutureTask<List<Object>>> map = new ConcurrentHashMap<Map<String, String>, FutureTask<List<Object>>>();

public List<Object> get(final Map<String, String> params) throws InterruptedException, ExecutionException {
FutureTask<List<Object>> result = map.get(params);
if(result == null){
FutureTask<List<Object>> task = new FutureTask<List<Object>>(new Callable<List<Object>>(){
@Override
public List<Object> call() throws Exception {
return ObjectDao.getfromDB(params);
}});
result = map.putIfAbsent(params, task);
if(result == null){
System.out.println("result = null");
result = task;
}
result.run();
}
return result.get();
}

在数据库数据更新后,考虑到缓存数据要重新从数据库里获得,可以利用这个任务的重置方法,使此任务可以重新执行。例
如runAndReset()方法,在数据更新时,可以从任务MAP中获取此任务,使用此方法使任务重置。


好,我喜欢这样的讨论,我们假设使用你的代码,然后其他都不用改,getObject方法上继续加使用required事务

如果我的getObject方法里面采用了你的代码connection还是会耗尽,因为我的getObject方法是放在事务里面的啊,这一点你考虑了吗?

你给出的只是同步的方案而已,不能解决connection耗尽的问题,我前面已经说过了,同步的话只要在getObject方法上加锁就可以了,不用这么麻烦

------------------------------------------------------

好好的一个阐述事务粒度的文章居然被偏到并发问题上去了,呵呵,希望大家看到这个回帖之后不要转移重点了。

相关推荐

    SqlServer实验四:事务与数据库备份.doc

    函数的定义包括`RETURNS`关键字,声明返回类型,以及`BEGIN`和`END`之间的函数主体。 - **调用函数**:创建完函数后,可以在查询中通过函数名和括号内的参数来调用。例如,`dbo.fn_mathtutor (5,6)`返回30。 - **...

    讨论AspectJ之target、this、within关键字差异性

    总的来说,AspectJ的`target`、`this`和`within`关键字是构建切面逻辑的关键元素,它们提供了对通知应用范围的细粒度控制。理解并掌握这些关键字的使用,有助于提升AOP编程的效率和质量。对于阅读本文的开发者来说,...

    Java多线程同步机制在网络售票系统中的应用.zip

    3. Lock接口与实现:Java提供Lock接口(如ReentrantLock可重入锁)及其子类,提供了更细粒度的控制,可以实现公平锁、非公平锁、可中断锁和读写锁等。 4. Condition接口:配合Lock使用,可以实现线程间的条件等待,...

    游标、事务、锁 .pptx

    ### 游标、事务、锁知识点详解 #### 一、游标 **1.1 游标概述** 游标是一种数据库对象,它提供了一种机制,使得开发人员能够逐行处理查询结果集中的数据,而不仅仅是批量处理。游标允许用户在结果集上向前或向后...

    java单线程多线程clientserver

    这可能涉及到数据库事务、锁机制以及线程局部存储(ThreadLocal)等。 总的来说,理解并熟练掌握Java中的单线程和多线程编程是开发高效客户端-服务器应用的基础。通过合理设计和利用线程,可以显著提升应用程序的...

    2022面试题6java背诵版本.doc

    - Lock接口及其实现:ReentrantLock、ReadWriteLock等提供更细粒度的锁控制。 5. **Spring MVC工作流程**: - 用户请求到达前端控制器DispatcherServlet。 - DispatcherServlet根据请求映射找到对应的...

    数据库面试题

    1. **去除重复列值**:在SQL查询中,使用`DISTINCT`关键字可以去除结果集中重复的列值,确保返回的每一行都是唯一的。 2. **快照(Snapshot)**:快照是数据库在特定时间点的完整状态记录,主要用于备份和恢复。它...

    mysql性能优化篇-自己的理解

    - 使用`EXPLAIN`关键字查看查询执行计划,了解查询的实际执行路径。 - 根据执行计划调整查询语句或索引策略,提高查询效率。 - **性能剖析(Profiling)**: - 设置`profiling=1`开启性能剖析功能。 - 使用`SHOW...

    阿里巴巴Java开发手册(详尽版)1.4.0[2018-11-27]

    -事务管理:正确配置事务边界,防止事务丢失和脏读。 8. **性能优化** - 内存优化:避免内存泄漏,合理设置对象缓存,控制对象生命周期。 - 资源释放:及时关闭数据库连接、网络连接等资源,防止资源泄露。 - ...

    java_汇总知识点1

    - Final关键字:final用于声明变量不可变,类不可继承,方法不可覆盖。 - 内部类和外部类互访:内部类可以访问外部类的所有成员,包括私有成员;外部类访问内部类需通过实例化内部类对象。 2. **Spring框架**: ...

    数据库MYSQL底层原理分析-笔记-pdf

    MySQL是世界上最受欢迎的关系型数据库管理系统之一,其底层原理对于数据库管理员和开发人员来说至关重要,能够帮助他们优化查询性能,理解事务处理,以及更好地管理数据存储。以下是对标题和描述中涉及知识点的详细...

    MySQL数据库面试宝典1.pdf

    - **索引覆盖**:查询结果只需要索引即可获取,无需访问实际的数据行。 **4.4 索引有哪几种类型?** - **唯一索引**:索引列的值必须唯一。 - **全文索引**:用于全文搜索。 - **组合索引**:基于多个列构建的索引...

    阿里巴巴《java开发手册》.rar

    -事务管理:正确设置事务隔离级别,防止脏读、不可重复读、幻读等问题。 - ORM框架:如MyBatis、Hibernate等,注意避免N+1查询和笛卡尔积问题。 6. **安全控制**: - 输入验证:对用户输入进行校验,防止SQL注入...

    SQL数据库复习题[定义].pdf

    10. 意向锁:意向锁是多粒度锁定的一种形式,包括意向共享锁(IS)和意向排他锁(IX),用于在执行复杂查询时提供锁的兼容性。 单项选择题涉及的数据库基础知识包括数据库的定义、数据库的层次、数据一致性、数据...

    java-syn.zip_Java syn_Java syn锁_java同步锁syn_java锁 syn_syn同步事务锁

    对于更细粒度的控制,可以使用同步代码块,只锁定必要的代码区域: ```java synchronized (object) { // 临界区 } ``` 在这里,`object`是监视器锁的对象,只有获取到这个对象的锁的线程才能进入代码块。 3....

    JAVA面试宝典 JAVA笔试面试题

    - 数据库事务:ACID特性,以及事务的隔离级别。 12. **Spring框架** - DI(Dependency Injection)依赖注入,通过XML配置或注解实现。 - AOP(Aspect Oriented Programming)面向切面编程,实现日志记录、权限...

    数据库+Mysql+性能调用+用于在实践过程中进行Mysql的性能调优

    2. **使用EXPLAIN分析查询**:在SELECT语句前添加EXPLAIN关键字,了解MySQL如何执行查询,识别性能瓶颈,比如未充分利用的索引或不必要的全表扫描。 3. **LIMIT 1提升效率**:当只需要一条数据时,添加LIMIT 1,让...

    DB2 Version 9.5 SQL Reference (Vol. 1).pdf

    - **查询与表表达式**:查询是SQL中最常用的部分之一,通过SELECT语句来检索数据;表表达式则涉及对多个表进行联接操作以获取所需信息。 - **DB2 Call Level Interface (CLI) 和 Open Database Connectivity (ODBC)*...

Global site tag (gtag.js) - Google Analytics