<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>satellite</title>
    <description></description>
    <link>http://satellite.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>关于Oracle数据库中的锁机制的研究</title>
        <author>satellite</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://satellite.javaeye.com">satellite</a>&nbsp;
          链接：<a href="http://satellite.javaeye.com/blog/233198" style="color:red;">http://satellite.javaeye.com/blog/233198</a>&nbsp;
          发表时间: 2008年08月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          本文通过对Oracle数据库锁机制的研究，首先介绍了Oracle数据库锁的种类，并描述了实际应用中遇到的与锁相关的异常情况，特别对经常遇到的由于等待锁而使事务被挂起的问题进行了定位及解决，并对死锁这一比较严重的现象，提出了相应的解决方法和具体的分析过程。 <br /><br />    数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时，在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据，破坏数据库的一致性。 <br /><br />    加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前，先向系统发出请求，对其加锁。加锁后事务就对该数据对象有了一定的控制，在该事务释放锁之前，其他的事务不能对此数据对象进行更新操作。 <br /><br />    在数据库中有两种基本的锁类型：排它锁（Exclusive Locks，即X锁）和共享锁（Share Locks，即S锁）。当数据对象被加上排它锁时，其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取，但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。 <br /><br />    在实际应用中经常会遇到的与锁相关的异常情况，如由于等待锁事务被挂起、死锁等现象，如果不能及时地解决，将严重影响应用的正常执行，而目前对于该类问题的解决缺乏系统化研究和指导，本文在总结实际经验的基础上，提出了相应的解决方法和具体的分析过程。 <br /><br />Oracle数据库的锁类型 <br /><br />    根据保护的对象不同，Oracle数据库锁可以分为以下几大类：DML锁（data locks，数据锁），用于保护数据的完整性；DDL锁（dictionary locks，字典锁），用于保护数据库对象的结构，如表、索引等的结构定义；内部锁和闩（internal locks and latches），保护数据库的内部结构。 <br /><br />    DML锁的目的在于保证并发情况下的数据完整性，本文主要讨论DML锁。在Oracle数据库中，DML锁主要包括TM锁和TX锁，其中TM锁称为表级锁，TX锁称为事务锁或行级锁。 <br /><br />    当Oracle执行DML语句时，系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后，系统再自动申请TX类型的锁，并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志，而只需检查TM锁模式的相容性即可，大大提高了系统的效率。TM锁包括了SS、SX、S、X等多种模式，在数据库中用0－6来表示。不同的SQL操作产生不同类型的TM锁。如表1所示。 <br /><br />    在数据行上只有X锁（排他锁）。在 Oracle数据库中，当一个事务首次发起一个DML语句时就获得一个TX锁，该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行DML语句时，第一个会话在该条记录上加锁，其他的会话处于等待状态。当第一个会话提交后，TX锁被释放，其他会话才可以加锁。 <br /><br />    当Oracle数据库发生TX锁等待时，如果不及时处理常常会引起Oracle数据库挂起，或导致死锁的发生，产生ORA-60的错误。这些现象都会对实际应用产生极大的危害，如长时间未响应，大量事务失败等。<br /><br /><br />TX锁等待的分析 <br /><br />    在介绍了有关地Oracle数据库锁的种类后，下面讨论如何有效地监控和解决锁等待现象，及在产生死锁时如何定位死锁的原因。 <br /><br />    监控锁的相关视图 数据字典是Oracle数据库的重要组成部分，用户可以通过查询数据字典视图来获得数据库的信息。和锁相关的数据字典视图如表2所示。 <br /><br />    TX锁等待的监控和解决在日常工作中，如果发现在执行某条SQL时数据库长时间没有响应，很可能是产生了TX锁等待的现象。为解决这个问题，首先应该找出持锁的事务，然后再进行相关的处理，如提交事务或强行中断事务。 <br /><br />    死锁的监控和解决在数据库中，当两个或多个会话请求同一个资源时会产生死锁的现象。死锁的常见类型是行级锁死锁和页级锁死锁，Oracle数据库中一般使用行级锁。下面主要讨论行级锁的死锁现象。 <br /><br />    当Oracle检测到死锁产生时，中断并回滚死锁相关语句的执行，报ORA-00060的错误并记录在数据库的日志文件alertSID.log中。同时在user_dump_dest下产生了一个跟踪文件，详细描述死锁的相关信息。 <br /><br />    在日常工作中，如果发现在日志文件中记录了ora-00060的错误信息，则表明产生了死锁。这时需要找到对应的跟踪文件，根据跟踪文件的信息定位产生的原因。 <br /><br />    如果查询结果表明，死锁是由于bitmap索引引起的，将IND_T_PRODUCT_HIS_STATE索引改为normal索引后，即可解决死锁的问题。<br /><br /><br /><br />引用原文地址：<a href="http://tech.ccidnet.com/art/1107/20061130/964113_1.html" target="_blank">http://tech.ccidnet.com/art/1107/20061130/964113_1.html</a>
          <br/><br/>
          <span style="color:red;">
            <a href="http://satellite.javaeye.com/blog/233198#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 27 Aug 2008 14:52:50 +0800</pubDate>
        <link>http://satellite.javaeye.com/blog/233198</link>
        <guid>http://satellite.javaeye.com/blog/233198</guid>
      </item>
      <item>
        <title>replace()与replaceAll()的区别</title>
        <author>satellite</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://satellite.javaeye.com">satellite</a>&nbsp;
          链接：<a href="http://satellite.javaeye.com/blog/224820" style="color:red;">http://satellite.javaeye.com/blog/224820</a>&nbsp;
          发表时间: 2008年08月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是:<br />1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串);<br />2)replaceAll的参数是regex,即基于规则表达式的替换,比如,可以通过replaceAll("\\d", "*")把一个字符串所有的数字字符都换成星号;<br />相同点是都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串,如果只想替换第一次出现的,可以使用<br />replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的时,只替换第一次出现的字符串;<br />另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的,即这两者也支持字符串的操作;<br />还有一点注意:执行了替换操作后,源字符串的内容是没有发生改变的.<br /><br />举例如下:<br />        <br />        String src = new String("ab43a2c43d");<br /><br />        System.out.println(src.replace("3","f"));=>ab4f2c4fd.<br />        System.out.println(src.replace('3','f'));=>ab4f2c4fd.<br />        System.out.println(src.replaceAll("\\d","f"));=>abffafcffd.<br />        System.out.println(src.replaceAll("a","f"));=>fb43fc23d.<br />        System.out.println(src.replaceFirst("\\d,"f"));=>abf32c43d<br />        System.out.println(src.replaceFirst("4","h"));=>abh32c43d.
          <br/><br/>
          <span style="color:red;">
            <a href="http://satellite.javaeye.com/blog/224820#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 06 Aug 2008 01:51:12 +0800</pubDate>
        <link>http://satellite.javaeye.com/blog/224820</link>
        <guid>http://satellite.javaeye.com/blog/224820</guid>
      </item>
      <item>
        <title>编写高性能的SQL语句注意事项(转)</title>
        <author>satellite</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://satellite.javaeye.com">satellite</a>&nbsp;
          链接：<a href="http://satellite.javaeye.com/blog/218423" style="color:red;">http://satellite.javaeye.com/blog/218423</a>&nbsp;
          发表时间: 2008年07月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在应用系统开发初期，由于开发数据库数据比较少，对于查询SQL语句，复杂视图的的编写等体会不出SQL语句各种写法的性能优劣，但是如果将应用系统提交实际应用后，随着数据库中数据的增加，系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据，劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍，可见对于一个系统不是简单地能实现其功能就可，而是要写出高质量的SQL语句，提高系统的可用性。<br />在多数情况下，Oracle使用索引来更快地遍历表，优化器主要根据定义的索引来提高性能。但是，如果在SQL语句的where子句中写的SQL代码不合理，就会造成优化器删去索引而使用全表扫描，一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来删除索引，这有助于写出高性能的SQL语句。<br /><br />SQL语句编写注意问题<br /><br />    下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中，即使某些列存在索引，但是由于编写了劣质的SQL，系统在运行该SQL语句时也不能使用该索引，而同样使用全表扫描，这就造成了响应速度的极大降低。<br /><br />1. IS NULL 与 IS NOT NULL<br /><br />    不能用null作索引，任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下，只要这些列中有一列含有null，该列就会从索引中排除。也就是说如果某列存在空值，即使对该列建索引也不会提高性能。<br /><br />任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。<br /><br />2. 联接列<br /><br />    对于有联接的列，即使最后的联接值为一个静态值，优化器是不会使用索引的。我们一起来看一个例子，假定有一个职工表（employee），对于一个职工的姓和名分成两列存放（FIRST_NAME和LAST_NAME），现在要查询一个叫比尔.克林顿（Bill Cliton）的职工。<br /><br />下面是一个采用联接查询的SQL语句，<br /><br /><br />select * from employss<br />where<br />first_name||''||last_name ='Beill Cliton'<br /><br /><br />   上面这条语句完全可以查询出是否有Bill Cliton这个员工，但是这里需要注意，系统优化器对基于last_name创建的索引没有使用。<br /><br />当采用下面这种SQL语句的编写，Oracle系统就可以采用基于last_name创建的索引。<br /><br /><br />Select * from employee<br />where<br />first_name ='Beill' and last_name ='Cliton'<br /><br /><br />    遇到下面这种情况又如何处理呢？如果一个变量（name）中存放着Bill Cliton这个员工的姓名，对于这种情况我们又如何避免全程遍历，使用索引呢？可以使用一个函数，将变量name中的姓和名分开就可以了，但是有一点需要注意，这个函数是不能作用在索引列上。下面是SQL查询脚本：<br /><br /><br />select * from employee<br />where<br />first_name = SUBSTR('&&name',1,INSTR('&&name',' ')-1)<br />and<br />last_name = SUBSTR('&&name',INSTR('&&name’,' ')+1)<br /><br /><br />3. 带通配符（%）的like语句<br /><br />    同样以上面的例子来看这种情况。目前的需求是这样的，要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句：<br /><br /><br />select * from employee where last_name like '%cliton%'<br /><br /><br />    这里由于通配符（%）在搜寻词首出现，所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况，但是一定要心中有底，通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时，优化器就能利用索引。在下面的查询中索引得到了使用：<br /><br /><br />select * from employee where last_name like 'c%'<br /><br />4. Order by语句<br /><br />    ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制，也可以将函数加入列中（象联接或者附加等）。任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。<br /><br />    仔细检查order by语句以找出非索引项或者表达式，它们会降低性能。解决这个问题的办法就是重写order by语句以使用索引，也可以为所使用的列建立另外一个索引，同时应绝对避免在order by子句中使用表达式。<br /><br />5. NOT<br /><br />   我们在查询时经常在where子句使用一些逻辑表达式，如大于、小于、等于以及不等于等等，也可以使用and（与）、or（或）以及not（非）。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子：<br /><br /><br />... where not (status ='VALID')<br /><br /><br />   如果要使用NOT，则应在取反的短语前面加上括号，并在短语前面加上NOT运算符。NOT运算符包含在另外一个逻辑运算符中，这就是不等于（&lt;>）运算符。换句话说，即使不在查询where子句中显式地加入NOT词，NOT仍在运算符中，见下例：<br /><br /><br />... where status &lt;>'INVALID'<br /><br /><br />再看下面这个例子：<br /><br /><br />select * from employee where salary&lt;>3000;<br /><br /><br />对这个查询，可以改写为不使用NOT：<br /><br /><br />select * from employee where salary&lt;3000 or salary>3000;<br /><br /><br />    虽然这两种查询的结果一样，但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引，而第一种查询则不能使用索引。<br /><br />6. IN和EXISTS<br /><br />    有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种格式的子查询。<br /><br />第一种格式是使用IN操作符：<br /><br /><br />... where column in(select * from ... where ...);<br /><br /><br />第二种格式是使用EXIST操作符：<br /><br /><br />... where exists (select 'X' from ...where ...);<br /><br /><br />    我相信绝大多数人会使用第一种格式，因为它比较容易编写，而实际上第二种格式要远比第一种格式的效率高。在Oracle中可以几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。<br /><br />    第二种格式中，子查询以‘select 'X'开始。运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句。这样优化器就不必遍历整个表而仅根据索引就可完成工作（这里假定在where语句中使用的列存在索引）。相对于IN子句来说，EXISTS使用相连子查询，构造起来要比IN子查询困难一些。<br /><br />    通过使用EXIST，Oracle系统会首先检查主查询，然后运行子查询直到它找到第一个匹配项，这就节省了时间。Oracle系统在执行IN子查询时，首先执行子查询，并将获得的结果列表存放在在一个加了索引的临时表中。在执行子查询之前，系统先将主查询挂起，待子查询执行完毕，存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。<br /><br />    同时应尽可能使用NOT EXISTS来代替NOT IN，尽管二者都使用了NOT（不能使用索引而降低速度），NOT EXISTS要比NOT IN查询效率更高。
          <br/><br/>
          <span style="color:red;">
            <a href="http://satellite.javaeye.com/blog/218423#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Jul 2008 23:48:09 +0800</pubDate>
        <link>http://satellite.javaeye.com/blog/218423</link>
        <guid>http://satellite.javaeye.com/blog/218423</guid>
      </item>
      <item>
        <title>(转)JAVA初始化顺序</title>
        <author>satellite</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://satellite.javaeye.com">satellite</a>&nbsp;
          链接：<a href="http://satellite.javaeye.com/blog/218165" style="color:red;">http://satellite.javaeye.com/blog/218165</a>&nbsp;
          发表时间: 2008年07月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          1、调用顺序: <br />   JAVA类首次装入时，会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的，静态成员变量和静态初始化块级别相同，非静态成员变量和非静态初始化块级别相同。 <br />    先初始化父类的静态代码--->初始化子类的静态代码--> <br />(创建实例时,如果不创建实例,则后面的不执行)初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函数 <br />2、类只有在使用New调用创建的时候才会被JAVA类装载器装入 <br />3、创建类实例时，首先按照父子继承关系进行初始化 <br />4、类实例创建时候，首先初始化块部分先执行，然后是构造方法；然后从本类继承的子类的初始化块执行，最后是子类的构造方法 <br />5、类消除时候，首先消除子类部分，再消除父类部分 <br /><br /><span style="color: red"><br />1． 父类静态成员和静态初始化块 ，按在代码中出现的顺序依次执行 <br />2． 子类静态成员和静态初始化块 ，按在代码中出现的顺序依次执行 <br />3． 父类实例成员和实例初始化块 ，按在代码中出现的顺序依次执行 <br />4． 父类构造方法 <br />5． 子类实例成员和实例初始化块 ，按在代码中出现的顺序依次执行 <br />6． 子类构造方法 <br /></span><br /><br />例子： <br />public abstract class Base { <br />//<span style="color: blue">5、初始化父类的非静态代码</span> <br />public int age = getNumber(100); <br />// <span style="color: blue">静态成员变量和静态初始化块级别相同 所以按照在代码中的顺序依次执行</span> <br />// <span style="color: blue">1、初始化父 静态成员变量 static int sage </span><br />static int sage = getNumber(50); <br />// <span style="color: blue">2、初始化父 静态初始化块 static </span><br />static { <br />System.out.println("base static block"); <br />} <br />{ <br />System.out.println("base nonstatic block"); <br />} <br />//<span style="color: blue">6、初始化父类构造函数</span> <br />Base() <br /><br />{ <br />System.out.println(age); <br />System.out.println("base start"); <br />draw();// <span style="color: blue">会调用子类覆盖后的方法</span> <br />System.out.println("base end"); <br /><br />} <br /><br />static int getNumber(int base) { <br />System.out.println("base.getNumber int" + base); <br />return base; <br />} <br /><br />public void draw() { <br />System.out.println("base.draw"); <br />} <br /><br />} <br /><br /><br />public class InitializeOrder extends Base { <br />//<span style="color: blue">7、初始化子类的非静态代码</span><br />public int age = getNumber(1001); <br />//<span style="color: blue">8、初始化子类的非静态代码</span> <br />private int _radius = getNumber(10); <br />//<span style="color: blue">3、初始化子 静态成员变量 static int sage</span> <br />static int sage = getNumber(250); <br />//<span style="color: blue">4、初始化子 静态初始化块 static</span> <br />static { <br />System.out.println("subclass static block"); <br />} <br />{ <br />System.out.println("subclass nonstatic block"); <br />} <br />//<span style="color: blue">9、初始化子类构造函数</span> <br />InitializeOrder(int radius) { <br />_radius = radius; <br />System.out.println(age); <br />System.out.println("initializeOrder initialized"); <br />} <br /><br />public void draw() { <br />System.out.println("initializeOrder.draw " + _radius); <br />} <br /><br />/** */ <br />/** <br />* @param args <br />*/ <br />public static void main(String[] args) { <br /><br />    new InitializeOrder(1000); <br />   } <br /><br />}
          <br/><br/>
          <span style="color:red;">
            <a href="http://satellite.javaeye.com/blog/218165#comments" style="color:red;">已有 <strong>0</strong> 人发表留言，猛击-&gt;&gt;<strong>这里</strong>&lt;&lt;-参与讨论</a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Jul 2008 16:09:13 +0800</pubDate>
        <link>http://satellite.javaeye.com/blog/218165</link>
        <guid>http://satellite.javaeye.com/blog/218165</guid>
      </item>
  </channel>
</rss>