Gay Bird

登高者必自卑,行远者必自迩,在这个世界上,重要的不是你正站在那里,而是你正朝什么方向移动......

2008年10月8日 #

JAVA几种对象的解释

posted @ 2008-10-16 12:52 Sky Yi 阅读(194) | 评论 (0)编辑 收藏

MSSQL事务、事务隔离级别、锁的简单总结

一、数据库事务
1、事务是作为单个逻辑工作单元执行的一系列操作。可以是一条SQL语句也可以是多条SQL语句。

2、事务具有四个特性
   原子性:不可分隔、成则具成、败则具败。
   恢滦裕菏挛裨谕瓿墒保 匦胧顾 械氖 荻急3忠恢伦刺?
   隔离性:独立的执行互不干扰。由并发事务所作的修改必须与任何其他并发事务所作的修改隔离(另外的描述:多个事务同时进行,它们之间应该互不干扰.应该防止一个事务处理其他事务也要修改的数据时,不合理的存取和不完整的读取数据)
  
3、启动事务:使用 API 函数和 Transact-SQL 语句,可以按显式、自动提交或隐式的方式来启动事务。

4、结束事务:您可以使用 COMMIT(成功) 或 ROLLBACK(失败) 语句,或者通过 API 函数来结束事务。

5、创建事务的原则:
   尽可能使事务保持简短很重要,当事务启动后,数据库管理系统 (DBMS) 必须在事务结束之前保留很多资源、以保证事务的正确安全执行。
   特别是在大量并发的系统中, 保持事务简短以减少并发 资源锁定争夺,将先得更为重要。
   1、事务处理,禁止与用户交互,在事务开始前完成用户输入。
   2、在浏览数据时,尽量不要打开事务
   3、尽可能使事务保持简短。
   4、考虑为只读查询使用快照隔离,以减少阻塞。
   5、灵活地使用更低的事务隔离级别。
   6、灵活地使用更低的游标并发选项,例如开放式并发选项。
   7、在事务中尽量使访问的数据量最小。

 

二、事务的隔离级别

1、数据库事务的隔离级别:四种

隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
读未提交(Read uncommitted) 可能 可能 可能
读已提交(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能

2、数据库一般的默认隔离离级别是“读已提交”,默认的事务隔离级别下:Insert,update ,delete下的是X锁, 会等待事务完成。通常情况下可以把隔离级别设为Read Commited,它能避免脏读,而且有较好的并发性能。尽管它会导致不可重复读、虚读和第二类更新丢失等问题,在可能出现这类问题的个别场合可以由应用程序釆用悲观锁或乐观锁来控制。


3、SQL语句可以使用SET TRANSACTION ISOLATION LEVEL来设置事务的隔离级别。如:SET TRANSACTION ISOLATION LEVEL   Read Committed。若要在应用程序中使用更严格或较宽松的隔离级别,可以通过使用   set transaction isolation level语句设置会话的隔离级别,来自定义整个会话的锁定。  
指定隔离级别后,sql server会话中所有select语句的锁定行为都运行于该隔离级别上,并一直保持有效直到会话终止或者将隔离级别设置为另一个级别。

4、另外要提一点:SQL标准对事务隔离级别的规定,是按该级别不可能发生什么问题来确定的,不一定会发生这样的问题;所以,不同的数据库对事务隔离的级别约定不一样,比如,有的数据库把 可重复读级别按可串行化来对待。(lkdlhw_2000个人理解:各个数据库应该都遵循四种标准的事务隔离等级的定义,但是某些数据库具体实现可能不存在四种,因为串行化可以避免不可重复读,因此某些数据库语法上支持设置事务隔离等级为不可重复读,但实际上是串行化在起作用。也就是说只要该级别能够避免不可重复读的问题,就可以称之为不可重复读取级别。)

5、该隔离级别定义一个事务必须与其他事务所进行的资源或数据更改相隔离的程度。事务隔离级别控制:
     读取数据时是否占用锁以及所请求的锁类型。
     占用读取锁的时间。
     引用其他事务修改的行的读取操作是否:
     在该行上的排他锁被释放之前阻塞其他事务。
     检索在启动语句或事务时存在的行的已提交版本。
     读取未提交的数据修改

三、锁

1、分类:从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁

2、事务使用锁,防止其他用户修改另外一个还没有完成的事务中的数据。对于多用户系统来说,锁机制是必须的。SQL Server有多种锁,允许事务锁定不同的资源。锁就是保护指定的资源,不被其他事务操作。SQL Server有多种锁,允许事务锁定不同的资源。锁就是保护指定的资源,不被其他事务操作。为了最小化锁的成本,SQL Server自动地以与任务相应等级的锁来锁定资源对象。锁定比较小的对象,例如锁定行,虽然可以提高并发性,但是却有较高的开支,因为如果锁定许多行,那么需要占有更多的锁。锁定比较大的对象,例如锁定表,会大大降低并发性,因为锁定整个表就限制了其他事务访问该表的其他部分,但是成本开支比较低,因为只需维护比较少的锁。

3、 锁的特点:
1. 锁是保证并发控制的手段
2. 可以锁定的资源包括行、页、簇、表和数据库
3. 锁的类型主要包括共享锁和排它锁
4. 特殊类型的锁包括意图锁、修改锁和模式锁
5. 共享锁允许其他事务继续使用锁定的资源
6. 排它锁只允许一个事务访问数据
7. 系统本身可以处理死锁
8. 用户可以根据实际情况定制锁的一些特征

4、锁是定义到sql语句上的,对数据进行操作的sql就是:select,Insert,update ,delete。不同的事物隔离即被在执行sql的时候会向表上发送不同的锁。

关于锁的更多描述,可以去网上搜索一下。http://www.bitscn.com/windows/sql/200604/1068.html

四、多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:

脏读dirty reads:
   当事务读取还未被提交的数据时,就会发生这种事件。举例来说:Transaction1修改了一行数据,然后Transaction2在Transaction1还未提交修改操作之前读取了被修改的行。如果Transaction1回滚了修改操作,那么Transaction2读取的数据就可以看作是从未存在过的。
不可重复的读non-repeatable reads:
   当事务两次读取同一行数据,但每次得到的数据都不一样时,就会发生这种事件。举例来说:Transaction1读取一行数据,然后Transaction2修改或删除该行并提交修改操作。当Transaction1试图重新读取该行时,它就会得到不同的数据值(如果该行被更新)或发现该行不再存在(如果该行被删除)。    
虚读phantom read:
   如果符合搜索条件的一行数据在后面的读取操作中出现,但该行数据却不属于最初的数据,就会发生这种事件。举例来说Transactio1读取满足某种搜索条件的一些行,然后Transaction2插入了符合Transaction1的搜索条件的一个新行。如果Transaction1重新执行产生原来那些行的查询,就会得到不同的行。

为了解决这些问题,数据库引入了“锁”的机制(从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁,详细内容不再描述)。

 

五、lkdlhw_2000个人理解(以下问题都是推测,还没有证实):

隔离级别是由锁来实现的,之所以出现事务的隔离级别相当于数据库开发商根据一般的业务需求实现定义好的一组锁使用的规则,便于我们时候,当我们将事务隔离级别定义到某一级上后如果不能满足需求,我们还可以自行定义sql的锁来覆盖事务隔离级别默认的锁机制?

锁存在两个问题:一个是锁的粒度,一个是锁的时间,锁的时间应该包括两种一种是sql执行完就释放锁,领一中是事务结束后释放锁

六、参考文章

http://www.es-ivision.com/Channel-4-10-108-0.html
http://tech.ccidnet.com/art/1105/20050602/261573_1.html
http://www.blogjava.net/zhengtengfeng/archive/2007/04/23/113025.html

七、事务隔离级别的例子

1. Read Uncommitted:最低等级的事务隔离,仅仅保证了读取过程中不会读取到非法数据。上诉4种不确定情况均有可能发生。
2. Read Committed:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
第一个查询事务
SET TRANSACTION ISOLATION LEVEL   Read Committed
begin tran
   update Cate SET Sname=Sname+'b' where ID=1
   SELECT * FROM cate where ID=1
   waitfor delay '00:00:6'  
   rollback tran --回滚事务
select Getdate()
SELECT * FROM cate where ID=1
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed   --把committed换成Read uncommitted可看到“脏读取”的示例。
SELECT * FROM cate where ID=1
select Getdate()
可以看到使用 Read Committed 成功的避免了“脏读取”.
3. Repeatable Read:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
第一个查询事务
SET TRANSACTION ISOLATION LEVEL Repeatable Read --   把Repeatable Read换成Read committed可以看到“不可重复读取”的示例
begin tran
SELECT * FROM cate where ID=33 --第一次读取数据
   waitfor delay '00:00:6'  
SELECT * FROM cate where ID=33 --第二次读取数据,不可重复读取
commit
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed
update cate set Sname=Sname+'JD' where ID=33
SELECT * FROM cate where ID>30
4. Serializable:最高等级的事务隔离,上面3种不确定情况都将被规避。这个级别将模拟事务的串行执行。
在第一个查询窗口执行
SET TRANSACTION ISOLATION LEVEL Serializable -- 把Serializable换成Repeatable Read 可看到“幻像读”的示例
begin tran
SELECT * FROM cate where ID>30 --第一次读取数据,“幻像读”的示例
   waitfor delay '00:00:6'   --延迟6秒读取
SELECT * FROM cate where ID>30 --第一次读取数据
commit
第二个查询事务
SET TRANSACTION ISOLATION LEVEL Read committed
Delete from cate where ID>33
SELECT * FROM cate where ID>30
创建事务

设置事务级别:SET TRANSACTION ISOLATION LEVEL
开始事务:begin tran
提交事务:COMMIT
回滚事务:ROLLBACK
创建事务保存点:SAVE TRANSACTION savepoint_name
回滚到事务点:ROLLBACK TRANSACTION savepoint_name



1、并发的影响:http://technet.microsoft.com/zh-cn/library/ms190805.aspx
      该文章列出了并发引起的四种影响:丢失更新、脏读(未提交的依赖关系)、不可重复读(不一致的分析)、幻读
  
2、并发控制类型:http://technet.microsoft.com/zh-cn/library/ms189132.aspx
     当许多人试图同时修改数据库中的数据时,必须实现一个控制系统,使一个人所做的修改不会对他人所做的修改产生负面影响。这称为并发控制。并发控制类型分为两大类:乐观并发控制和悲观并发控制
  
3、数据库引擎中的隔离级别:http://technet.microsoft.com/zh-cn/library/ms189122.aspx
     1)讲到了事务隔离级别控制的内容:
           事务隔离级别控制:
          读取数据时是否占用锁以及所请求的锁类型。
          占用读取锁的时间。
          引用其他事务修改的行的读取操作是否:
                 在该行上的排他锁被释放之前阻塞其他事务。
                检索在启动语句或事务时存在的行的已提交版本。
                 读取未提交的数据修改。
      2)列出了事务的隔离级别:
        未提交读(隔离事务的最低级别,只能保证不读取物理上损坏的数据)
         已提交读(数据库引擎的默认级别)
         可重复读
         可序列化(隔离事务的最高级别,事务之间完全隔离)

     3)选择事务隔离级别不影响为保护数据修改而获取的锁。事务总是在其修改的任何数据上获取排他锁并在事务完成之前持有该锁,不管为该事务设置了什么样的隔离级别。对于读取操作,事务隔离级别主要定义保护级别,以防受到其他事务所做更改的影响。
  
4、SET TRANSACTION ISOLATION LEVEL (Transact-SQL) 设置事务隔离级别http://technet.microsoft.com/zh-cn/library/ms173763.aspx
     该选项的作用与在事务内所有 SELECT 语句中的所有表上设置 HOLDLOCK 相同
5、总结:
     通过以上几篇文章基本上可以了解数据库事务和锁之间的关系。数据库事务隔级别也是由锁机制来最实现的。要想了解关于锁的更深层析的内容还需要专门学习锁的相关知识。

posted @ 2008-10-11 13:11 Sky Yi 阅读(5428) | 评论 (1)编辑 收藏

struts2笔记 - 配置

     摘要: 与Struts 1.X不同,Struts2引入了WebWork的配置机制,在很大程度上提高了配置的灵活度。通过使用配置可以配置如下内容: 配置类型 配置文件 ...  阅读全文

posted @ 2008-10-08 14:36 Sky Yi 阅读(597) | 评论 (0)编辑 收藏

struts2笔记 - helloworld

可以从Apache Struts 的官方站点(http://struts.apache.org)下载发布版本,当前最新的版本是2.0.9。下载的版本中包含struts2-core.jar和相关的依赖类库文件,示例程序,HTML格式的文档,和全部的源代码。

1,导入struts2需要的jar文件
commons-logging-1.0.4.jar              日志记录接口,可以配置选择使用jdk1.4 log 或者 log4j
freemarker-2.3.8.jar                        所有标签的模板都是用Freemarker编写
ognl-2.6.11.jar                               Objet Graph NavigationLanguage,Struts2表达式的基础。
struts2-core-2.0.9.jar                      struts2框架类库
xwork-2.0.4.jar                               xwork类库,struts2的基础

2,配置web.xml文件
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd"
>

<web-app>
  
<display-name>My Application</display-name>
  
<filter>
    
<!--配置struts过滤器-->
    
<filter-name>struts2</filter-name>
    
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  
</filter>

  
<filter-mapping>
    
<filter-name>struts2</filter-name>
    
<url-pattern>/*</url-pattern>
  
</filter-mapping>
</web-app>

3,配置struts.xml文件
必须要把该文件建立在编译好的WEB-INF下的classes目下
在myeclipse可以把它新建到src下。src下的所有资源文件等都会在保存时自动编译到classes目录
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd"
>

<struts>
    
<!-- 配置默认的包. -->
    
<package name="default" extends="struts-default">
         
    
</package>
</struts>


3,建立页面文件
Struts2提交一个请求的时候,输入的数据并没有直接送给下一个页面,而是送给了一个你提供的Java类。这种Java类被称为Action。当 Action执行之后,Struts2会选择一个结果作为返回,通常情况下是一个JSP页面,但是也可以是PDF文件,Excel表单或者Java Applet窗口。
这时需要做的是
  • 创建一个JSP页面来显示欢迎消息
  • 创建一个Action类来生成欢迎消息
  • 在struts.xml中创建一个配置项来关联上述的Action和JSP页面

  • 建立jsp页面
    第一行引入了struts2的标签库,在之后的页面中可以使用s标签了。这行在几乎所有的struts2应用的jsp页面中都会出现

    <%@ taglib prefix="s" uri="/struts-tags" %>
    <html>
        
    <head>
            
    <title>Hello World!</title>
        
    </head>
        
    <body>
            
    <s:form action="hello">
             
    <s:textfield name="name" label="name" />
           
    </s:form>
        
    </body>
    </html>

    创建action类
    execute方法用来处理业务操作
    import com.opensymphony.xwork2.ActionSupport;
    public class HelloWorld extends ActionSupport {

        
    private String name;
        
    public String execute() throws Exception {
           
    return SUCCESS;
        }


        
    public void setName(String name){
            
    this.name= name;
        }


        
    public String getName() {
            
    return name;
        }

    }

    配置struts.xml关联jsp和action
    <!DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    "http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
        
    <package name="tutorial" extends="struts-default">        
            
    <action name="HelloWorld" class="tutorial.HelloWorld">         
                
    <result>/HelloWorld.jsp</result>        
            
    </action>       
         
    </package>
    </struts>

    工作原理
    当浏览器发送请求 http://localhost:8080/tutorial/HelloWorld.action 的时候,在服务器上发生了如下事件:

    1. 服务器接收到对HelloWorld.action的请求,根据web.xml文件中的配置,所有以.action结尾的请求都会被 org.apache.struts2.dispatcher.FilterDispatcher过滤,所以这个请求被发送给 FilterDispatcher,FilterDispatcher是Struts 2 框架的入口点。
    2. Struts 2 框架查找HelloWorld.action对应的Java 类,发现是HelloWorld.java,之后Struts 2 框架实例化了一个HelloWorld类,并且调用了这个类的execute方法。
    3. execute方法设置了message的内容,并且返回SUCCESS。框架却定返回值SUCCESS,并且找到对应的内容HelloWorld.jsp,并且通知服务器将HelloWorld.jsp作为返回内容。
    4. 在HelloWorld.jsp被处理的过程中,<s:property value="message" />标签的内容被替换为HelloWorld 的getMessage方法调用的结果
    5. 根据HelloWorld.jsp内容生成的HTML内容被发回到请求的浏览器。
    结果类型(Result Type)
    Action 处理完成之后,会选择一个结果返回给客户,这个结果可能是简单的HTML页面,JSP页面,FreeMarker模板,Velocity模板,或者是一个 PDF文旦个或者是更复杂的JasperReports。一个Action可能有几个可选的结果类型,为了决定到底使用那个结果类型,Action类的 execute方法必须返回一个标记结果类型的字符串。
    struts.xml
    <action name="Logon" class="tutorial.Logon">
      <result type="redirect-action">Menu</result>
      <result name="input">/tutorial/Logon.jsp</result>
    </action>
    如果我们输入了用户名和密码,Logon Action会返回“success”。"success"是默认的返回结果,这个时候会使用Menu action作为结果。
    如果我们什么也不输入,Logon Action 会返回"input", Struts 2会使用Logon.jsp 作为结果返回

    posted @ 2008-10-08 14:31 Sky Yi 阅读(459) | 评论 (0)编辑 收藏

    struts2笔记 - 概述

    Struts 2 中不想要要在在处理和HTTP相关的操作,自需要使用框架的接口即可。
           在Strut 2 中不再会涉及到诸如 HttpServletRequest, HttpServletResponse, HttpSession等Http相关的Servlet接口类,取而代之的是Struts 2 的接口,例如RequestAware,SessionAware等。

    Struts 2 的标签基于 CSS,标签可以提供自己需要的HTML支持。
            Struts 2 的标签利用了CSS和模板,使用起来会非常方便,在Struts 1.x中我们需要使用Table来组织表单,但是在Struts 2中所有的标签自带了Table内容,可以方便的处理格式。例如<s:textfield> 标签自动添加了 <tr> <td> 等标签。

    有状态的Checkbox,可以以一种统一的方式记录checkbox状态的变化。
           在Struts 2中即使没有被选中的checkbox其内容仍然存在于Struts 2 框架中,不必像在Struts 1.x中那样需要做特殊的存在性判断。

     灵活的取消按钮,在取消按钮点击的时候可以指向一个不同的action。
           @TODO
           可以在制定Form的action的同时,制定cancel按钮的action,当点击submit和cancel的时候出现完全按不同的功能。

        第一等级的AJAX的支持,在普通struts 标签的基础上,使用AJAX增加了交互性和灵活性。
           Struts 2 的标签内置了Ajax的支持。Struts 2 的标签使用了Dojotoolkit Ajax框架,不但能够使用Ajax特性,而且能够使用非常丰富和强大的浏览器小控件,例如日期选择控件

        见到那集成Spring框架,非常简单的使用Spring框架提供的依赖注入功能。
           可以方便的使用Spring管理Struts 2 的action的创建,通过使用Spring可以充分的利用Spring的依赖诸如功能,并且能够很好的集成其他的框架,例如Hibernate,iBatis等。

        更多的返回形式,除了JSP还支持,JasperReports,JFreeChart, Action链,文件下载等。
           除了支持JSP的表现形式,还支持JasperResports报表, JFreechart图标,Action链,文件下载等。

        POJO表单,不再需要ActionForms,使用Javabean获得客户的收入或者将属性表示出来,
        完全消除了ActionForm组建,可以使用任意合适的类型来接受页面传来的数据或者将数据表现出来。ActionFrom可以使用POJO的 JavaBean来替代,JavaBean中的属性可以使用String,也可以使用具体的类型,例如Date,Int等。

        POJO Action,使用任意的类作为Action类,甚至可以使用接口。
           任何类都可以作为Action类,只要接口满足一些简单的定义,不需要在使用Action类似的基类,你可以完全自由的发挥。
    部署
        插件结构,使用jar文件扩展框架功能,不需要在做手动的配置,内置了JavaServer Faces, JasperResports, JFreeChart, Tiles等插件。
           扩展一个功能只需要添加一个插件,插件甚至可以热插拔,在你的应用不停止的情况下追加新的功能。

        集成了分析功能,可以方便的找到程序性能的问题点。
           可以不借助外力发现程序的热点,找到问题的所在,

        准确的报告错误,可以非常准确的指出程序的问题点。
           准确的报告运行时的错误,方便解决问题。

    维护
        Action容易测试,直接测试Struts 2的Action,不需要使用Mock Http对象来测试。
           Action是普通的类,不需要特殊的环境,所以Struts 2 的Action 特别容易测试。

        聪明的默认值,不需要配置不必要的配置,大部分的框架配置元素的都有非常合适的默认值,基本上你不需要在做任何配置。
           Struts 2 有很多的配置项,但是每一个都有默认值,基本额上不需要更改默认的选项即可保证最佳

        容易定制的控制器,可以定制每一个Action的处理过程。
           可以使用Intercepter来过滤每一个Action,在Action执行前后追加自定义的操作。

        集成了Debugging,可以使用内容之的debugging工具找到问题。
          
         灵活的标签库,可以通过修改FreeMarker模板来定制标签的输出,不需要在操作像天书异样的JSP Taglib API,模板语言支持,Freemarker和Velocity     
           可以自定义模板库,或者修改已有模板的内容来定制页面的显示。

    Struts 2 中使用的模式
    Command
    Chain of responsibility

    Struts2 处理流程概要




    上图来源于Struts2官方站点,是Struts 2 的整体结构。
    一个请求在Struts2框架中的处理大概分为以下几个步骤
    1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
    2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
    3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action
    4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
    5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
    6 ActionProxy创建一个ActionInvocation的实例。
    7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
    8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper
     
    在上述过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。

    posted @ 2008-10-08 13:56 Sky Yi 阅读(528) | 评论 (0)编辑 收藏