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

[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水平有限,文中不妥之处还望不吝指正,谢谢。

时间: 2024-10-06 09:43:34

关键字:查询,事务,粒度的相关文章

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

/**   * 该方法上加事务,传播途径为required   * @param params   * @return   */  public List<object> getObject(Map<String, String> params)  {   //先从memcached中取得数据   List<object> o1 = memcachedClient.getFromCache(params);         if (o1 == null) {    ol

使用asp.net进行多关键字查询的例子

asp.net|关键字 下面的代码演示了如何对一段文本进行多关键字查询并高亮显示,给自己做为一个小tip保留下<%@ Page Language="C#" Debug="False" Strict="True" Explicit="True" Buffer="True"%><%@ Import Namespace="System" %><html>&l

SQL server中多种关键字查询数据

问题描述 SQL server中多种关键字查询数据 比如学生有姓名,学号,班级等列,我可以通过学号查询,也可以通过姓名查询 解决方案 两个办法,一个是首先在代码中判断输入的是全数字还是中文,分别执行不同的查询.或者写在一起:select * from table where 姓名=输入 or 学号=输入 解决方案二: select * from 学生表 where name = '姓名' or No='学号' 解决方案三: 可以使用动态sql拼接比如定义一个@sqltext 根据不同的情况拼接s

sphinx关键字查询排序不理想

问题描述 sphinx关键字查询排序不理想 数据库里有三条记录: id name 1 琅琊榜续集 2 琅琊榜 3 琅琊榜大结局 $sphinx->SetSortMode("SPH_SORT_RELEVANCE"); $sphinx->Query("琅琊榜"); 使用sphinx api查出匹配的结果是: array (size=3) 0 => array (size=3) 'id' => string '1' (length=1) 'weig

为什么我的关键字查询 like后面怎样都粘在一起的!(hql语句)

问题描述 为什么我的关键字查询 like后面怎样都粘在一起的!(hql语句) 解决方案 like后面要加空格,像 " select * from user where name like '% "+ key +"%' " 解决方案二: 空格影响了...空格影响了...空格影响了...

c++按关键字查询txt文件

问题描述 c++按关键字查询txt文件 比如 5^3 1 2 4 2 4 3 3 1 2 4 3 1 5 5 5 类似数据类型还有很多,以矩阵形式输出,形成5行3列表格 解决方案 #include<cstdio> using namespace std; int a[100][100]; int main(){ FILE* fin=fopen("*****.txt","r"); for(int i=1;i<=*****;++i)//行 for(in

linux-Linux命令,根据关键字查询日志

问题描述 Linux命令,根据关键字查询日志 由于日志特别大,我想根据一个命令查询关键字,比如说日志中有一个 '111222' 有没有一个命令可以定位到日志中这个关键字的位置,并且显示关键字前后的日志,并且关键字颜色加深,如果日志中有多个地方有这个关键字.按一下快捷键,就能定位到第二个关键字位置,求教! 解决方案 直接vi 日志文件后 /111222按enter查询,按n指向下一个 解决方案二: 可以试试 grep,参数 -A n -B n,显示上下需要行数 解决方案三: 难道不是grep吗?个

oracle 合并查询 事务 sql函数小知识学习_oracle

表查询: 合并查询:使用union关键字,可将满足条件的重复行去掉. 复制代码 代码如下: select ename,sal,job from emp where sal > 2500 union select ename,sal,job from emp where job = 'MANAGER'; 而union all用法和union相似,但是不会取消重复行. intersect 用来取两个结果的交集. minus用来取两个结果的差集. 使员工scott的岗位,工资,补助与SMITH员工一样

最有效率的“多字段模糊匹配关键字查询”的解决办法

关键字|解决 我们开发数据库应用时,常常需要用到模糊查询.如果同一个条件需要匹配很多字段怎么办呢?通常,程序员会每个字段都在SQL中"field like '%cond%'"一次.这样,SQL语句会长得惊人,碰上复杂一点的,甚至SQL语句会因为超长而被数据库拒绝执行. 其实,这个问题只要动动脑筋就很容易解决: 首先,将要匹配相同条件的字段连起来(field1+field2+...)成一个长字符串:然后再 Like "%cond%"就可以了. 不过这种方法有个问题,就