随笔 - 24  文章 - 0  trackbacks - 0
<2024年5月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

Eclipse快捷键大全
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)
Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)
Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性
Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)
Ctrl+Q 定位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)
Ctrl+/(小键盘) 折叠当前类中的所有代码
Ctrl+×(小键盘) 展开当前类中的所有代码
Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用Alt+/来代替)
Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)
Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)
Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)
Ctrl+Shift+F4 关闭所有打开的Editer
Ctrl+Shift+X 把当前选中的文本全部变味小写
Ctrl+Shift+Y 把当前选中的文本全部变为小写
Ctrl+Shift+F 格式化当前代码
Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之)

下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开头的了)
Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)
Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)
Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)
Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)
Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)
Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo)

编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?
Alt+Shift+?
Ctrl+Shift+Space
Java编辑器 显示工具提示描述 F2
Java编辑器 选择封装元素 Alt+Shift+↑
Java编辑器 选择上一个元素 Alt+Shift+←
Java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y

 
查看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-

 
窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-

 
导航
作用域 功能 快捷键
Java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一个 Ctrl+,
全局 下一个 Ctrl+.
Java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
Java编辑器 转至上一个成员 Ctrl+Shift+↑
Java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至行 Ctrl+L

 
搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G

 
文本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下滚行 Ctrl+↓

 
文件
作用域 功能 快捷键
全局 保存 Ctrl+X
Ctrl+S
全局 打印 Ctrl+P
全局 关闭 Ctrl+F4
全局 全部保存 Ctrl+Shift+S
全局 全部关闭 Ctrl+Shift+F4
全局 属性 Alt+Enter
全局 新建 Ctrl+N

 
项目
作用域 功能 快捷键
全局 全部构建 Ctrl+B

 
源代码
作用域 功能 快捷键
Java编辑器 格式化 Ctrl+Shift+F
Java编辑器 取消注释 Ctrl+\
Java编辑器 注释 Ctrl+/
Java编辑器 添加导入 Ctrl+Shift+M
Java编辑器 组织导入 Ctrl+Shift+O
Java编辑器 使用try/catch块来包围 未设置,太常用了,所以在这里列出,建议自己设置。
也可以使用Ctrl+1自动修正。

 
运行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入选择 Ctrl+F5
全局 调试上次启动 F11
全局 继续 F8
全局 使用过滤器单步执行 Shift+F5
全局 添加/去除断点 Ctrl+Shift+B
全局 显示 Ctrl+D
全局 运行上次启动 Ctrl+F11
全局 运行至行 Ctrl+R
全局 执行 Ctrl+U

 
重构
作用域 功能 快捷键
全局 撤销重构 Alt+Shift+Z
全局 抽取方法 Alt+Shift+M
全局 抽取局部变量 Alt+Shift+L
全局 内联 Alt+Shift+I
全局 移动 Alt+Shift+V
全局 重命名 Alt+Shift+R
全局 重做 Alt+Shift+Y

posted @ 2011-01-03 19:56 冯占科 阅读(73) | 评论 (0)编辑 收藏

<数据类型>[] 变量名 = new <数据类型>[数组长度]
int[] a = new int[5]
int a[1]=1;
int a[2]=2;
int a[3]=3;
int a[4]=4;
int a[5]=5;

int[] a = {1,2,3,4,5,6}

posted @ 2010-12-30 22:09 冯占科 阅读(99) | 评论 (0)编辑 收藏
 

抽象类:

absstract定义的类为抽象类,抽象类可以包含抽象方法也可以包含具体的方法;

没有方法体的方法为抽象方法;

抽象的类不能创建对象,只能通过继承使用这个类;

只用覆盖了父类中的方法后,才能实例化,才能使用;

模板方法,用来定义规则;

接口:

接口就是特殊的类;

接口内没有具体的方法,只能包含抽象的方法;

接口内默认就是抽象方法,不用加abstract;

接口内的方法默认是公用的,不用加public

接口不能实例化;

接口可以被继承,产生子接口,子接口也不能创建对象;

通过implements实现接口;

接口可以出现变量,但都是常量,用final定义,在声明的时候就赋值,默认是finalstatic

final最终的,不允许修改;

父类能适用的地方,子类也能适用;

posted @ 2010-12-23 22:30 冯占科 阅读(84) | 评论 (0)编辑 收藏

Linux下可以超过3G,Windows下最大也就1.6G左右(x86)。

一般32位的机器做大只能用到2G内存,4G内存可以跑2个tomcat,通过Apache做cluster.

posted @ 2010-12-22 14:43 冯占科 阅读(2794) | 评论 (0)编辑 收藏
 

一些新手朋友对选择器一知半解,不知道在什么情况下运用什么样的选择器,这是一个比较头疼的问题,针对新手朋友,对CSS选择器作一些简单的说明,希望能对大家的学习工作有一定的帮助,更多的CSS知识请参考Webjx.com的其他文章。

  准确而简洁的运用CSS选择器会达到非常好的效果。我们不必通篇给每一个元素定义类(class)或ID,通过合适的组织,可以用最简单的方法实现同样的效果。在实际工作中,最常用的选择器有以下五类:

一、标签选择器:

  顾名思议,标签选择器是直接将HTML标签作为选择器,可以是ph1dlstrongHTML标签。如:

p { font:12px;}

em { color:blue;}

dl { float:left; margin-top:10px;}

二、id选择器:

  我们通常给页面元素定义id。例如定义一个层 <div id="menubar"></div> 然后在样式表里这样定义:

#menubar {

margin:0 auto;

background:#ccc;

color:#c00;

}

  其中"menubar"是你自己定义的id名称。注意在前面加"#"号。

id选择器也同样支持后代选择器,例如: #menubar p { text-align:center; line-height:20px;; } 这个方法主要用来定义层和那些比较复杂,有多个“唯一后代”的元素。

三、类(class)选择器:

  在CSS里用一个点开头表示类别选择器定义,例如:

.da1 {

color:#f60;

font-size:14px ;

}

  在页面中,用class="类别名"的方法调用: <span class="da1">14px大小的字体</span> 这个方法比较简单灵活,可以随时根据页面需要新建和删除。但需要避免多class综合症。

四、群组选择器:

  当几个元素样式属性一样时,可以共同调用一个声明,元素之间用逗号分隔。如:

p, td, li {

line-height:20px;

color:#c00;

}

#main p, #sider span {

color:#000;

line-height:26px;

}

.www_52css_com,#main p span {

color:#f60;

}

.text1 h1,#sider h3,.art_title h2 {

font-weight:100;

}

  使用组群选择器,将会大大的减化CSS代码,将具有多个相同属性的元素,合并群组进行选择,定义同样的CSS属性,这大大的提高了编码效率与CSS文件体积。

五、后代选择器:

  后代选择器也叫派生选择器。可以使用后代选择器给一个元素里的子元素定义样式,例如这样:

li strong {

font-style:italic;

font-weight:800;

color:#f00;

}

#main p {

color:#000;

line-height:26px;

}

#sider .con span {

color:#000;

line-height:26px;

}

.www_52css_com p span {

color:#f60;

}

#sider ul li.subnav1 {

margin-top:5px;

}  第一段,就是给li下面的子元素strong定义一个斜体加粗而且套红的样式。其他以此类推。

  后代选择器的使用是非常有益的,如果父元素内包括的HTML元素具有唯一性,则不必给内部元素再指定classid,直接应用此选择器即可,例如下面的h3ul就不必指定classid

<div id="sider">

<h3></h3>

<ul>

<li>...</li>

<li>...</li>

<li>...</li>

</ul>

</div>

  在这里CSS就可以及样写:

#sider h3 {...}

#sider ul {...}

#sider ul li {...}

  结合使用上面的四种CSS选择器,基本满足了CSS布局的需要,主要在于灵活的使用,特别是后代选择器的使用能大大的简化HTML文档,使HTML做到结构化明确,最小的代码实现同样的效果。

  CSS中用四个伪类来定义链接的样式,分别是:a:linka:visiteda:hovera : active

  例如:

a:link{font-weight : bold ;text-decoration : none ;color : #c00 ;}

a:visited {font-weight : bold ;text-decoration : none ;color : #c30 ;}

a:hover {font-weight : bold ;text-decoration : underline ;color : #f60 ;}

a:active {font-weight : bold ;text-decoration : none ;color : #F90 ;}

     以上语句分别定义了"链接、已访问过的链接、鼠标停在上方时、点下鼠标时"的样式。注意,必须按以上顺序写,否则显示可能和你预期的不一致。记住它们的顺序是“LVHA”。

posted @ 2010-12-21 09:31 冯占科 阅读(90) | 评论 (0)编辑 收藏
 

Transactions(用户事务分析)

用户事务分析是站在用户角度进行的基础性能分析。

1、Transation Sunmmary(事务综述)

对事务进行综合分析是性能分析的第一步,通过分析测试时间内用户事务的成功与失败情况,可以直接判断出系统是否运行正常。

2、Average Transaciton Response Time(事务平均响应时间)

事务平均响应时间”显示的是测试场景运行期间的每一秒内事务执行所用的平均时间,通过它可以分析测试场景运行期间应用系统的性能走向。

例:随着测试时间的变化,系统处理事务的速度开始逐渐变慢,这说明应用系统随着投产时间的变化,整体性能将会有下降的趋势。

3、Transactions per Second(每秒通过事务数/TPS)

每秒通过事务数/TPS”显示在场景运行的每一秒钟,每个事务通过、失败以及停止的数量,使考查系统性能的一个重要参数。通过它可以确定系统在任何给定时刻的时间事务负载。分析TPS主要是看曲线的性能走向。

将它与平均事务响应时间进行对比,可以分析事务数目对执行时间的影响。

例:当压力加大时,点击率/TPS曲线如果变化缓慢或者有平坦的趋势,很有可能是服务器开始出现瓶颈。

4、Total Transactions per Second(每秒通过事务总数)

每秒通过事务总数”显示在场景运行时,在每一秒内通过的事务总数、失败的事务总署以及停止的事务总数。

5、Transaction Performance Sunmmary(事务性能摘要)

事务性能摘要”显示方案中所有事务的最小、最大和平均执行时间,可以直接判断响应时间是否符合用户的要求。

重点关注事务的平均和最大执行时间,如果其范围不在用户可以接受的时间范围内,需要进行原因分析。

6、Transaction Response Time Under Load(事务响应时间与负载)

事务响应时间与负载”是“正在运行的虚拟用户”图和“平均响应事务时间”图的组合,通过它可以看出在任一时间点事务响应时间与用户数目的关系,从而掌握系统在用户并发方面的性能数据,为扩展用户系统提供参考。此图可以查看虚拟用户负载对执行时间的总体影响,对分析具有渐变负载的测试场景比较有用。

7、Transaction Response Time(Percentile)(事务响应时间(百分比))

事务响应时间(百分比)”是根据测试结果进行分析而得到的综合分析图,也就是工具通过一些统计分析方法间接得到的图表。通过它可以分析在给定事务响应时间范围内能执行的事务百分比。

8、Transaction Response Time(Distribution)(事务响应时间(分布))

事务响应时间(分布)”显示在场景运行过程中,事务执行所用时间的分布,通过它可以了解测试过程中不同响应时间的事务数量。如果系统预先定义了相关事务可以接受的最小和最大事务响应时间,则可以使用此图确定服务器性能是否在可以接受的范围内。

Web Resources(Web资源分析)

Web资源分析是从服务器入手对Web服务器的性能分析。

1、Hits per Second(每秒点击次数)

每秒点击次数”,即使运行场景过程中虚拟用户每秒向Web服务器提交的HTTP请求数。

通过它可以评估虚拟用户产生的负载量,如将其和“平均事务响应时间”图比较,可以查看点击次数对事务性能产生的影响。通过对查看“每秒点击次数”,可以判断系统是否稳定。系统点击率下降通常表明服务器的响应速度在变慢,需进一步分析,发现系统瓶颈所在。

2、Throughput(吞吐率)

吞吐率”显示的是场景运行过程中服务器的每秒的吞吐量。其度量单位是字节,表示虚拟用在任何给定的每一秒从服务器获得的数据量。

可以依据服务器的吞吐量来评估虚拟用户产生的负载量,以及看出服务器在流量方面的处理能力以及是否存在瓶颈。

吞吐率”图和“点击率”图的区别:

吞吐率”图,是每秒服务器处理的HTTP申请数。

点击率”图,是客户端每秒从服务器获得的总数据量。

3、HTTP Status Code Summary(HTTP状态代码概要)

“HTTP状态代码概要”显示场景或会话步骤过程中从Web服务器返回的HTTP状态代码数,该图按照代码分组。HTTP状态代码表示HTTP请求的状态。

4、HTTP Responses per Second(每秒HTTP响应数)

每秒HTTP响应数”是显示运行场景过程中每秒从Web服务器返回的不同HTTP状态代码的数量,还能返回其它各类状态码的信息,通过分析状态码,可以判断服务器在压力下的运行情况,也可以通过对图中显示的结果进行分组,进而定位生成错误的代码脚本。

5、Pages Downloader per Second(每秒下载页面数)

每秒下载页面数”显示场景或会话步骤运行的每一秒内从服务器下载的网页数。使用此图可依据下载的页数来计算Vuser生成的负载量。

和吞吐量图一样,每秒下载页面数图标是Vuser在给定的任一秒内从服务器接收到的数据量。但是吞吐量考虑的各个资源极其大小(例,每个GIF文件的大小、每个网页的大小)。而每秒下载页面数只考虑页面数。

注:要查看每秒下载页数图,必须在R-T-S那里设置“每秒页面数(仅HTML模式)”。

6、Retries per Second(每秒重试次数)

每秒重试次数”显示场景或会话步骤运行的每一秒内服务器尝试的连接次数。

在下列情况将重试服务器连接:

A、初始连接未经授权

B、要求代理服务器身份验证

C、服务器关闭了初始连接

D、初始连接无法连接到服务器

E、服务器最初无法解析负载生成器的IP地址

7、Retries Summary(重试次数概要)

重试次数概要”显示场景或会话步骤运行过程中服务器尝试的连接次数,它按照重试原因分组。将此图与每秒重试次数图一起使用可以确定场景或会话步骤运行过程中服务器在哪个时间点进行了重试。

8、Connections(连接数)

连接数”显示场景或会话步骤运行过程中每个时间点打开的TCP/IP连接数。

借助此图,可以知道何时需要添加其他连接。

例:当连接数到达稳定状态而事务响应时间迅速增大时,添加连接可以使性能得到极大提高(事务响应时间将降低)。

9、Connections Per Second(每秒连接数)

每秒连接数”显示方案在运行过程中每秒建立的TCP/IP连接数。

理想情况下,很多HTTP请求都应该使用同一连接,而不是每个请求都新打开一个连接。通过每秒连接数图可以看出服务器的处理情况,就表明服务器的性能在逐渐下降。

10、SSLs Per Second(每秒SSL连接数)

每秒SSL连接数”显示场景或会话步骤运行的每一秒内打开的新的以及重新使用的SSL连接数。当对安全服务器打开TCP/IP连接后,浏览器将打开SSL连接。

Web Page Breakdown(网页元素细分)

网页元素细分”主要用来评估页面内容是否影响事务的响应时间,通过它可以深入地分析网站上那些下载很慢的图形或中断的连接等有问题的

元素。

1、Web Page Breakdown(页面分解总图)

页面分解”显示某一具体事务在测试过程的响应情况,进而分析相关的事务运行是否正常。

页面分解”图可以按下面四种方式进行进一步细分:

1)、Download Time Breaddown(下载时间细分)

下载时间细分”图显示网页中不同元素的下载时间,同时还可按照下载过程把时间进行分解,用不同的颜色来显示DNS解析时间、建立连接时间、第一次缓冲时间等各自所占比例。

2)、Component Breakdown(Over Time)(组件细分(随时间变化))

组件细分”图显示选定网页的页面组件随时间变化的细分图。通过该图可以很容易的看出哪些元素在测试过程中下载时间不稳定。该图特别适用于需要在客户端下载控件较多的页面,通过分析控件的响应时间,很容易就能发现那些控件不稳定或者比较耗时。

3)、Download Time Breakdown(Over Time)(下载时间细分(随时间变化))

下载时间细分(随时间变化)” 图显示选定网页的页面元素下载时间细分(随时间变化)情况,它非常清晰地显示了页面各个元素在压力测试过程中的下载情况。

下载时间细分”图显示的是整个测试过程页面元素响应的时间统计分析结果,“下载时间细分(随时间变化)”显示的事场景运行过程中每一秒内页面元素响应时间的统计结果,两者分别从宏观和微观角度来分析页面元素的下载时间。

4)、Time to First Buffer Breakdown(Over Time)(第一次缓冲时间细分(随时间变化))

第一次缓冲时间细分(随时间变化)”图显示成功收到从Web服务器返回的第一次缓冲之前的这段时间,场景或会话步骤运行的每一秒中每个网页组件的服务器时间和网络时间(以秒为单位)。可以使用该图确定场景或会话步骤运行期间服务器或网络出现问题的时间。

First Buffer Time:是指客户端与服务器端建立连接后,从服务器发送第一个数据包开始计时,数据经过网络传送到客户端,到浏览器接收到第一个缓冲所用的时间。

2、Page Component Breakdown(页面组件细分)

页面组件细分”图显示每个网页及其组件的平均下载时间(以秒为单位)。可以根据下载组件所用的平均秒数对图列进行排序,通过它有助于隔离有问题的组件。

3、Page Component Breakdown(Over Time)(页面组件分解(随时间变化))

页面组件分解(随时间变化)”图显示在方案运行期间的每一秒内每个网页及其组件的平均响应时间(以秒为单位)。

4、Page Download Time Breakdown(页面下载时间细分)

页面下载时间细分”图显示每个页面组件下载时间的细分,可以根据它确定在网页下载期间事务响应时间缓慢是由网络错误引起还是由服务器错误引起。

页面下载时间细分”图根据DNS解析时间、连接时间、第一次缓冲时间、SSL握手时间、接收时间、FTP验证时间、客户端时间和错误时间来对每个组件的下载过程进行细分。

5、Page Download Time Breakdown(Over Time)(页面下载时间细分(随时间变化))

页面下载时间细分(随时间变化)”图显示方案运行期间,每一秒内每个页面组件下载时间的细分。使用此图可以确定网络或服务器在方案执行期间哪一时间点发生了问题。

页面组件细分(随时间变化)”图和“页面下载时间细分(随时间变化)”图通常结合起来进行分析:首先确定有问题的组件,然后分析它们的下载过程,进而定位原因在哪里。

6、Time to First Buffer Breakdown(第一次缓冲时间细分)

第一次缓冲时间细分”图显示成功收到从Web服务器返回的第一次缓冲之前的这一段时间内的每个页面组件的相关服务器/网路时间。如果组件的下载时间很长,则可以使用此图确定产生的问题与服务器有关还是与网络有关。

网络时间:定义为第一个HTTP请求那一刻开始,直到确认为止所经过的平均时间。

服务器时间:定义为从收到初始HTTP请求确认开始,直到成功收到来自Web服务器的一次缓冲为止所经过的平均时间。

7、Time to First Buffer Breakdown(Over Time)(第一次缓冲时间细分(随时间变化))

第一次缓冲时间细分(随时间变化)”图显示成功收到从Web服务器返回的第一个缓冲之前的这段时间内,场景运行的每一秒中每个网页组件的服务器时间和网络时间。可以使用此图确定场景运行期间服务器或网络出现问题的时间点。

8、Downloader Component Size(KB)(已下载组件大小)

已下载组件大小”图显示每个已经下载的网页组建的大小。通过它可以直接看出哪些组件比较大并需要进一步进行优化以提高性能。

posted @ 2010-12-20 15:45 冯占科 阅读(174) | 评论 (0)编辑 收藏
 

你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握了Java的异常处理机制?在下面这段代码中,你能够迅速找出异常处理的六个问题吗?


1 OutputStreamWriter out = ...
2 java.sql.Connection conn = ...
3 try { //
4  Statement stat = conn.createStatement();
5  ResultSet rs = stat.executeQuery(
6   "select uid, name from user");
7  while (rs.next())
8  {
9   out.println("ID" + rs.getString("uid") //
10    ",姓名:" + rs.getString("name"));
11  }
12  conn.close(); //
13  out.close();
14 }
15 catch(Exception ex) //
16 {
17  ex.printStackTrace(); //
18 }

  作为一个Java程序员,你至少应该能够找出两个问题。但是,如果你不能找出全部六个问题,请继续阅读本文。

  本文讨论的不是Java异常处理的一般性原则,因为这些原则已经被大多数人熟知。我们要做的是分析各种可称为反例anti-pattern)的违背优秀编码规范的常见坏习惯,帮助读者熟悉这些典型的反面例子,从而能够在实际工作中敏锐地察觉和避免这些问题。

  反例之一:丢弃异常

  代码:15-18行。

  这段代码捕获了异常却不作任何处理,可以算得上Java编程中的杀手。从问题出现的频繁程度和祸害程度来看,它也许可以和C/C++程序的一个恶名远播的问题相提并论??不检查缓冲区是否已满。如果你看到了这种丢弃(而不是抛出)异常的情况,可以百分之九十九地肯定代码存在问题(在极少数情况下,这段代码有存在的理由,但最好加上完整的注释,以免引起别人误解)。

  这段代码的错误在于,异常(几乎)总是意味着某些事情不对劲了,或者说至少发生了某些不寻常的事情,我们不应该对程序发出的求救信号保持沉默和无动于衷。调用一下printStackTrace算不上处理异常。不错,调用printStackTrace对调试程序有帮助,但程序调试阶段结束之后,printStackTrace就不应再在异常处理模块中担负主要责任了。

  丢弃异常的情形非常普遍。打开JDKThreadDeath类的文档,可以看到下面这段说明:特别地,虽然出现ThreadDeath是一种正常的情形,但ThreadDeath类是Error而不是Exception的子类,因为许多应用会捕获所有的Exception然后丢弃它不再理睬。这段话的意思是,虽然ThreadDeath代表的是一种普通的问题,但鉴于许多应用会试图捕获所有异常然后不予以适当的处理,所以JDKThreadDeath定义成了Error的子类,因为Error类代表的是一般的应用不应该去捕获的严重问题。可见,丢弃异常这一坏习惯是如此常见,它甚至已经影响到了Java本身的设计。

  那么,应该怎样改正呢?主要有四个选择:

  1、处理异常。针对该异常采取一些行动,例如修正问题、提醒某个人或进行其他一些处理,要根据具体的情形确定应该采取的动作。再次说明,调用printStackTrace算不上已经处理好了异常

  2、重新抛出异常。处理异常的代码在分析异常之后,认为自己不能处理它,重新抛出异常也不失为一种选择。

  3、把该异常转换成另一种异常。大多数情况下,这是指把一个低级的异常转换成应用级的异常(其含义更容易被用户了解的异常)。

  4、不要捕获异常。

  结论一:既然捕获了异常,就要对它进行适当的处理。不要捕获异常之后又把它丢弃,不予理睬。

  反例之二:不指定具体的异常

  代码:15行。

  许多时候人们会被这样一种美妙的想法吸引:用一个catch语句捕获所有的异常。最常见的情形就是使用catch(Exception ex)语句。但实际上,在绝大多数情况下,这种做法不值得提倡。为什么呢?

  要理解其原因,我们必须回顾一下catch语句的用途。catch语句表示我们预期会出现某种异常,而且希望能够处理该异常。异常类的作用就是告诉Java编译器我们想要处理的是哪一种异常。由于绝大多数异常都直接或间接从java.lang.Exception派生,catch(Exception ex)就相当于说我们想要处理几乎所有的异常。

  再来看看前面的代码例子。我们真正想要捕获的异常是什么呢?最明显的一个是SQLException,这是JDBC操作中常见的异常。另一个可能的异常是IOException,因为它要操作OutputStreamWriter。显然,在同一个catch块中处理这两种截然不同的异常是不合适的。如果用两个catch块分别捕获SQLExceptionIOException就要好多了。这就是说,catch语句应当尽量指定具体的异常类型,而不应该指定涵盖范围太广的Exception类。

  另一方面,除了这两个特定的异常,还有其他许多异常也可能出现。例如,如果由于某种原因,executeQuery返回了null,该怎么办?答案是让它们继续抛出,即不必捕获也不必处理。实际上,我们不能也不应该去捕获可能出现的所有异常,程序的其他地方还有捕获异常的机会??直至最后由JVM处理。

  结论二:在catch语句中尽可能指定具体的异常类型,必要时使用多个catch。不要试图处理所有可能出现的异常。

  反例之三:占用资源不释放

  代码:3-14行。

  异常改变了程序正常的执行流程。这个道理虽然简单,却常常被人们忽视。如果程序用到了文件、SocketJDBC连接之类的资源,即使遇到了异常,也要正确释放占用的资源。为此,Java提供了一个简化这类操作的关键词finally

  finally是样好东西:不管是否出现了异常,Finally保证在try/catch/finally块结束之前,执行清理任务的代码总是有机会执行。遗憾的是有些人却不习惯使用finally

  当然,编写finally块应当多加小心,特别是要注意在finally块之内抛出的异常??这是执行清理任务的最后机会,尽量不要再有难以处理的错误。

  结论三:保证所有资源都被正确释放。充分运用finally关键词。

  反例之四:不说明异常的详细信息

  代码:3-18行。

  仔细观察这段代码:如果循环内部出现了异常,会发生什么事情?我们可以得到足够的信息判断循环内部出错的原因吗?不能。我们只能知道当前正在处理的类发生了某种错误,但却不能获得任何信息判断导致当前错误的原因。

  printStackTrace的堆栈跟踪功能显示出程序运行到当前类的执行流程,但只提供了一些最基本的信息,未能说明实际导致错误的原因,同时也不易解读。

  因此,在出现异常时,最好能够提供一些文字信息,例如当前正在执行的类、方法和其他状态信息,包括以一种更适合阅读的方式整理和组织printStackTrace提供的信息。

  结论四:在异常处理模块中提供适量的错误原因信息,组织错误信息使其易于理解和阅读。

  反例之五:过于庞大的try

  代码:3-14行。

  经常可以看到有人把大量的代码放入单个try块,实际上这不是好习惯。这种现象之所以常见,原因就在于有些人图省事,不愿花时间分析一大块代码中哪几行代码会抛出异常、异常的具体类型是什么。把大量的语句装入单个巨大的try块就象是出门旅游时把所有日常用品塞入一个大箱子,虽然东西是带上了,但要找出来可不容易。

  一些新手常常把大量的代码放入单个try块,然后再在catch语句中声明Exception,而不是分离各个可能出现异常的段落并分别捕获其异常。这种做法为分析程序抛出异常的原因带来了困难,因为一大段代码中有太多的地方可能抛出Exception

  结论五:尽量减小try块的体积。

  反例之六:输出数据不完整

  代码:7-11行。

  不完整的数据是Java程序的隐形杀手。仔细观察这段代码,考虑一下如果循环的中间抛出了异常,会发生什么事情。循环的执行当然是要被打断的,其次,catch块会执行??就这些,再也没有其他动作了。已经输出的数据怎么办?使用这些数据的人或设备将收到一份不完整的(因而也是错误的)数据,却得不到任何有关这份数据是否完整的提示。对于有些系统来说,数据不完整可能比系统停止运行带来更大的损失。

  较为理想的处置办法是向输出设备写一些信息,声明数据的不完整性;另一种可能有效的办法是,先缓冲要输出的数据,准备好全部数据之后再一次性输出。

  结论六:全面考虑可能出现的异常以及这些异常对执行流程的影响。

  改写后的代码

  根据上面的讨论,下面给出改写后的代码。也许有人会说它稍微有点?嗦,但是它有了比较完备的异常处理机制。

OutputStreamWriter out = ...
java.sql.Connection conn = ...
try {
 Statement stat = conn.createStatement();
 ResultSet rs = stat.executeQuery(
  "select uid, name from user");
 while (rs.next())
 {
  out.println("ID" + rs.getString("uid") + ",姓名: " + rs.getString("name"));
 }
}
catch(SQLException sqlex)
{
 out.println("警告:数据不完整");
 throw new ApplicationException("读取数据时出现SQL错误", sqlex);
}
catch(IOException ioex)
{
 throw new ApplicationException("写入数据时出现IO错误", ioex);
}
finally
{
 if (conn != null) {
  try {
   conn.close();
  }
  catch(SQLException sqlex2)
  {
   System.err(this.getClass().getName() + ".mymethod - 不能关闭数据库连接: " + sqlex2.toString());
  }
 }

 if (out != null) {
  try {
   out.close();
  }
  catch(IOException ioex2)
  {
   System.err(this.getClass().getName() + ".mymethod - 不能关闭输出文件" + ioex2.toString());
  }
 }
}

  本文的结论不是放之四海皆准的教条,有时常识和经验才是最好的老师。如果你对自己的做法没有百分之百的信心,务必加上详细、全面的注释。

  另一方面,不要笑话这些错误,不妨问问你自己是否真地彻底摆脱了这些坏习惯。即使最有经验的程序员偶尔也会误入歧途,原因很简单,因为它们确确实实带来了方便。所有这些反例都可以看作Java编程世界的恶魔,它们美丽动人,无孔不入,时刻诱惑着你。也许有人会认为这些都属于鸡皮蒜毛的小事,不足挂齿,但请记住:勿以恶小而为之,勿以善小而不为。

posted @ 2010-12-17 23:02 冯占科 阅读(119) | 评论 (0)编辑 收藏

NO.1 java.lang.NullPointerException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.RuntimeException
        java.lang.NullPointerException

  这个异常的解释是 "程序遇上了空指针 ",简单地说就是调用了未经初始化的对象或者是不存在的对象,对数组操作中出现空指针,很
多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初始化混淆起来了。数组的初始化是对数组分配需要的
空间,而初始化后的数组,其中的元素并没有实例化,依然是空的,所以还需要对每个元素都进行初始化(如果要调用的话)
当应用程序试图在需要对象的地方使用 null 时,抛出该异常。这种情况包括:
调用 null 对象的实例方法。
访问或修改 null 对象的字段。
将 null 作为一个数组,获得其长度。
将 null 作为一个数组,访问或修改其时间片。
将 null 作为 Throwable 值抛出。
应用程序应该抛出该类的实例,指示其他对 null 对象的非法使用。


NO.2 java.lang.ClassNotFoundException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.ClassNotFoundException

  这个异常的解释是 "指定的类不存在 ",这里主要考虑一下类的名称和路径是否正确即可.
当应用程序试图使用以下方法通过字符串名加载类时,抛出该异常:
Class 类中的 forName 方法。
ClassLoader 类中的 findSystemClass 方法。
ClassLoader 类中的 loadClass 方法。
但是没有找到具有指定名称的类的定义。


NO.3 java.lang.ArithmeticException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.RuntimeException
        java.lang.ArithmeticException

当出现异常的运算条件时,抛出此异常。
  这个异常的解释是 "数学运算异常 ",比如程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自
己程序中涉及到数学运算的地方,公式是不是有不妥了。


NO.4 java.lang.ArrayIndexOutOfBoundsException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.RuntimeException
        java.lang.IndexOutOfBoundsException
     java.lang.ArrayIndexOutOfBoundsException

  这个异常的解释是 "数组下标越界 ",现在程序中大多都有对数组的操作,因此在调用数组的时候一
定要认真检查,看自己调用的下标是不是超出了数组的范围,一般来说,显示(即直接用常数当下标)调用不太容易出这样的错,但隐式(
即用变量表示下标)调用就经常出错了,还有一种情况,是程序中定义的数组的长度是通过某些特定方法决定的,不是事先声明的,这个时
候,最好先查看一下数组的length,以免出现这个异常。
用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。


NO.5 java.lang.IllegalArgumentException
      java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.RuntimeException
        java.lang.IllegalArgumentException


    抛出的异常表明向方法传递了一个不合法或不正确的参数。
  这个异常的解释是 "方法的参数错误 ",很多J2ME的类库中的方法在一些情况下都会引发这样的错误,比如音量调节方法中的音量参数
如果写成负数就会出现这个异常,再比如 g.setColor(int red,int green,int blue)这个方法中的三个值,如果有超过255的也会出现
这个异常,因此一旦发现这个异常,我们要做的,就是赶紧去检查一下方法调用中的参数传递是不是出现了错误。


NO.6 java.lang.IllegalAccessException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.IllegalAccessException

  这个异常的解释是 "没有访问权限 ",当应用程序要调用一个类,但当前的方法即没有对该类的访问权限便会出现这个异常。对程序中
用了Package的情况下要注意这个异常。
当应用程序试图创建一个实例(而不是数组)、设置或获取一个字段,或者调用一个方法,但当前正在执行的方法无法访问指定类、字段、
方法或构造方法的定义时,抛出 IllegalAccessException。


NO.7 java.lang.IncompatibleClassChangeError
java.lang.Object
   java.lang.Throwable
       java.lang.Error
    java.lang.LinkageError
        java.lang.IncompatibleClassChangeError

不兼容的类变化错误。当正在执行的方法所依赖的类定义发生了不兼容的改变时,抛出该异常。一般在修改了应用中的某些类的声明定义而
没有对整个应用重新编译而直接运行的情况下,容易引发该错误。
在某些类定义中出现不兼容的类更改时抛出该异常。某些目前执行的方法所依赖的类定义已发生了变化。


NO.8 java.lang.InstantiationError
java.lang.Object
   java.lang.Throwable
       java.lang.Error
    java.lang.LinkageError
        java.lang.IncompatibleClassChangeError
     java.lang.InstantiationError

实例化错误。当一个应用试图通过Java的new操作符构造一个抽象类或者接口时抛出该异常.
通常由编译器捕获此错误;如果类定义中存在不兼容的更改,则此错误将只可能在运行时发生。


NO.9 java.lang.LinkageError
java.lang.Object
   java.lang.Throwable
       java.lang.Error
    java.lang.LinkageError

链接错误。该错误及其所有子类指示某个类依赖于另外一些类,在该类编译之后,被依赖的类改变了其类定义而没有重新编译所有的类,进
而引发错误的情况。
LinkageError 的子类指示一个类在一定程度上依赖于另一个类;但是,在编译前一个类之后,后一个类发生了不相容的改变。


NO.10 java.lang.StackOverflowError
java.lang.Object
   java.lang.Throwable
       java.lang.Error
    java.lang.VirtualMachineError
        java.lang.StackOverflowError

堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出时抛出该错误。


NO.11 java.lang.Exception
java.lang.Object
   java.lang.Throwable
       java.lang.Exception

Exception 类及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。 (异常层次结构的根类)


NO.12 java.lang.RuntimeException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.RuntimeException

RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。可能在执行方法期间抛出但未被捕获的 RuntimeException
的任何子类都无需在 throws 子句中进行声明。 (java.lang中异常的基类)


NO.13 java.util.InputMismatchException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.RuntimeException
        java.util.NoSuchElementException
     java.util.InputMismatchException

由 Scanner 抛出,表明用于检索的标记与期望类型的模式不匹配,或者该标记处在期望类型的范围之外。


NO.14 java.io.IOException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.io.IOException

当发生某种 I/O 异常时,抛出此异常。此类为异常的通用类,它是由失败的或中断的 I/O 操作生成的。


NO.15 java.io.FileNotFoundException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.io.IOException
        java.io.FileNotFoundException

当试图打开指定路径名表示的文件失败时,抛出此异常。
在不存在具有指定路径名的文件时,此异常将由 FileInputStream、FileOutputStream 和 RandomAccessFile 构造方法抛出。
如果该文件存在,但是由于某些原因不可访问,比如试图打开一个只读文件进行写入,此时这些构造方法仍然会抛出该异常。


NO.16 java.io.EOFException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.io.IOException
        java.io.EOFException

当输入过程中意外到达文件或流的末尾时,抛出此异常。
此异常主要被数据输入流用来表明到达流的末尾。注意,其他许多输入操作返回一个特殊值表示到达流的末尾,而不是抛出异常。


NO.17 java.lang.InterruptedException
java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.InterruptedException

当线程在很长一段时间内一直处于正在等待、休眠或暂停状态,而另一个线程用 Thread 类中的 iterrupt 方法中断它时,抛出该异常。


NO.18 java.lang.NumberFormatException
      java.lang.Object
   java.lang.Throwable
       java.lang.Exception
    java.lang.RuntimeException
        java.lang.IllegalArgumentException
     java.lang.NumberFormatException


当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。

posted @ 2010-12-17 22:51 冯占科 阅读(215) | 评论 (0)编辑 收藏
 

数据并发的问题

 

一个数据库可能拥有多个访问客户端,这些客户端都可以并发方式访问数据库。数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。这些问题可以归结为5类,包括3类数据读问题(脏读、幻象读和不可重复读)以及2类数据更新问题(第一类丢失更新和第二类丢失更新)。

脏读(dirty read

事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。如果恰巧B事务回滚,那么A事务读到的数据根本是不被承认的。来看取款事务和转账事务并发时引发的脏读场景

时间

转账事务A

取款事务B

T1

开始事务

T2

开始事务

T3

     

查询账户余额为1000元    

T4

        

取出500元把余额改为500元

T5

查询账户余额为500元(脏读)

T6

撤销事务余额恢复为1000元

T7

汇入100元把余额改为600元

T8

提交事务

B希望取款500元而后又撤销了动作,而A往相同的账户中转账100元,就因为A事务读取了B事务尚未提交的数据,因而造成账户白白丢失了500元。

不可重复读(unrepeatable read

 

不可重复读是指A事务读取了B事务已经提交的更改数据。假设A在取款事务的过程中,B往该账户转账100元,A两次读取账户的余额发生不一致:

时间

取款事务A

转账事务B

T1

开始事务

T2

开始事务

                          

T3

                              

查询账户余额为1000元     

T4

查询账户余额为1000元

                          

T5

                  

取出100元把余额改为900元

T6

提交事务                  

T7

查询账户余额为900元(和T4读取的不一致)

在同一事务中,T4时间点和T7时间点读取账户存款余额不一样。

幻象读(phantom read)
    A事务读取B事务提交的新增数据,这时A事务将出现幻象读的问题。幻象读一般发生在计算统计数据的事务中,举一个例子,假设银行系统在同一个事务中,两次统计存款账户的总金额,在两次统计过程中,刚好新增了一个存款账户,并存入100元,这时,两次统计的总金额将不一致:  

时间

统计金额事务A

转账事务B

T1

开始事务

T2

开始事务

             

T3

统计总存款数为10000元

             

T4

新增一个存款账户,存款为100元

T5

提交事务     

T6

再次统计总存款数为10100元(幻象读)


   
如果新增数据刚好满足事务的查询条件,这个新数据就进入了事务的视野,因而产生了两个统计不一致的情况。
幻象读和不可重复读是两个容易混淆的概念,前者是指读到了其它已经提交事务的新增数据,而后者是指读到了已经提交事务的更改数据(更改或删除),为了避免这两种情况,采取的对策是不同的,防止读取到更改数据,只需要对操作的数据添加行级锁,阻止操作中的数据发生变化,而防止读取到新增数据,则往往需要添加表级锁——将整个表锁定,防止新增数据(Oracle使用多版本数据的方式实现)。


第一类丢失更新
    A
事务撤销时,把已经提交的B事务的更新数据覆盖了。这种错误可能造成很严重的问题,通过下面的账户取款转账就可以看出来: 
    

时间

取款事务A

转账事务B

T1

开始事务

 

T2

开始事务

T3

查询账户余额为1000元    

T4

查询账户余额为1000元

T5

汇入100元把余额改为1100元

T6

提交事务

T7

取出100元把余额改为900元

T8

撤销事务

T9

余额恢复为1000元(丢失更新)


A
事务在撤销时,“不小心”将B事务已经转入账户的金额给抹去了。
第二类丢失更新
A事务覆盖B事务已经提交的数据,造成B事务所做操作丢失:  

时间

转账事务A

取款事务B

T1

 

开始事务

T2

开始事务

                         

T3

               

查询账户余额为1000元    

T4

查询账户余额为1000元

                         

T5

取出100元把余额改为900元

T6

提交事务           

T7

汇入100元

T8

提交事务

T9

把余额改为1100元(丢失更新)


   
上面的例子里由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失了100元,相反如果转账事务先提交,那么用户账户将损失100元。

数据库锁机制
   
数据并发会引发很多问题,在一些场合下有些问题是允许的,但在另外一些场合下可能却是致命的。数据库通过锁的机制解决并发访问的问题,虽然不同的数据库在实现细节上存在差别,但原理基本上是一样的。
    按锁定的对象的不同,一般可以分为表锁定和行锁定,前者对整个表进行锁定,而后者对表中特定行进行锁定。从并发事务锁定的关系上看,可以分为共享锁定和独占锁定。共享锁定会防止独占锁定,但允许其它的共享锁定。而独占锁定既防止其它的独占锁定,也防止其它的共享锁定。为了更改数据,数据库必须在进行更改的行上施加行独占锁定,INSERT、UPDATE、DELETE和SELECT FOR UPDATE语句都会隐式采用必要的行锁定。下面我们介绍一下ORACLE数据库常用的5种锁定:
 行共享锁定:一般通过SELECT FOR UPDATE语句隐式获得行共享锁定,在Oracle中你也可以通过LOCK TABLE IN ROW SHARE MODE语句显式获得行共享锁定。行共享锁定并不防止对数据行进行更改的操作,但是可以防止其它会话获取独占性数据表锁定。允许进行多个并发的行共享和行独占性锁定,还允许进行数据表的共享或者采用共享行独占锁定;
 行独占锁定:通过一条INSERT、UPDATE或DELETE语句隐式获取,或者通过一条LOCK TABLE IN ROW EXCLUSIVE MODE语句显式获取。这个锁定可以防止其它会话获取一个共享锁定、共享行独占锁定或独占锁定;
 表共享锁定:通过LOCK TABLE IN SHARE MODE语句显式获得。这种锁定可以防止其它会话获取行独占锁定(INSERT、UPDATE或DELETE),或者防止其它表共享行独占锁定或表独占锁定,它允许在表中拥有多个行共享和表共享锁定。该锁定可以让会话具有对表事务级一致性访问,因为其它会话在你提交或者回溯该事务并释放对该表的锁定之前不能更改这个被锁定的表;
 表共享行独占:通过LOCK TABLE IN SHARE ROW EXCLUSIVE MODE语句显式获得。这种锁定可以防止其它会话获取一个表共享、行独占或者表独占锁定,它允许其它行共享锁定。这种锁定类似于表共享锁定,只是一次只能对一个表放置一个表共享行独占锁定。如果A会话拥有该锁定,则B会话可以执行SELECT FOR UPDATE操作,但如果B会话试图更新选择的行,则需要等待;
 表独占:通过LOCK TABLE IN EXCLUSIVE MODE显式获得。这个锁定防止其它会话对该表的任何其它锁定。

事务隔离级别
    尽管数据库为用户提供了锁的DML操作方式,但直接使用锁管理是非常麻烦的,因此数据库为用户提供了自动锁机制。只要用户指定会话的事务隔离级别,数据库就会分析事务中的SQL语句,然后自动为事务操作的数据资源添加上适合的锁。此外数据库还会维护这些锁,当一个资源上的锁数目太多时,自动进行锁升级以提高系统的运行性能,而这一过程对用户来说完全是透明的。
    ANSI/ISO SQL 92标准定义了4个等级的事务隔离级别,在相同数据环境下,使用相同的输入,执行相同的工作,根据不同的隔离级别,可以导致不同的结果。不同事务隔离级别能够解决的数据并发问题的能力是不同的。
        表 1 事务隔离级别对并发问题的解决情况 

隔离级别

脏读

不可

重复读

幻象读

第一类丢失更新

第二类丢失更新

READ UNCOMMITED

允许

允许

允许

不允许

允许

READ COMMITTED

不允许

允许

允许

不允许

允许

REPEATABLE READ

不允许

不允许

允许

不允许

不允许

SERIALIZABLE

不允许

不允许

不允许

不允许

不允许


   
事务的隔离级别和数据库并发性是对立的,两者此增彼长。一般来说,使用READ UNCOMMITED隔离级别的数据库拥有最高的并发性和吞吐量,而使用SERIALIZABLE隔离级别的数据库并发性最低。

    SQL 92定义READ UNCOMMITED主要是为了提供非阻塞读的能力,Oracle虽然也支持READ UNCOMMITED,但它不支持脏读,因为Oracle使用多版本机制彻底解决了在非阻塞读时读到脏数据的问题并保证读的一致性,所以,Oracle的READ COMMITTED隔离级别就已经满足了SQL 92标准的REPEATABLE READ隔离级别。

    SQL 92推荐使用REPEATABLE READ以保证数据的读一致性,不过用户可以根据应用的需要选择适合的隔离等级。

posted @ 2010-12-17 22:42 冯占科 阅读(529) | 评论 (0)编辑 收藏
select * from T  WHERE dt is NULL

T:表名;
dt:日期字段
posted @ 2010-12-16 22:17 冯占科 阅读(194) | 评论 (0)编辑 收藏
仅列出标题
共3页: 上一页 1 2 3 下一页