<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[一天到晚游泳的鱼儿！----dannis]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[我需要一个自己的空间，一个能充分自由的发挥自己才智的空间，畅想我的未来！——丹尼斯]]></description>
<link>http://hi.baidu.com/zh%5Fdaniel</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[TCP/IP每层所对应的协议！以及OSI七层模型所对应的协议！]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/1d3b2eadd0d5440e4a36d674.html]]></link>
        <description><![CDATA[
		
		TCP/IP: <br>
数据链路层：ARP,RARP <br>
网络层： IP,ICMP,IGMP <br>
传输层：TCP ,UDP,UGP <br>
应用层：Telnet,FTP,SMTP,SNMP. <br>
<br>
OSI: <br>
物理层：EIA/TIA-232, EIA/TIA-499, V.35, V.24, RJ45, Ethernet, 802.3, 802.5, FDDI, NRZI, NRZ, B8ZS <br>
数据链路层：Frame Relay, HDLC, PPP, IEEE 802.3/802.2, FDDI, ATM, IEEE 802.5/802.2 <br>
网络层：IP，IPX，AppleTalk DDP <br>
传输层：TCP，UDP，SPX <br>
会话层：RPC,SQL,NFS,NetBIOS,names,AppleTalk,ASP,DECnet,SCP <br>
表示层:TIFF,GIF,JPEG,PICT,ASCII,EBCDIC,encryption,MPEG,MIDI,HTML <br>
应用层：FTP,WWW,Telnet,NFS,SMTP,Gateway,SNMP <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/1d3b2eadd0d5440e4a36d674.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/mfc%26%2347%3Bc%2B%2B%D1%A7%CF%B0%D0%C4%B5%C3%CC%E5%BB%E1">mfc&#47;c++学习心得体会</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/1d3b2eadd0d5440e4a36d674.html#comment">查看评论</a>]]></description>
        <pubDate>2008年11月21日 星期五  08:52 P.M.</pubDate>
        <category><![CDATA[mfc&#47;c++学习心得体会]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/1d3b2eadd0d5440e4a36d674.html</guid>
</item>

<item>
        <title><![CDATA[Fibonacci数列分析]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/589b16238f137c4993580779.html]]></link>
        <description><![CDATA[
		
		<p>Fibonacci数列F(n)递归地定义为：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  n&lt;=2<br>
F(n)={<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; F(n-1)+F(n-2)&nbsp;&nbsp;&nbsp;&nbsp;  n&gt;2</p>
<p>列出前几项：1，1，2，3，5，8，13，21，34。。。</p>
<p>&nbsp;&nbsp;&nbsp;  注意到这些数字没有，很多都是在大自然中出现的，我知道的少，不过你可以在互联网上搜一下，关键词：黄金分割。</p>
<p>没错，这个数列中体现了黄金分割，用数学方法很容易证明。首先它是发散的，但是不妨假设F(n+1)/F(n)是可以收敛的，设e=limF(n+1)/F(n)，由递推方程：F(n)=F(n-1)+F(n-2)，两边同除F(n-1)得（在极限情况下）：e=1+1/e，解出来就得e=1.618…，同时也得知它近似地相当于指数数列1.618^n，至少会以这样的增涨率增涨。</p>
<p>&nbsp;&nbsp;&nbsp;  以下总结一下Fibonacci数列的计算方法。</p>
<p>1，直接递归计算。</p>
<p>int fibonacci(int n)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  if(n&lt;=2)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  return 1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  return fibonacci(n-1)+fibonacci(n-2);<br>
}</p>
<p>&nbsp;&nbsp;&nbsp;  它的计算效率同它的数值增涨效率一样是指数型的（O(1.618^n)），因为它会在递归中重复计算子问题，改进的方法就是&lsquo;打表&rsquo;，把已经计算过的F(n)记录下来，在以后的计算中只管用就是了，也叫备忘录方法，也是DP算法的一个组成部分。</p>
<p>&nbsp;&nbsp;&nbsp;  2、备忘录方法。</p>
<p>int fibonacci(int n)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  if(mem(n)&gt;0)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  return mem(n);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  return mem(n)=fibonacci(n-1)+fibonacci(n-1);<br>
}</p>
<p>&nbsp;&nbsp;&nbsp; 3. 非递归，先开一个表f(n)，然后由f(1)=f(2)=1开始计算。</p>
<p>inf fibonacci(int n)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  if(n&lt;=2)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  return 1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  int *f=new int[n+1];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  f[1]=f[2]=1;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  for(int i=3;i&lt;=n;++i)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  f[i]=f[i-1]+f[i-2];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  int result=f[n];<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  delete[] f;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  return result;<br>
}</p>
<p>&nbsp;&nbsp;&nbsp;  前者是自顶向下，后者是自底向上，其效率是一样的，都是O(n)。从指数型复杂度到线性复杂度，是多大的提高啊。然而效率还可以提高。</p>
<p>4.非递归</p>
<p> long   Fib1(int   n)   <br>
          {   <br>
              int   a,b,c;//C代表当前项，a和b分别代表当前项前面的第2项和第1项   <br>
              a=b=1;         //给a和b赋初值1   <br>
              if(n==1||n==2)   <br>
                return   1;   <br>
              else   <br>
                for(int   i=3;i&lt;=n;i++){   <br>
                    c=a+b;     //求出当前项   <br>
                    a=b;//把前面第1项赋给前面第2项   <br>
                    b=c;//把当前项赋给前面第1项   <br>
                  }   <br>
                    return   c;//返回所求的第n项   <br>
              }&nbsp;&nbsp;</p> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/589b16238f137c4993580779.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%C4%AC%C8%CF%B7%D6%C0%E0">默认分类</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/589b16238f137c4993580779.html#comment">查看评论</a>]]></description>
        <pubDate>2008年11月17日 星期一  09:26 P.M.</pubDate>
        <category><![CDATA[默认分类]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/589b16238f137c4993580779.html</guid>
</item>

<item>
        <title><![CDATA[经典设计模式描述解析]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/c5f0989406617419d31b701d.html]]></link>
        <description><![CDATA[
		
		创建型模式 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1、FACTORY&mdash;追MM少不了请吃饭了，麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西，虽然口味有所不同，但不管你带MM去麦当劳或肯德基，只管向服务员说&ldquo;来四个鸡翅&rdquo;就行了。麦当劳和肯德基就是生产鸡翅的Factory <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  工厂模式：客户类和工厂类分开。消费者任何时候需要某种产品，只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时，工厂类也要做相应的修改。如：如何创建及如何向客户端提供。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2、BUILDER&mdash;MM最爱听的就是&ldquo;我爱你&rdquo;这句话了，见到不同地方的MM,要能够用她们的方言跟她说这句话哦，我有一个多种语言翻译机，上面每种语言都有一个按键，见到MM我只要按对应的键，它就能够用相应的语言说出&ldquo;我爱你&rdquo;这句话了，国外的MM也可以轻松搞掂，这就是我的&ldquo;我爱你&rdquo;builder。（这一定比美军在伊拉克用的翻译机好卖） <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  建造模式：将产品的内部表象和产品的生成过程分割开来，从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化，客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  3、FACTORY METHOD&mdash;请MM去麦当劳吃汉堡，不同的MM有不同的口味，要每个都记住是一件烦人的事情，我一般采用Factory Method模式，带着MM到服务员那儿，说&ldquo;要一个汉堡&rdquo;，具体要什么样的汉堡呢，让MM直接跟服务员说就行了。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  工厂方法模式：核心工厂类不再负责所有产品的创建，而是将具体创建的工作交给子类去做，成为一个抽象工厂角色，仅负责给出具体工厂类必须实现的接口，而不接触哪一个产品类应当被实例化这种细节。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  4、PROTOTYPE&mdash;跟MM用QQ聊天，一定要说些深情的话语了，我搜集了好多肉麻的情话，需要时只要copy出来放到QQ里面就行了，这就是我的情话prototype了。（100块钱一份，你要不要） <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  原始模型模式：通过给出一个原型对象来指明所要创建的对象的类型，然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类，产品类不需要非得有任何事先确定的等级结构，原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  5、SINGLETON&mdash;俺有6个漂亮的老婆，她们的老公都是我，我就是我们家里的老公Sigleton，她们只要说道&ldquo;老公&rdquo;，都是指的同一个人，那就是我(刚才做了个梦啦，哪有这么好的事) <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  单例模式：单例模式确保某一个类只有一个实例，而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的&ldquo;单一实例&rdquo;的需求时才可使用。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  结构型模式 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  6、ADAPTER&mdash;在朋友聚会上碰到了一个美女Sarah，从香港来的，可我不会说粤语，她不会说普通话，只好求助于我的朋友kent了，他作为我和Sarah之间的Adapter，让我和Sarah可以相互交谈了(也不知道他会不会耍我) <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  适配器（变压器）模式：把一个类的接口变换成客户端所期待的另一种接口，从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  7、BRIDGE&mdash;早上碰到MM，要说早上好，晚上碰到MM，要说晚上好；碰到MM穿了件新衣服，要说你的衣服好漂亮哦，碰到MM新做的发型，要说你的头发好漂亮哦。不要问我&ldquo;早上碰到MM新做了个发型怎么说&rdquo;这种问题，自己用BRIDGE组合一下不就行了 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  桥梁模式：将抽象化与实现化脱耦，使得二者可以独立的变化，也就是说将他们之间的强关联变成弱关联，也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系，从而使两者可以独立的变化。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  8、COMPOSITE&mdash;Mary今天过生日。&ldquo;我过生日，你要送我一件礼物。&rdquo;&ldquo;嗯，好吧，去商店，你自己挑。&rdquo;&ldquo;这件T恤挺漂亮，买，这条裙子好看，买，这个包也不错，买。&rdquo;&ldquo;喂，买了三件了呀，我只答应送一件礼物的哦。&rdquo;&ldquo;什么呀，T恤加裙子加包包，正好配成一套呀，小姐，麻烦你包起来。&rdquo;&ldquo;……&rdquo;，MM都会用Composite模式了，你会了没有？ <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  合成模式：合成模式将对象组织到树结构中，可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  9、DECORATOR&mdash;Mary过完轮到Sarly过生日，还是不要叫她自己挑了，不然这个月伙食费肯定玩完，拿出我去年在华山顶上照的照片，在背面写上&ldquo;最好的的礼物，就是爱你的Fita&rdquo;，再到街上礼品店买了个像框（卖礼品的MM也很漂亮哦），再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来……，我们都是Decorator，最终都在修饰我这个人呀，怎么样，看懂了吗？ <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  装饰模式：装饰模式以对客户端透明的方式扩展对象的功能，是继承关系的一个替代方案，提供比继承更多的灵活性。动态给一个对象增加功能，这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  10、FACADE&mdash;我有一个专业的Nikon相机，我就喜欢自己手动调光圈、快门，这样照出来的照片才专业，但MM可不懂这些，教了半天也不会。幸好相机有Facade设计模式，把相机调整到自动档，只要对准目标按快门就行了，一切由相机自动调整，这样MM也可以用这个相机给我拍张照片了。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  门面模式：外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口，使得子系统更易于使用。每一个子系统只有一个门面类，而且此门面类只有一个实例，也就是说它是一个单例模式。但整个系统可以有多个门面类。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  11、FLYWEIGHT&mdash;每天跟MM发短信，手指都累死了，最近买了个新手机，可以把一些常用的句子存在手机里，要用的时候，直接拿出来，在前面加上MM的名字就可以发送了，再不用一个字一个字敲了。共享的句子就是Flyweight，MM的名字就是提取出来的外部特征，根据上下文情况使用。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  享元模式：FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部，不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态，它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来，将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象，而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  12、PROXY&mdash;跟MM在网上聊天，一开头总是&ldquo;hi,你好&rdquo;,&ldquo;你从哪儿来呀？&rdquo;&ldquo;你多大了？&rdquo;&ldquo;身高多少呀？&rdquo;这些话，真烦人，写个程序做为我的Proxy吧，凡是接收到这些话都设置好了自动的回答，接收到其他的话时再通知我回答，怎么样，酷吧。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  代理模式：代理模式给某一个对象提供一个代理对象，并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下，客户不想或者不能够直接引用一个对象，代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象，而仅仅持有一个被代理对象的接口，这时候代理对象不能够创建被代理对象，被代理对象必须有系统的其他角色代为创建并传入。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  行为模式 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  13、CHAIN OF RESPONSIBLEITY&mdash;晚上去上英语课，为了好开溜坐到了最后一排，哇，前面坐了好几个漂亮的MM哎，找张纸条，写上&ldquo;Hi,可以做我的女朋友吗？如果不愿意请向前传&rdquo;，纸条就一个接一个的传上去了，糟糕，传到第一排的MM把纸条传给老师了，听说是个老处女呀，快跑! <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  责任链模式：在责任链模式中，很多对象由每一个对象对其下家的引用而接 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  起来形成一条链。请求在这个链上传递，直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求，系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择：承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  14、COMMAND&mdash;俺有一个MM家里管得特别严，没法见面，只好借助于她弟弟在我们俩之间传送信息，她对我有什么指示，就写一张纸条让她弟弟带给我。这不，她弟弟又传送过来一个COMMAND，为了感谢他，我请他吃了碗杂酱面，哪知道他说：&ldquo;我同时给我姐姐三个男朋友送COMMAND，就数你最小气，才请我吃面。&rdquo;，:-( <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  命令模式：命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开，委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来，使得请求的一方不必知道接收请求的一方的接口，更不必知道请求是怎么被接收，以及操作是否执行，何时被执行以及是怎么被执行的。系统支持命令的撤消。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  15、INTERPRETER&mdash;俺有一个《泡MM真经》，上面有各种泡MM的攻略，比如说去吃西餐的步骤、去看电影的方法等等，跟MM约会时，只要做一个Interpreter，照着上面的脚本执行就可以了。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  解释器模式：给定一个语言后，解释器模式可以定义出其文法的一种表示，并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后，使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构，也就是一系列的组合规则。每一个命令对象都有一个解释方法，代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  16、ITERATOR&mdash;我爱上了Mary，不顾一切的向她求婚。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Mary：&ldquo;想要我跟你结婚，得答应我的条件&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  我：&ldquo;什么条件我都答应，你说吧&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Mary：&ldquo;我看上了那个一克拉的钻石&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  我：&ldquo;我买，我买，还有吗？&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Mary：&ldquo;我看上了湖边的那栋别墅&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  我：&ldquo;我买，我买，还有吗？&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Mary：&ldquo;你的小弟弟必须要有50cm长&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  我脑袋嗡的一声，坐在椅子上，一咬牙：&ldquo;我剪，我剪，还有吗？&rdquo; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  …… <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  迭代子模式：迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集，聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中，从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象，每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  17、MEDIATOR&mdash;四个MM打麻将，相互之间谁应该给谁多少钱算不清楚了，幸亏当时我在旁边，按照各自的筹码数算钱，赚了钱的从我这里拿，赔了钱的也付给我，一切就OK啦，俺得到了四个MM的电话。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  调停者模式：调停者模式包装了一系列对象相互作用的方式，使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时，不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化，把对象在小尺度的行为上与其他对象的相互作用分开处理。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  18、MEMENTO&mdash;同时跟几个MM聊天时，一定要记清楚刚才跟MM说了些什么话，不然MM发现了会不高兴的哦，幸亏我有个备忘录，刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存，这样可以随时察看以前的记录啦。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  备忘录模式：备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下，将一个对象的状态捉住，并外部化，存储起来，从而可以在将来合适的时候把这个对象还原到存储起来的状态。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  19、OBSERVER&mdash;想知道咱们公司最新MM情报吗？加入公司的MM情报邮件组就行了，tom负责搜集情报，他发现的新情报不用一个一个通知我们，直接发布给邮件组，我们作为订阅者（观察者）就可以及时收到情报啦 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  观察者模式：观察者模式定义了一种一队多的依赖关系，让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时，会通知所有观察者对象，使他们能够自动更新自己。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  20、STATE&mdash;跟MM交往时，一定要注意她的状态哦，在不同的状态时她的行为会有不同，比如你约她今天晚上去看电影，对你没兴趣的MM就会说&ldquo;有事情啦&rdquo;，对你不讨厌但还没喜欢上的MM就会说&ldquo;好啊，不过可以带上我同事么？&rdquo;，已经喜欢上你的MM就会说&ldquo;几点钟？看完电影再去泡吧怎么样？&rdquo;，当然你看电影过程中表现良好的话，也可以把MM的状态从不讨厌不喜欢变成喜欢哦。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  状态模式：状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里，每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候，其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时，系统便改变所选的子类。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  21、STRATEGY&mdash;跟不同类型的MM约会，要用不同的策略，有的请电影比较好，有的则去吃小吃效果不错，有的去海边浪漫最合适，单目的都是为了得到MM的芳心，我的追MM锦囊中有好多Strategy哦。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  策略模式：策略模式针对一组算法，将每一个算法封装到具有共同接口的独立的类中，从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类，各种算法在具体的策略类中提供。由于算法和环境独立开来，算法的增减，修改都不会影响到环境和客户端。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  22、TEMPLATE METHOD&mdash;&mdash;看过《如何说服女生上床》这部经典文章吗？女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤(Template method)，但每个步骤针对不同的情况，都有不一样的做法，这就要看你随机应变啦(具体实现)； <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  模板方法模式：模板方法模式准备一个抽象类，将部分逻辑以具体方法以及具体构造子的形式实现，然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法，从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架，而将逻辑的细节留给具体的子类去实现。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  23、VISITOR&mdash;情人节到了，要给每个MM送一束鲜花和一张卡片，可是每个MM送的花都要针对她个人的特点，每张卡片也要根据个人的特点来挑，我一个人哪搞得清楚，还是找花店老板和礼品店老板做一下Visitor，让花店老板根据MM的特点选一束花，让礼品店老板也根据每个人特点选一张卡，这样就轻松多了； <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  访问者模式：访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话，接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统，它把数据结构和作用于结构上的操作之间的耦合解脱开，使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易，就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中，而不是分散到一个个的节点类中。当使用访问者模式时，要将尽可能多的对象浏览逻辑放在访问者类中，而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。 <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/c5f0989406617419d31b701d.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/mfc%26%2347%3Bc%2B%2B%D1%A7%CF%B0%D0%C4%B5%C3%CC%E5%BB%E1">mfc&#47;c++学习心得体会</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/c5f0989406617419d31b701d.html#comment">查看评论</a>]]></description>
        <pubDate>2008年11月02日 星期日  09:42 P.M.</pubDate>
        <category><![CDATA[mfc&#47;c++学习心得体会]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/c5f0989406617419d31b701d.html</guid>
</item>

<item>
        <title><![CDATA[经典逗女孩子的暴笑短信]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/c08cb24bdb5acef683025c7a.html]]></link>
        <description><![CDATA[
		
		<span ><br>
1.黑猩猩不小心踩到了长臂猿拉的大便，长臂猿温柔细心地帮其擦洗干净后它们相爱了。别人问起他们是怎么走到一起的？黑猩猩感慨地说：猿粪！都是猿粪啊！ <br>
　　<br>
　　<br>
　　2.我说：&ldquo;你是猪。&rdquo;你说：&ldquo;我是猪才怪！&rdquo;从此我就叫你猪才怪。终于有一天，你忍不住当着众人的面对我吼道：&ldquo;我不是猪才怪！&rdquo; <br>
　　<br>
　　<br>
　　3.明天你醒来，枕边躺着一只蚊子，身边有一封遗书，上书：我奋斗了一晚，也没能刺破你的脸，你的脸皮厚得让我无颜活在这世上！主啊~宽恕他吧！我是自杀的。 <br>
　　<br>
　　<br>
　　4.一日 一对苍蝇母子在一起吃午餐 <br>
　　儿子问苍蝇妈妈:为什么我们每天都吃大便啊 <br>
　　苍蝇妈妈生气的说:吃饭的时候不要说这么恶心的话,趁热吃!! <br>
　　<br>
　　<br>
　　5.一大学生被敌人抓了，敌人把他绑在了电线杆上，然后问他：说，你是哪里的？不说就电死你！大学生回了敌人一句话，结果被电死了，他说：我是电大的！ <br>
　　<br>
　　<br>
　　6.两个饺子结婚了，送走客人后新郎回到卧室，竟发现床上躺着一个肉丸子！新郎大惊，忙问新娘在哪？肉丸子害羞的说：讨厌，人家脱了衣服你就不认识啦！ <br>
　　<br>
　　<br>
　　7.四只老鼠吹牛：甲：我每天都拿鼠药当糖吃；乙：我一天不踩老鼠夹脚发痒；丙：我每天不过几次大街不踏实；丁：时间不早了，回家抱猫去咯 <br>
　　<br>
　　<br>
　　8.某晚，一裸男叫了一辆出租车，女司机目不转睛盯着看他，裸男大怒，吼道：你他妈没见过裸男呀！女司机也大怒：我看你他妈从哪儿掏钱！ <br>
　　<br>
　　<br>
　　9.你那边有没有电视啊?现在快点看中央一台赵本山被炸死了,pol.ice封锁了东北,19人死亡,11人失踪,1人被忽悠! <br>
　　<br>
　　<br>
　　10.一醉汉不慎从三楼掉下,引来路人围观,一pol.ice过来:发生什么事?醉汉:不清楚,我也是刚到 <br>
　　<br>
　　<br>
　　11.有个腼腆的男孩终于鼓足勇气问心爱的女孩：你喜欢什么样的男孩子？女孩说： 投缘的。男孩再问还是一样，他只好伤心地说：头扁一点的不行吗？ <br>
　　<br>
　　<br>
　　12.狼崽从出生就吃素。狼爸狼妈绞尽脑汁训练狼崽捕猎。终于有天狼爸狼妈欣慰地看到儿子狂追兔子。狼崽抓住兔子凶相毕露恶狠狠地说：小子！把胡萝卜交出来！ <br>
　　<br>
　　<br>
　　13.拉面店柜台前，一位漂亮女孩正排队等候。到她时，拉面师傅问：你要粗的还是细的？女孩答：你拉什么我就吃什么。 <br>
　　<br>
　　<br>
　　14.一对男女偷情，丈夫突然回家，男的没顾穿衣服就跳窗逃跑，走在大街上路上围观，男的装着若无其事看天：啊，这就是地球呀。路人说：cao，装鸡毛外星人。 <br>
　　<br>
　　<br>
　　15.白兔Q B灰狼后逃走，狼愤慨急追，兔以土抹身扮灰兔，戴眼镜看报纸，狼问：可看到一白兔？兔：是那只强*狼的白兔吗？狼羞：我KAO，这么快就见报了？ <br>
　　<br>
　　<br>
　　16.首长：同志们好！士兵：首长好！首长：同志们都晒黑了！士兵：首长更黑！首长拍一士兵的胸部说：这肌肉练得多好！士兵：报告首长，我是女兵。 <br>
　　<br>
　　<br>
　　17.我在马路边，看到一分钱，刚要弯腰捡，原来是口痰，我靠，谁吐这么圆？ <br>
　　<br>
　　<br>
　　18.护士看到一病人在病房喝酒，就走过去小声地对他说：&ldquo;小心肝！&rdquo;病人微笑着说：&ldquo;小宝贝。&rdquo; <br>
　　<br>
　　<br>
　　19.吝啬鬼有事外出，怕别人偷喝了他刚叫的酒，于是在纸上写了：我在杯里吐了一口痰。一会儿他回来，发现纸条上多了几个字：我也吐了一口！ <br>
　　<br>
　　<br>
　　20.某人骑车上街，过一路口，撒把前行。交警看见，惊呼：&ldquo;手掌好！&rdquo;某人高兴地挥手作答：&ldquo;同志们辛苦了！&rdquo; <br>
　　<br>
　　<br>
　　21.老师想让体育委员确认一下全班女生来齐没有，就对他说：&ldquo;你去把全班女生清一下。&rdquo;体委是个小色鬼，忙问：&ldquo;亲哪个？&rdquo;老师说：&ldquo;我晓得还要你去！&rdquo; <br>
　　<br>
　　<br>
　　22.初中数学课上，老师讲方程式变换，在讲台上袖子一挽大声喝道：同学们注意！我要变形了！…… </span> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/c08cb24bdb5acef683025c7a.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%C4%AC%C8%CF%B7%D6%C0%E0">默认分类</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/c08cb24bdb5acef683025c7a.html#comment">查看评论</a>]]></description>
        <pubDate>2008年09月29日 星期一  12:36 P.M.</pubDate>
        <category><![CDATA[默认分类]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/c08cb24bdb5acef683025c7a.html</guid>
</item>

<item>
        <title><![CDATA[锁初探2(sqlserver 2005)]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/c60564cbbc3e9519bf09e62a.html]]></link>
        <description><![CDATA[
		
		<pre><span style="color: rgb(0, 0, 0);">几个例子帮助大家加深印象 <br>设table1(A,B,C) <br>A B C <br>a1 b1 c1 <br>a2 b2 c2 <br>a3 b3 c3 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);">）排它锁 <br>新建两个连接 <br>在第一个连接中执行以下语句 <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> table1 <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> A</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">aa</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> B</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">b2</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay </span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">00:00:30</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 128);">--</span><span style="color: rgb(0, 128, 128);">等待30秒 </span><span style="color: rgb(0, 128, 128);"><br></span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br>在第二个连接中执行以下语句 <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> table1 <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> B</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">b2</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);">）共享锁 <br>在第一个连接中执行以下语句 <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> table1 </span><span style="color: rgb(0, 0, 255);">holdlock</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">holdlock人为加锁 <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> B</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">b2</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay </span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">00:00:30</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 128);">--</span><span style="color: rgb(0, 128, 128);">等待30秒 </span><span style="color: rgb(0, 128, 128);"><br></span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br><br>在第二个连接中执行以下语句 <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> A,C </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> table1 <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> B</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">b2</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> table1 <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> A</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">aa</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> B</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">b2</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br><br>若同时执行上述两个语句，则第二个连接中的select查询可以执行 <br>而update必须等待第一个事务释放共享锁转为排它锁后才能执行 即要等待30秒 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);">）死锁 <br>增设table2(D,E) <br>D E <br>d1 e1 <br>d2 e2 <br>在第一个连接中执行以下语句 <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> table1 <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> A</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">aa</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> B</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">b2</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay </span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">00:00:30</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> table2 <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> D</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">d5</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> E</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">e1</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br><br>在第二个连接中执行以下语句 <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> table2 <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> D</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">d5</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> E</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">e1</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay </span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">00:00:10</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> table1 <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> A</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">aa</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> B</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">b2</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br><br>同时执行，系统会检测出死锁，并中止进程 <br><br>补充一点: <br>Sql Server2000支持的表级锁定提示 <br><br></span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);"> 持有共享锁，直到整个事务完成，应该在被锁对象不需要时立即释放，等于SERIALIZABLE事务隔离级别 <br><br>NOLOCK 语句执行时不发出共享锁，允许脏读 ，等于 </span><span style="color: rgb(0, 0, 255);">READ</span><span style="color: rgb(0, 0, 0);"> UNCOMMITTED事务隔离级别 <br><br>PAGLOCK 在使用一个表锁的地方用多个页锁 <br><br>READPAST 让sql server跳过任何锁定行，执行事务，适用于READ UNCOMMITTED事务隔离级别只跳过RID锁，不跳过页，区域和表锁 <br><br>ROWLOCK 强制使用行锁 <br><br>TABLOCKX 强制使用独占表级锁，这个锁在事务期间阻止任何其他事务使用这个表 <br><br>UPLOCK 强制在读表时使用更新而不用共享锁 <br><br>应用程序锁: <br>应用程序锁就是客户端代码生成的锁，而不是sql server本身生成的锁 <br><br>处理应用程序锁的两个过程 <br><br>sp_getapplock 锁定应用程序资源 <br><br>sp_releaseapplock 为应用程序资源解锁 <br><br>注意: 锁定数据库的一个表的区别 <br><br></span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">FROM</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">WITH</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);">) 其他事务可以读取表，但不能更新删除 <br><br></span></pre>
<div><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> 如何锁一个表的某一行  </span><span style="color: rgb(0, 128, 128);">/*</span><span style="color: rgb(0, 128, 128);">          测试环境：windows 2K server + Mssql 2000          所有功能都进行测试过，并有相应的结果集，如果有什么疑义在论坛跟帖          关于版权的说明：部分资料来自互联网，如有不当请联系版主，版主会在第一时间处理。          功能：sql遍历文件夹下的文本文件名,当然你修改部分代码后可以完成各种文件的列表。  </span><span style="color: rgb(0, 128, 128);">*/</span><span style="color: rgb(0, 0, 0);">    A 连接中执行   </span><span style="color: rgb(0, 0, 255);">SET</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">TRANSACTION</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">ISOLATION</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">LEVEL</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">REPEATABLE</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">READ</span><span style="color: rgb(0, 0, 0);">   </span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);">   </span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> tablename </span><span style="color: rgb(0, 0, 255);">with</span><span style="color: rgb(0, 0, 0);"> (rowlock) </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> id</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);">   </span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay </span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">00:00:05</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">   </span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);">   B连接中如果执行   </span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> tablename </span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> colname</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">10</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> id</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 128);">--</span><span style="color: rgb(0, 128, 128);">则要等待5秒 </span><span style="color: rgb(0, 128, 128);"> </span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> tablename </span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> colname</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(255, 0, 0);">10</span><span style="color: rgb(255, 0, 0);">'</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> id </span><span style="color: rgb(128, 128, 128);">&lt;&gt;</span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 128);">--</span><span style="color: rgb(0, 128, 128);">可立即执行 </span><span style="color: rgb(0, 128, 128);"> </span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> 锁定数据库的一个表   </span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">FROM</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">WITH</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);">)    注意: 锁定数据库的一个表的区别   </span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">FROM</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">WITH</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);">)  其他事务可以读取表，但不能更新删除   </span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">FROM</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">WITH</span><span style="color: rgb(0, 0, 0);"> (TABLOCKX)  其他事务不能读取表,更新和删除</span></div>
<pre><br><span style="color: rgb(0, 0, 0);"><br></span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">FROM</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">WITH</span><span style="color: rgb(0, 0, 0);"> (TABLOCKX) 其他事务不能读取表,更新和删除 </span><br><span style="color: rgb(0, 0, 0);"><br>若同时执行上述两个语句，则select查询必须等待update执行完毕才能执行即要等待30秒 </span><br><br><span style="color: rgb(0, 0, 0);">SQL Server 2005中解决死锁问题 <br><br>数据库操作的死锁是不可避免的，本文并不打算讨论死锁如何产生，重点在于解决死锁，通过SQL Server </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2005</span><span style="color: rgb(0, 0, 0);">, 现在似乎有了一种新的解决办法。 <br><br>将下面的SQL语句放在两个不同的连接里面，并且在5秒内同时执行，将会发生死锁。 <br><br><br></span><span style="color: rgb(0, 0, 255);">use</span><span style="color: rgb(0, 0, 0);"> Northwind <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">insert</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">into</span><span style="color: rgb(0, 0, 0);"> Orders(CustomerId) </span><span style="color: rgb(0, 0, 255);">values</span><span style="color: rgb(0, 0, 0);">(@#ALFKI@#) <br>　　</span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay @#</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">05</span><span style="color: rgb(0, 0, 0);">@# <br>　　</span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> Orders </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> CustomerId </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> @#ALFKI@# <br></span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">print</span><span style="color: rgb(0, 0, 0);"> @#</span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);">@# <br><br>　　 <br>SQL Server对付死锁的办法是牺牲掉其中的一个，抛出异常，并且回滚事务。在SQL Server </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2000</span><span style="color: rgb(0, 0, 0);">，语句一旦发生异常，T</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">SQL将不会继续运行，上面被牺牲的连接中， </span><span style="color: rgb(0, 0, 255);">print</span><span style="color: rgb(0, 0, 0);"> @#</span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);">@#语句将不会被运行，所以我们很难在SQL Server 2000的T</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">SQL中对死锁进行进一步的处理。 <br><br>现在不同了，SQL Server 2005可以在T</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">SQL中对异常进行捕获，这样就给我们提供了一条处理死锁的途径： <br><br>下面利用的try ... catch来解决死锁。 <br><br><br></span><span style="color: rgb(0, 0, 255);">SET</span><span style="color: rgb(0, 0, 0);"> XACT_ABORT </span><span style="color: rgb(0, 0, 255);">ON</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">declare</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">&lt;=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br>　　 <br>　　</span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> try　　　 <br>　　　　</span><span style="color: rgb(0, 0, 255);">insert</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">into</span><span style="color: rgb(0, 0, 0);"> Orders(CustomerId) </span><span style="color: rgb(0, 0, 255);">values</span><span style="color: rgb(0, 0, 0);">(@#ALFKI@#) <br>　　　　</span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay @#</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">05</span><span style="color: rgb(0, 0, 0);">@# <br>　　　　</span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> Orders </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> CustomerId </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> @#ALFKI@# <br>　　　　 <br>　　　　</span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> <br>　　　　</span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> try <br>　　　　 <br>　　</span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> catch <br>　　　　</span><span style="color: rgb(0, 0, 255);">rollback</span><span style="color: rgb(0, 0, 0);"> <br>　　　　</span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay @#</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">03</span><span style="color: rgb(0, 0, 0);">@# <br>　　　　</span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> <br>　　　　</span><span style="color: rgb(0, 0, 255);">continue</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> catch <br></span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> <br><br>　　 <br>解决方法当然就是重试，但捕获错误是前提。rollback后面的waitfor不 <br><br>解决方法当然就是重试，但捕获错误是前提。rollback后面的waitfor不可少，发生冲突后需要等待一段时间，</span><span style="color: rgb(0, 128, 0);">@retry数目可以调整以应付不同的要求</span><span style="color: rgb(0, 0, 0);">。 <br><br>但是现在又面临一个新的问题: 错误被掩盖了，一但问题发生并且超过3次，异常却不会被抛出。SQL Server </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2005</span><span style="color: rgb(0, 0, 0);"> 有一个RaiseError语句，可以抛出异常，但却不能直接抛出原来的异常，所以需要重新定义发生的错误，现在，解决方案变成了这样: <br><br><br></span><span style="color: rgb(0, 0, 255);">declare</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">&lt;=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">tran</span><span style="color: rgb(0, 0, 0);"> <br>　　 <br>　　</span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> try　　　 <br>　　　　</span><span style="color: rgb(0, 0, 255);">insert</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">into</span><span style="color: rgb(0, 0, 0);"> Orders(CustomerId) </span><span style="color: rgb(0, 0, 255);">values</span><span style="color: rgb(0, 0, 0);">(@#ALFKI@#) <br>　　　　</span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay @#</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">05</span><span style="color: rgb(0, 0, 0);">@# <br>　　　　</span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> Orders </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> CustomerId </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> @#ALFKI@# <br>　　　　 <br>　　　　</span><span style="color: rgb(0, 0, 255);">commit</span><span style="color: rgb(0, 0, 0);"> <br>　　　　</span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> try <br>　　　　 <br>　　</span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> catch <br>　　　　</span><span style="color: rgb(0, 0, 255);">rollback</span><span style="color: rgb(0, 0, 0);"> <br>　　　　</span><span style="color: rgb(0, 0, 255);">waitfor</span><span style="color: rgb(0, 0, 0);"> delay @#</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">00</span><span style="color: rgb(0, 0, 0);">:</span><span style="color: rgb(128, 0, 0); font-weight: bold;">03</span><span style="color: rgb(0, 0, 0);">@# <br>　　　　</span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@r</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> <br>　　　　</span><span style="color: rgb(0, 0, 255);">continue</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> catch <br></span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> ERROR_NUMBER() </span><span style="color: rgb(128, 128, 128);">&lt;&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">0</span><span style="color: rgb(0, 0, 0);"> <br></span><span style="color: rgb(0, 0, 255);">begin</span><span style="color: rgb(0, 0, 0);"> <br>　　</span><span style="color: rgb(0, 0, 255);">declare</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@ErrorMessage</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">nvarchar</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(128, 0, 0); font-weight: bold;">4000</span><span style="color: rgb(0, 0, 0);">); <br>　　</span><span style="color: rgb(0, 0, 255);">declare</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@ErrorSeverity</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">; <br>　　</span><span style="color: rgb(0, 0, 255);">declare</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 128, 0);">@ErrorState</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">; <br>　　</span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> <br>　　　　</span><span style="color: rgb(0, 128, 0);">@ErrorMessage</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> ERROR_MESSAGE(), <br>　　　　</span><span style="color: rgb(0, 128, 0);">@ErrorSeverity</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> ERROR_SEVERITY(), <br>　　　　</span><span style="color: rgb(0, 128, 0);">@ErrorState</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> ERROR_STATE(); <br>　　</span><span style="color: rgb(0, 0, 255);">raiserror</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 128, 0);">@ErrorMessage</span><span style="color: rgb(0, 0, 0);">, <br>　　　　　　　 </span><span style="color: rgb(0, 128, 0);">@ErrorSeverity</span><span style="color: rgb(0, 0, 0);">, <br>　　　　　　　 </span><span style="color: rgb(0, 128, 0);">@ErrorState</span><span style="color: rgb(0, 0, 0);"> <br>　　　　　　　 ); <br></span><span style="color: rgb(0, 0, 255);">end</span><span style="color: rgb(0, 0, 0);"> <br><br>　　 <br>我希望将来SQL Server 2005能够直接抛出原有异常，比如提供一个无参数的RaiseError。 <br><br>因此方案有点臃肿，但将死锁问题封装到T</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">SQL中有助于明确职责，提高高层系统的清晰度。现在，对于DataAccess的代码，或许再也不需要考虑死锁问题了。 </span></pre> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/c60564cbbc3e9519bf09e62a.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%C4%AC%C8%CF%B7%D6%C0%E0">默认分类</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/c60564cbbc3e9519bf09e62a.html#comment">查看评论</a>]]></description>
        <pubDate>2008年08月22日 星期五  03:47 P.M.</pubDate>
        <category><![CDATA[默认分类]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/c60564cbbc3e9519bf09e62a.html</guid>
</item>

<item>
        <title><![CDATA[锁初探1(sqlserver 2005)]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/bad7882b807f52fce7cd4029.html]]></link>
        <description><![CDATA[
		
		<pre><span style="color: rgb(0, 0, 255);">上次逛bbs看到一牛人的评述，很NB，在这里与大伙分享下<br>HOLDLOCK</span><span style="color: rgb(0, 0, 0);"> 将共享锁保留到事务完成，而不是在相应的表、行或数据页不再需要时就立即释放锁。</span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);"> 等同于 </span><span style="color: rgb(0, 0, 255);">SERIALIZABLE</span><span style="color: rgb(0, 0, 0);">。 <br>NOLOCK 不要发出共享锁，并且不要提供排它锁。当此选项生效时，可能会读取未提交的事务或一组在读取中间回滚的页面。有可能发生脏读。仅应用于 </span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> 语句。 <br>PAGLOCK 在通常使用单个表锁的地方采用页锁。 <br>READCOMMITTED 用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下，SQL Server </span><span style="color: rgb(128, 0, 0); font-weight: bold;">2000</span><span style="color: rgb(0, 0, 0);"> 在此隔离级别上操作。 <br>READPAST 跳过锁定行。此选项导致事务跳过由其它事务锁定的行（这些行平常会显示在结果集内），而不是阻塞该事务，使其等待其它事务释放在这些行上的锁。READPAST 锁提示仅适用于运行在提交读隔离级别的事务，并且只在行级锁之后读取。仅适用于 </span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> 语句。 <br>READUNCOMMITTED 等同于 NOLOCK。 <br>REPEATABLEREAD 用与运行在可重复读隔离级别的事务相同的锁语义执行扫描。 <br>ROWLOCK 使用行级锁，而不使用粒度更粗的页级锁和表级锁。 <br></span><span style="color: rgb(0, 0, 255);">SERIALIZABLE</span><span style="color: rgb(0, 0, 0);"> 用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 </span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);">。 <br>TABLOCK 使用表锁代替粒度更细的行级锁或页级锁。在语句结束前，SQL Server 一直持有该锁。但是，如果同时指定 </span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);">，那么在事务结束之前，锁将被一直持有。 <br>TABLOCKX 使用表的排它锁。该锁可以防止其它事务读取或更新表，并在语句或事务结束前一直持有。 <br>UPDLOCK 读取表时使用更新锁，而不使用共享锁，并将锁一直保留到语句或事务的结束。UPDLOCK 的优点是允许您读取数据（不阻塞其它事务）并在以后更新数据，同时确保自从上次读取数据后数据没有被更改。 <br>XLOCK 使用排它锁并一直保持到由语句处理的所有数据上的事务结束时。可以使用 PAGLOCK 或 TABLOCK 指定该锁，这种情况下排它锁适用于适当级别的粒度<br><br></span><span style="color: rgb(0, 0, 0);">锁的概述 <br><br>一. 为什么要引入锁 <br><br>多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: <br><br>丢失更新 <br>A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 <br><br>脏读 <br>A用户修改了数据,随后B用户又读出该数据,但A用户因为某些原因取消了对数据的修改,数据恢复原值,此时B得到的数据就与数据库内的数据产生了不一致 <br><br>不可重复读 <br>A用户读取数据,随后B用户读出该数据并修改,此时A用户再读取数据时发现前后两次的值不一致 <br><br>并发控制的主要方法是封锁,锁就是在一段时间内禁止用户做某些操作以避免产生数据不一致 <br><br>二 锁的分类 <br><br>锁的类别有两种分法： <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);">. 从数据库系统的角度来看：分为独占锁（即排它锁），共享锁和更新锁 <br><br>MS</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">SQL Server 使用以下资源锁模式。 <br><br>锁模式 描述 <br>共享 (S) 用于不更改或不更新数据的操作（只读操作），如 </span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> 语句。 <br>更新 (U) 用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。 <br>排它 (X) 用于数据修改操作，例如 </span><span style="color: rgb(0, 0, 255);">INSERT</span><span style="color: rgb(0, 0, 0);">、</span><span style="color: rgb(0, 0, 255);">UPDATE</span><span style="color: rgb(0, 0, 0);"> 或 </span><span style="color: rgb(0, 0, 255);">DELETE</span><span style="color: rgb(0, 0, 0);">。确保不会同时同一资源进行多重更新。 <br>意向锁 用于建立锁的层次结构。意向锁的类型为：意向共享 (</span><span style="color: rgb(0, 0, 255);">IS</span><span style="color: rgb(0, 0, 0);">)、意向排它 (IX) 以及与意向排它共享 (SIX)。 <br>架构锁 在执行依赖于表架构的操作时使用。架构锁的类型为：架构修改 (Sch</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">M) 和架构稳定性 (Sch</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">S)。 <br>大容量更新 (BU) 向表中大容量复制数据并指定了 TABLOCK 提示时使用。 <br><br>共享锁 <br>共享 (S) 锁允许并发事务读取 (</span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);">) 一个资源。资源上存在共享 (S) 锁时，任何其它事务都不能修改数据。一旦已经读取数据，便立即释放资源上的共享 (S) 锁，除非将事务隔离级别设置为可重复读或更高级别，或者在事务生存周期内用锁定提示保留共享 (S) 锁。 <br><br>更新锁 <br>更新 (U) 锁可以防止通常形式的死锁。一般更新模式由一个事务组成，此事务读取记录，获取资源（页或行）的共享 (S) 锁，然后修改行，此操作要求锁转换为排它 (X) 锁。如果两个事务获得了资源上的共享模式锁，然后试图同时更新数据，则一个事务尝试将锁转换为排它 (X) 锁。共享模式到排它锁的转换必须等待一段时间，因为一个事务的排它锁与其它事务的共享模式锁不兼容；发生锁等待。第二个事务试图获取排它 (X) 锁以进行更新。由于两个事务都要转换为排它 (X) 锁，并且每个事务都等待另一个事务释放共享模式锁，因此发生死锁。 <br><br>若要避免这种潜在的死锁问题，请使用更新 (U) 锁。一次只有一个事务可以获得资源的更新 (U) 锁。如果事务修改资源，则更新 (U) 锁转换为排它 (X) 锁。否则，锁转换为共享锁。 <br><br>排它锁 <br>排它 (X) 锁可以防止并发事务对资源进行访问。其它事务不能读取或修改排它 (X) 锁锁定的数据。 <br><br>意向锁 <br>意向锁表示 SQL Server 需要在层次结构中的某些底层资源上获取共享 (S) 锁或排它 (X) 锁。例如，放置在表级的共享意向锁表示事务打算在表中的页或行上放置共享 (S) 锁。在表级设置意向锁可防止另一个事务随后在包含那一页的表上获取排它 (X) 锁。意向锁可以提高性能，因为 SQL Server 仅在表级检查意向锁来确定事务是否可以安全地获取该表上的锁。而无须检查表中的每行或每页上的锁以确定事务是否可以锁定整个表。 <br><br>意向锁包括意向共享 (</span><span style="color: rgb(0, 0, 255);">IS</span><span style="color: rgb(0, 0, 0);">)、意向排它 (IX) 以及与意向排它共享 (SIX)。 <br><br>锁模式 描述 <br>意向共享 (</span><span style="color: rgb(0, 0, 255);">IS</span><span style="color: rgb(0, 0, 0);">) 通过在各资源上放置 S 锁，表明事务的意向是读取层次结构中的部分（而不是全部）底层资源。 <br>意向排它 (IX) 通过在各资源上放置 X 锁，表明事务的意向是修改层次结构中的部分（而不是全部）底层资源。IX 是 </span><span style="color: rgb(0, 0, 255);">IS</span><span style="color: rgb(0, 0, 0);"> 的超集。 <br>与意向排它共享 (SIX) 通过在各资源上放置 IX 锁，表明事务的意向是读取层次结构中的全部底层资源并修改部分（而不是全部）底层资源。允许顶层资源上的并发 </span><span style="color: rgb(0, 0, 255);">IS</span><span style="color: rgb(0, 0, 0);"> 锁。例如，表的 SIX 锁在表上放置一个 SIX 锁（允许并发 </span><span style="color: rgb(0, 0, 255);">IS</span><span style="color: rgb(0, 0, 0);"> 锁），在当前所修改页上放置 IX 锁（在已修改行上放置 X 锁）。虽然每个资源在一段时间内只能有一个 SIX 锁，以防止其它事务对资源进行更新，但是其它事务可以通过获取表级的 </span><span style="color: rgb(0, 0, 255);">IS</span><span style="color: rgb(0, 0, 0);"> 锁来读取层次结构中的底层资源。 <br><br>独占锁：只允许进行锁定操作的程序使用，其他任何对他的操作均不会被接受。执行数据更新命令时，SQL Server会自动使用独占锁。当对象上有其他锁存在时，无法对其加独占锁。 <br>共享锁：共享锁锁定的资源可以被其他用户读取，但其他用户无法修改它，在执行Select时，SQL Server会对对象加共享锁。 <br>更新锁：当SQL Server准备更新数据时，它首先对数据对象作更新锁锁定，这样数据将不能被修改，但可以读取。等到SQL Server确定要进行更新数据操作时，他会自动将更新锁换为独占锁，当对象上有其他锁存在时，无法对其加更新锁。 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);">. 从程序员的角度看：分为乐观锁和悲观锁。 <br>乐观锁：完全依靠数据库来管理锁的工作。 <br>悲观锁：程序员自己管理数据或对象上的锁处理。 <br><br>MS</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">SQLSERVER 使用锁在多个同时在数据库内执行修改的用户间实现悲观并发控制 <br><br>三 锁的粒度 <br>锁粒度是被封锁目标的大小,封锁粒度小则并发性高,但开销大,封锁粒度大则并发性低但开销小 <br><br>SQL Server支持的锁粒度可以分为为行、页、键、键范围、索引、表或数据库获取锁 <br><br>资源 描述 <br>RID 行标识符。用于单独锁定表中的一行。 <br>键 索引中的行锁。用于保护可串行事务中的键范围。 <br>页 </span><span style="color: rgb(128, 0, 0); font-weight: bold;">8</span><span style="color: rgb(0, 0, 0);"> 千字节 (KB) 的数据页或索引页。 <br>扩展盘区 相邻的八个数据页或索引页构成的一组。 <br>表 包括所有数据和索引在内的整个表。 <br>DB 数据库。 <br><br>四 锁定时间的长短 <br><br>锁保持的时间长度为保护所请求级别上的资源所需的时间长度。 <br><br>用于保护读取操作的共享锁的保持时间取决于事务隔离级别。采用 </span><span style="color: rgb(0, 0, 255);">READ</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">COMMITTED</span><span style="color: rgb(0, 0, 0);"> 的默认事务隔离级别时，只在读取页的期间内控制共享锁。在扫描中，直到在扫描内的下一页上获取锁时才释放锁。如果指定 </span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);"> 提示或者将事务隔离级别设置为 </span><span style="color: rgb(0, 0, 255);">REPEATABLE</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">READ</span><span style="color: rgb(0, 0, 0);"> 或 </span><span style="color: rgb(0, 0, 255);">SERIALIZABLE</span><span style="color: rgb(0, 0, 0);">，则直到事务结束才释放锁。 <br><br>根据为游标设置的并发选项，游标可以获取共享模式的滚动锁以保护提取。当需要滚动锁时，直到下一次提取或关闭游标（以先发生者为准）时才释放滚动锁。但是，如果指定 </span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);">，则直到事务结束才释放滚动锁。 <br><br>用于保护更新的排它锁将直到事务结束才释放。 <br>如果一个连接试图获取一个锁，而该锁与另一个连接所控制的锁冲突，则试图获取锁的连接将一直阻塞到： <br><br>将冲突锁释放而且连接获取了所请求的锁。 <br><br>连接的超时间隔已到期。默认情况下没有超时间隔，但是一些应用程序设置超时间隔以防止无限期等待 <br><br>五 SQL Server 中锁的自定义 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> 处理死锁和设置死锁优先级 <br><br>死锁就是多个用户申请不同封锁,由于申请者均拥有一部分封锁权而又等待其他用户拥有的部分封锁而引起的无休止的等待 <br><br>可以使用SET DEADLOCK_PRIORITY控制在发生死锁情况时会话的反应方式。如果两个进程都锁定数据，并且直到其它进程释放自己的锁时，每个进程才能释放自己的锁，即发生死锁情况。 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> 处理超时和设置锁超时持续时间。 <br><br></span><span style="color: rgb(0, 128, 0); font-weight: bold;">@@LOCK_TIMEOUT</span><span style="color: rgb(0, 0, 0);"> 返回当前会话的当前锁超时设置，单位为毫秒 <br><br></span><span style="color: rgb(0, 0, 255);">SET</span><span style="color: rgb(0, 0, 0);"> LOCK_TIMEOUT 设置允许应用程序设置语句等待阻塞资源的最长时间。当语句等待的时间大于 LOCK_TIMEOUT 设置时，系统将自动取消阻塞的语句，并给应用程序返回&quot;已超过了锁请求超时时段&quot;的 </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1222</span><span style="color: rgb(0, 0, 0);"> 号错误信息 <br><br>示例 <br>下例将锁超时期限设置为 </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0); font-weight: bold;">800</span><span style="color: rgb(0, 0, 0);"> 毫秒。 <br></span><span style="color: rgb(0, 0, 255);">SET</span><span style="color: rgb(0, 0, 0);"> LOCK_TIMEOUT </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1800</span><span style="color: rgb(0, 0, 0);"> <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);">) 设置事务隔离级别。 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">4</span><span style="color: rgb(0, 0, 0);"> ) 对 </span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);">、</span><span style="color: rgb(0, 0, 255);">INSERT</span><span style="color: rgb(0, 0, 0);">、</span><span style="color: rgb(0, 0, 255);">UPDATE</span><span style="color: rgb(0, 0, 0);"> 和 </span><span style="color: rgb(0, 0, 255);">DELETE</span><span style="color: rgb(0, 0, 0);"> 语句使用表级锁定提示。 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">5</span><span style="color: rgb(0, 0, 0);">) 配置索引的锁定粒度 <br>可以使用 sp_indexoption 系统存储过程来设置用于索引的锁定粒度 <br><br>六 查看锁的信息 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> 执行 </span><span style="color: rgb(0, 0, 255);">EXEC</span><span style="color: rgb(0, 0, 0);"> SP_LOCK 报告有关锁的信息 <br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> 查询分析器中按Ctrl</span><span style="color: rgb(128, 128, 128);">+</span><span style="color: rgb(0, 0, 0);">2可以看到锁的信息 <br><br>七 使用注意事项 <br><br>如何避免死锁 <br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> 使用事务时，尽量缩短事务的逻辑处理过程，及早提交或回滚事务； <br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> 设置死锁超时参数为合理范围，如：3分钟</span><span style="color: rgb(128, 128, 128);">-</span><span style="color: rgb(0, 0, 0);">10分种；超过时间，自动放弃本次操作，避免进程悬挂； <br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">3</span><span style="color: rgb(0, 0, 0);"> 优化程序，检查并避免死锁现象出现； <br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">4</span><span style="color: rgb(0, 0, 0);"> .对所有的脚本和SP都要仔细测试，在正是版本之前。 <br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">5</span><span style="color: rgb(0, 0, 0);"> 所有的SP都要有错误处理（通过</span><span style="color: rgb(0, 128, 0);">@error</span><span style="color: rgb(0, 0, 0);">） <br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">6</span><span style="color: rgb(0, 0, 0);"> 一般不要修改SQL SERVER事务的默认级别。不推荐强行加锁 <br><br>解决问题 如何对行 表 数据库加锁 <br><br>八 几个有关锁的问题 <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> 如何锁一个表的某一行 <br><br></span><span style="color: rgb(0, 0, 255);">SET</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">TRANSACTION</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">ISOLATION</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">LEVEL</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">READ</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">UNCOMMITTED</span><span style="color: rgb(0, 0, 0);"> <br><br></span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">FROM</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> ROWLOCK </span><span style="color: rgb(0, 0, 255);">WHERE</span><span style="color: rgb(0, 0, 0);"> id </span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(0, 0, 0);"> <br><br></span><span style="color: rgb(128, 0, 0); font-weight: bold;">2</span><span style="color: rgb(0, 0, 0);"> 锁定数据库的一个表 <br><br></span><span style="color: rgb(0, 0, 255);">SELECT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 128, 128);">*</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">FROM</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">table</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">WITH</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">HOLDLOCK</span><span style="color: rgb(0, 0, 0);">) <br><br>加锁语句： <br>sybase: <br></span><span style="color: rgb(0, 0, 255);">update</span><span style="color: rgb(0, 0, 0);"> 表 </span><span style="color: rgb(0, 0, 255);">set</span><span style="color: rgb(0, 0, 0);"> col1</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(0, 0, 0);">col1 </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(128, 0, 0); font-weight: bold;">0</span><span style="color: rgb(0, 0, 0);"> ; <br>MSSQL: <br></span><span style="color: rgb(0, 0, 255);">select</span><span style="color: rgb(0, 0, 0);"> col1 </span><span style="color: rgb(0, 0, 255);">from</span><span style="color: rgb(0, 0, 0);"> 表 (tablockx) </span><span style="color: rgb(0, 0, 255);">where</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(128, 0, 0); font-weight: bold;">1</span><span style="color: rgb(128, 128, 128);">=</span><span style="color: rgb(128, 0, 0); font-weight: bold;">0</span><span style="color: rgb(0, 0, 0);"> ; <br>oracle: <br>LOCK </span><span style="color: rgb(0, 0, 255);">TABLE</span><span style="color: rgb(0, 0, 0);"> 表 </span><span style="color: rgb(128, 128, 128);">IN</span><span style="color: rgb(0, 0, 0);"> EXCLUSIVE MODE ； <br>加锁后其它人不可操作，直到加锁用户解锁，用commit或rollback解锁 <br><br><br><br></span></pre> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/bad7882b807f52fce7cd4029.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%C4%AC%C8%CF%B7%D6%C0%E0">默认分类</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/bad7882b807f52fce7cd4029.html#comment">查看评论</a>]]></description>
        <pubDate>2008年08月22日 星期五  03:47 P.M.</pubDate>
        <category><![CDATA[默认分类]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/bad7882b807f52fce7cd4029.html</guid>
</item>

<item>
        <title><![CDATA[死锁相关参考知识]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/0a1ab26e5a7e7bdc80cb4aeb.html]]></link>
        <description><![CDATA[
		
		<font color="#000000"><font size="3"><font face="宋体"><strong>1.&nbsp;&nbsp;&nbsp;&nbsp;  下面关于死锁问题的叙述哪些是正确的, 哪些是错误的, 说明原因.<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (1) 参与死锁的所有进程都占有资源;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (2) 参与死锁的所有进程中至少有两个进程占有资源;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (3) 死锁只发生在无关进程之间;<br>
<br>
(4) 死锁可发生在任意进程之间.<br>
<br>
答：说法（1）是错误的，应该是参与死锁的所有进程都等待资源。<br>
<br>
说法(2)正确。 参与死锁的进程至少有两个，设为p1,p2，p1占有资源r1而等待资源r2，p2占有资源r2而等待资源r1。<br>
<br>
说法(3)错误。死锁也可能发生在相关进程之间。<br>
<br>
说法(4)正确，死锁既可能发生在相关进程之间，也可能发生在无关进程之间。即死锁可发生在任意进程之间。<br>
<br>
2.&nbsp;&nbsp;&nbsp;&nbsp;  试证明当每个资源类中仅有一个资源实例时，资源分配图中的环路是死锁的充要条件。<br>
<br>
证明：先证明充分条件：<br>
<br>
用反证法，假设每个资源类中仅有一个资源实例时，资源分配图的环路是可约简的，那么说明环路外至少有一个非孤立且没有请求边的进程节点pk占有一个资源类rk中的一个实例,而rk中的另外一个实例被环路中某个进程占有。说明rk中有两个以上的资源实例，与前提矛盾。所以说，每个资源类中仅有一个资源实例时，资源分配图的环路是不可约简的，根据死锁定理，得出结论每个资源类中仅有一个资源实例时，资源分配图若存在环路就产生死锁。<br>
<br>
&nbsp;&nbsp;  再证明必要条件：若死锁产生，则存在一个循环等待进程序列&lt;p1,p2,p3……pn&gt;,进程p1正等待资源类rk1中唯一的一个实例，而rk1又被进程p2所占用；进程p2正等待资源类rk2中唯一的一个实例，而rk2又被进程p3所占用；……; 进程pn正等待资源类rkn中唯一的一个实例，而rkn又被进程p1所占用。能看出，画出的资源分配图存在环路。<br>
<br>
3.&nbsp;&nbsp;&nbsp;&nbsp;  什么叫饥饿？什么叫饿死？什么叫活锁？举例说明之．<br>
<br>
答：在一个动态系统中，资源请求与释放是经常性发生的进程行为．对于每类系统资源，操作系统需要确定一个分配策略，当多个进程同时申请某类资源时，由分配策略确定资源分配给进程的次序。 资源分配策略可能是公平的(fair)，能保证请求者在有限的时间内获得所需资源；资源分配策略也可能是不公平的(unfair)，即不能保证等待时间上界的存在。 在后一种情况下，即使系统没有发生死锁，某些进程也可能会长时间等待．当等待时间给进程推进和响应带来明显影响时，称发生了进程饥饿(starvation)，当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时称该进程被饿死(starve to death)。在忙式等待条件下发生的饥饿，称为活锁．<br>
<br>
考虑一台打印机分配的例子，当有多个进程需要打印文件时，系统按照短文件优先的策略排序，该策略具有平均等待时间短的优点，似乎非常合理，但当短文件打印任务源源不断时，长文件的打印任务将被无限期地推迟，导致饥饿以至饿死。<br>
<br>
4.&nbsp;&nbsp;&nbsp;&nbsp;  死锁与饿死之间有何相同点和不同点?<br>
<br>
答：饿死与死锁有一定联系：二者都是由于竞争资源而引起的，但又有明显差别，主要表现在如下几个方面：<br>
<br>
(1) 从进程状态考虑，死锁进程都处于等待状态，忙式等待(处于运行或就绪状态)的进程并非处于等待状态，但却可能被饿死；<br>
<br>
(2) 死锁进程等待永远不会被释放的资源，饿死进程等待会被释放但却不会分配给自己的资源，表现为等待时限没有上界(排队等待或忙式等待)；<br>
<br>
(3) 死锁一定发生了循环等待，而饿死则不然。这也表明通过资源分配图可以检测死锁存在与否，但却不能检测是否有进程饿死；<br>
<br>
(4) 死锁一定涉及多个进程，而饥饿或被饿死的进程可能只有一个。<br>
<br>
饥饿和饿死与资源分配策略(policy)有关，因而防止饥饿与饿死可从公平性考虑，确保所有进程不被忽视，如FCFS分配算法。<br>
<br>
5.&nbsp;&nbsp;&nbsp;&nbsp;  何谓银行家算法的保守性? 举例说明之.<br>
<br>
答：银行家算法的保守性是指银行家算法只给出了进程需要资源的最大量，而所需资源的具体申请和释放顺序仍是未知的，因而银行家只能往最坏处设想．<br>
<br>
例如：书中举例p119页。例5.5。<br>
<br>
6.&nbsp;&nbsp;&nbsp;&nbsp;  能否给出避免死锁的充要性算法? 为什么?<br>
<br>
答：目前关于避免死锁的算法，如银行家算法是充分性算法，即确保系统时刻处于安全状态，这是在系统已知每个进程所需资源最大量的条件下可以给出的最好结果。如果系统不仅知道每个进程所需资源的最大量，而且知道进程有关资源的活动序列，在这个更强的条件下，则可以给出避免死锁的充要性算法（读者可以证明），但其复杂度是很高(NP完全)的。而且由于程序中分支和循环的存在，事先给出进程有关资源的命令序列一般是不可能的。<br>
<br>
7.  设有一个Ｔ型路口, 其中A、B、C、D处各可容纳一辆车，车行方向如下图所示，试找出死锁并用有序分配法消除之. 要求资源编号合理.<br>
<br>
解：(1)E方向两台车分别位于A和B；S方向一台车位于C；W方向一台车位于D。(2)S方向两台车分别位于B和C；E方向一台车位于A；W方向一台车位于D。<br>
<br>
 设位置资源C、B、A、D的编号从低到高依次为1、2、3、4，管理四个位置的信号量分别为s1,s2,s3,s4，信号量的初值均为1。车辆活动如下：<br>
<br>
semaphore s1=1,s2=1,s3=1,s4=1;<br>
<br>
W ：直行<br>
<br>
P(s1); // 按序申请<br>
<br>
P(s4);<br>
<br>
驶入 D;<br>
<br>
驶入 C;<br>
<br>
V(s4);<br>
<br>
驶出 C;<br>
<br>
V(s1);<br>
&nbsp;&nbsp;&nbsp;  <br>
<br>
E ：左转<br>
<br>
P(s2);<br>
<br>
驶入 B;<br>
<br>
P(s3) ；<br>
<br>
驶入 A;<br>
<br>
V(S2)<br>
<br>
P(s4) ；<br>
<br>
驶入 D;<br>
<br>
V(s3) ；<br>
<br>
驶出 D;<br>
<br>
V(s4);<br>
&nbsp;&nbsp;&nbsp;  <br>
<br>
S ：左转<br>
<br>
P(s1);<br>
<br>
驶入 C;<br>
<br>
P(s2) ；<br>
<br>
驶入 B;<br>
<br>
V(S1)<br>
<br>
P(s3) ；<br>
<br>
驶入 A;<br>
<br>
V(s2) ；<br>
<br>
驶出 A;<br>
<br>
V(s3);<br>
<br>
8.  设系统中仅有一个资源类, 其中共有M个资源实例, 使用此类资源的进程个数共有N个, 它们所需资源最大量总和为S, 试证明发生死锁的必要条件是S&#179;M+N.<br>
<br>
答：证明：假定发生死锁，那么Alloc(1)+Alloc(2)+…+Alloc(N)=M，(Alloc(i)表示第i进程已分配的资源量)。Need(1)+Need(2)+…Need(N) &#179;N。（Need(i)表示第i进程还需要的资源量)<br>
<br>
所以，发生死锁时，所有进程所需资源的总量&#179;SM+N。<br>
<br>
9.  在银行家算法中，若出现如下资源分配情况：<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Allocation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Need&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Available&nbsp;&nbsp;&nbsp;&nbsp;  <br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C  D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C  D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C  D<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;  P0:  0  0  3  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  0  1  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1  6  2  3<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P1:  1  0  0  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1  7  5  0<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P2:  1  3  5  4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2  3  5  6<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P3:  0  3  3  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  6  5  2<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P4:  0  0  1  4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  6  5  6<br>
<br>
试问：(1)当前状态是否安全？<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (2)如果进程P2提出安全请求Request[2]=(1,2,2,2),系统能否将资源分配给它？说明原因．<br>
<br>
解：（1）当前状态是安全状态。<br>
<br>
运行安全性检查算法如下：<br>
<br>
&nbsp;&nbsp;&nbsp;  1）Work = Available；Finish = false；<br>
<br>
&nbsp;&nbsp;&nbsp;  2）寻找满足如下条件的i:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Finish[i]==false并且Need[i]≤Work[i]；<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  如果不存在，则转步骤4）；<br>
<br>
&nbsp;&nbsp;&nbsp;  3）Work = Work + Allocation[i]；Finish[i] = true；<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  转步骤2）<br>
<br>
4）如果对于所有i，Finish[i] = true，则系统处于安全状态，否则处于不安全状态。<br>
<br>
  　令Work = Available=（1, 6, 2, 3）<br>
<br>
运行安全性检测算法，Finish[0]=false并且Need[0]=(0 0 1 2)&lt;Work,<br>
<br>
则Work = Work + Allocation[0]=（1, 6, 2, 3）+（0, 0, 3, 2）=（1, 6, 5, 5）；Finish[0] = true；<br>
<br>
Finish[3]=false并且Need[3]=（0, 6, 5, 2）&lt;Work,<br>
<br>
则Work = Work + Allocation[3]=（1, 6, 5, 5）+（0, 3, 3, 2）=（1, 9, 8, 7）；Finish[3] = true；<br>
<br>
Finish[4]=false并且Need[4=（0, 6, 5, 6）&lt;Work,<br>
<br>
则Work = Work + Allocation[4]=（1, 9, 8, 7）+（0, 0, 1, 4 ）=（1, 9, 9, 11）；Finish[4] = true；<br>
<br>
Finish[1]=false并且Need[1]=（1, 7, 5, 0）&lt;Work,<br>
<br>
则Work = Work + Allocation[4]=（1, 9, 9, 11）+(1, 0, 0, 0 )=(2, 9, 9, 11)；Finish[1] = true；<br>
<br>
Finish[2]=false并且Need[2]=（2, 3, 5, 6）&lt;Work,<br>
<br>
则Work = Work + Allocation[4]=（2, 9, 9, 11）+（1, 3, 5, 4 ）=（3, 12, 14, 15）；Finish[2] = true；<br>
<br>
  可以找到一个安全进程序列&lt;p0 ，p3 ，p4 ，p1 ,p2&gt;，它使Finish=true，对于所有0≤i≤4，因而可以断言系统当前处于安全状态．<br>
<br>
（2）运行银行家算法，由于Request[2]=（1, 2, 2, 2）&#163;Need[2]=（2, 3, 5, 6），因而请求合法。进一步，Request[2]=（1, 2, 2, 2）&#163;Available=（1, 6, 2, 3），故该请求是可以满足的。假设将资源分配给p2，则系统状态变为:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Allocation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Need&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Available&nbsp;&nbsp;&nbsp;&nbsp;  <br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C  D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C  D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C  D<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;  P0:  0  0  3  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  0  1  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  4  0  1<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P1:  1  0  0  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1  7  5  0<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P2:  2  5  7  6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1  1  3  4<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P3:  0  3  3  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  6  5  2<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P4:  0  0  1  4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  6  5  6<br>
<br>
运行安全性检测算法，Work=Available=（0, 4, 0, 1），Finish=false，此时所有Need&#163;Work均不成立，结果Finish[i[均为false，不存在安全进程序列，系统处于不安全状态。系统将取消资源分配并恢复原来状态，进程p2等待。<br>
<br>
10．某系统采用死锁检测手段发现死锁，设系统中资源类集合为{A，B，C}，资源类A中共有8个实例，资源类B中共有6个实例，资源类C中共有5个实例．又设系统中进程集合为{p1,p2,p3,p4,p5,p6}, 某时刻系统状态如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Allocation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Request&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  Available<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A&nbsp;&nbsp;  B&nbsp;&nbsp;  C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A&nbsp;&nbsp;  B&nbsp;&nbsp;  C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A&nbsp;&nbsp;  B&nbsp;&nbsp;  C<br>
<br>
  p1:&nbsp;&nbsp;&nbsp;  1&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2&nbsp;&nbsp;&nbsp;  2&nbsp;&nbsp;  1<br>
<br>
  p2:&nbsp;&nbsp;&nbsp;  3&nbsp;&nbsp;  2&nbsp;&nbsp;  1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;  0<br>
<br>
  p3:&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  1&nbsp;&nbsp;  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;  2<br>
<br>
  p4:&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;  0<br>
<br>
  p5:&nbsp;&nbsp;&nbsp;  2&nbsp;&nbsp;  1&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  3&nbsp;&nbsp;&nbsp;  1<br>
<br>
  p6:&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;  1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0&nbsp;&nbsp;  0&nbsp;&nbsp;&nbsp;  0<br>
<br>
(1)&nbsp;&nbsp;&nbsp;  在上述状态下系统依次接受如下请求：Request[1]=(1,0,0)；Request[2]=(2,1,0)；&nbsp;&nbsp;  Request[4]=(0,0,2)．给出系统状态变化情况，并说明没有死锁．<br>
<br>
答：如果系统只是接受请求，但是没有分配资源给进程，那么系统状态变为：<br>
<br>
Allocation&nbsp;&nbsp;  Request&nbsp;&nbsp;  Available<br>
<br>
A  B  C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C&nbsp;&nbsp;&nbsp;  A  B  C<br>
<br>
p1:&nbsp;&nbsp;  1  0  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1  0  0&nbsp;&nbsp;&nbsp;  2  2  1<br>
<br>
p2:&nbsp;&nbsp;  3  2  1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2  1  0<br>
<br>
p3:&nbsp;&nbsp;  0  1  2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2  0  2<br>
<br>
p4:&nbsp;&nbsp;  0  0  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  0  2<br>
<br>
p5:&nbsp;&nbsp;  2  1  0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  3  1<br>
<br>
p6:&nbsp;&nbsp;  0  0  1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0  0  0<br>
<br>
在该状态下运行死锁检测算法，可以找到一个进程序列&lt;p4,p1,p2,p3,p5,p6&gt;，它使Finish=true，对于所有1≤i≤6，因而可以断言系统当前没有进入死锁状态。<br>
<br>
(2)&nbsp;&nbsp;&nbsp;  在由(1)所确定的状态下系统接收如下请求：Request[1]=(0,3,1)，说明此时已发生死锁，并找出参与死锁的进程．<br>
<br>
答：设在（1）的状态下系统接收如下请求：Request[1]=(0,3,1)，则系统状态变为：<br>
<br>
Allocation  Request  Available<br>
<br>
A  B  C&nbsp;&nbsp;&nbsp;&nbsp;  A  B  C&nbsp;&nbsp;  A  B  C<br>
<br>
p1:&nbsp;&nbsp;&nbsp;&nbsp;  2  0  0&nbsp;&nbsp;&nbsp;&nbsp;  0  3  1&nbsp;&nbsp;  1  2  1<br>
<br>
p2:&nbsp;&nbsp;&nbsp;&nbsp;  3  2  1&nbsp;&nbsp;&nbsp;&nbsp;  2  1  0<br>
<br>
p3:&nbsp;&nbsp;&nbsp;&nbsp;  0  1  2&nbsp;&nbsp;&nbsp;&nbsp;  2  0  2<br>
<br>
p4:&nbsp;&nbsp;&nbsp;&nbsp;  0  0  0&nbsp;&nbsp;&nbsp;&nbsp;  0  0  2<br>
<br>
p5:&nbsp;&nbsp;&nbsp;&nbsp;  2  1  0&nbsp;&nbsp;&nbsp;&nbsp;  0  3  1<br>
<br>
p6:&nbsp;&nbsp;&nbsp;&nbsp;  0  0  1&nbsp;&nbsp;&nbsp;&nbsp;  0  0  0<br>
<br>
在该状态下运行死锁检测算法，找不到一个进程序列使Finish=true，对于所有1≤i≤6，因为存在i∈{1，2，3，5}，使Finish=false，因而可以断言系统已经进入死锁状态，进程p1,p2,p3,p5卷入死锁．<br>
<br>
 <br>
<br>
11.  设有7个简单资源: A、B、C、D、E、F、G。 其申请命令分别为a、b、c、d、e、f、g; 释放命令分别为 a-、b-、c-、d-、d-、f-、g-; 又设系统中有P1、P2、P3三个进程，其活动分别为:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P1活动: a b a- b- e f g e- f- g-<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  P2活动: b c b- c- d a d- a-<br>
<br>
P3活动: c d c-d- e g f e- f- g-<br>
<br>
试分析当P1、P2、P3并发执行时，是否有发生死锁的可能性，并说明原因。<br>
<br>
解：不会有发生死锁的可能性。<br>
<br>
  在本题中，进程p1和p2都使用的资源集合是{a,b}，由于进程p2在申请a之前已经释放了b，不存在占有b并且申请a的情况，所以进程p1和p2之间不满足死锁的四个必要条件，不会产生死锁；<br>
<br>
进程p1和p3都使用的资源集合是{e,f,g}，进程p1和p3都是先申请资源e，这两个进程同时申请资源，那么只能有一个进程先获得e，另一个进程将因为得不到e而阻塞，获得e的进程将进一步顺利获得资源f和g，从而运行结束，释放资源e,f和g，唤醒另一个进程运行。可见，进程p1和p3之间不会产生死锁；<br>
<br>
进程p2和p3都使用的资源集合是{c,d}，由于进程p2在申请d之前已经释放了c，不存在占有c并且申请d的情况，所以进程p2和p3之间不满足死锁的四个必要条件，不会产生死锁。<br>
综上所述，当P1、P2、P3并发执行时，没有发生死锁的可能性。</strong></font></font></font> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/0a1ab26e5a7e7bdc80cb4aeb.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%C4%AC%C8%CF%B7%D6%C0%E0">默认分类</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/0a1ab26e5a7e7bdc80cb4aeb.html#comment">查看评论</a>]]></description>
        <pubDate>2008年07月31日 星期四  12:28 P.M.</pubDate>
        <category><![CDATA[默认分类]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/0a1ab26e5a7e7bdc80cb4aeb.html</guid>
</item>

<item>
        <title><![CDATA[SQL Server 索引结构及其使用（一）——作者：freedk]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/2814a9fd366f821209244db8.html]]></link>
        <description><![CDATA[
		
		<p>在公司平常接触到数据库方面的知识还是很多的，有自己不知道的，也有自己知道的（不过好像很少，：））。所以平常也看看这方面的相关知识，前几天在网上看到SQL Server 索引结构这篇文章，觉得写的很好而且相当实用，至少对我这小菜鸟还是有相当帮助的，毕竟以前对这方面接触不是很多。希望此文章对您也会有帮助。</p>
<p><strong>一、深入浅出理解索引结构</strong><br>
<br>
　　实际上，您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引：聚集索引（clustered index，也称聚类索引、簇集索引）和非聚集索引（nonclustered index，也称非聚类索引、非簇集索引）。下面，我们举例来说明一下聚集索引和非聚集索引的区别：<br>
　　其实，我们的汉语字典的正文本身就是一个聚集索引。比如，我们要查&ldquo;安&rdquo;字，就会很自然地翻开字典的前几页，因为&ldquo;安&rdquo;的拼音是&ldquo;an&rdquo;，而按照拼音排序汉字的字典是以英文字母&ldquo;a&rdquo;开头并以&ldquo;z&rdquo;结尾的，那么&ldquo;安&rdquo;字就自然地排在字典的前部。如果您翻完了所有以&ldquo;a&rdquo;开头的部分仍然找不到这个字，那么就说明您的字典中没有这个字；同样的，如果查&ldquo;张&rdquo;字，那您也会将您的字典翻到最后部分，因为&ldquo;张&rdquo;的拼音是&ldquo;zhang&rdquo;。也就是说，字典的正文部分本身就是一个目录，您不需要再去查其他目录来找到您需要找的内容。我们把这种正文内容本身就是一种按照一定规则排列的目录称为&ldquo;聚集索引&rdquo;。<br>
　　如果您认识某个字，您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字，不知道它的发音，这时候，您就不能按照刚才的方法找到您要查的字，而需要去根据&ldquo;偏旁部首&rdquo;查到您要找的字，然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合&ldquo;部首目录&rdquo;和&ldquo;检字表&rdquo;而查到的字的排序并不是真正的正文的排序方法，比如您查&ldquo;张&rdquo;字，我们可以看到在查部首之后的检字表中&ldquo;张&rdquo;的页码是672页，检字表中&ldquo;张&rdquo;的上面是&ldquo;驰&rdquo;字，但页码却是63页，&ldquo;张&rdquo;的下面是&ldquo;弩&rdquo;字，页面是390页。很显然，这些字并不是真正的分别位于&ldquo;张&rdquo;字的上下方，现在您看到的连续的&ldquo;驰、张、弩&rdquo;三字实际上就是他们在非聚集索引中的排序，是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字，但它需要两个过程，先找到目录中的结果，然后再翻到您所需要的页码。我们把这种目录纯粹是目录，正文纯粹是正文的排序方式称为&ldquo;非聚集索引&rdquo;。<br>
　　通过以上例子，我们可以理解到什么是&ldquo;聚集索引&rdquo;和&ldquo;非聚集索引&rdquo;。进一步引申一下，我们可以很容易的理解：每个表只能有一个聚集索引，因为目录只能按照一种方法进行排序。<br>
<br>
<strong>二、何时使用聚集索引或非聚集索引</strong><br>
<br>
下面的表总结了何时使用聚集索引或非聚集索引（很重要）：</p>
<table style="color: #000000; border-collapse: collapse" height="107" cellspacing="0" cellpadding="0" width="62%" border="1">
    <tbody>
        <tr>
            <td align="center" width="40%" height="23">动作描述</td>
            <td align="center" width="29%" height="23">使用聚集索引</td>
            <td align="center" width="31%" height="23">使用非聚集索引</td>
        </tr>
        <tr>
            <td width="40%" height="20">列经常被分组排序</td>
            <td width="29%" height="20">应</td>
            <td width="31%" height="20">应</td>
        </tr>
        <tr>
            <td width="40%" height="20">返回某范围内的数据</td>
            <td width="29%" height="20">应</td>
            <td width="31%" height="20">不应</td>
        </tr>
        <tr>
            <td width="40%" height="20">一个或极少不同值</td>
            <td width="29%" height="20">不应</td>
            <td width="31%" height="20">不应</td>
        </tr>
        <tr>
            <td width="40%" height="20">小数目的不同值</td>
            <td width="29%" height="20">应</td>
            <td width="31%" height="20">不应</td>
        </tr>
        <tr>
            <td width="40%" height="20">大数目的不同值</td>
            <td width="29%" height="20">不应</td>
            <td width="31%" height="20">应</td>
        </tr>
        <tr>
            <td width="40%" height="20">频繁更新的列</td>
            <td width="29%" height="20">不应</td>
            <td width="31%" height="20">应</td>
        </tr>
        <tr>
            <td width="40%" height="20">外键列</td>
            <td width="29%" height="20">应</td>
            <td width="31%" height="20">应</td>
        </tr>
        <tr>
            <td width="40%" height="20">主键列</td>
            <td width="29%" height="20">应</td>
            <td width="31%" height="20">应</td>
        </tr>
        <tr>
            <td width="40%" height="20">频繁修改索引列</td>
            <td width="29%" height="20">不应</td>
            <td width="31%" height="20">应</td>
        </tr>
    </tbody>
</table>
<p>　　事实上，我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如：返回某范围内的数据一项。比如您的某个表有一个时间列，恰好您把聚合索引建立在了该列，这时您查询2004年1月1日至2004年10月1日之间的全部数据时，这个速度就将是很快的，因为您的这本字典正文是按日期进行排序的，聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可；而不像非聚集索引，必须先查到目录中查到每一项数据对应的页码，然后再根据页码查到具体内容。<br>
<br>
<strong>三、结合实际，谈索引使用的误区</strong><br>
<br>
　　理论的目的是应用。虽然我们刚才列出了何时应使用聚集索引或非聚集索引，但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析。下面我们将根据在实践中遇到的实际问题来谈一下索引使用的误区，以便于大家掌握索引建立的方法。<br>
<br>
1、主键就是聚集索引<br>
　　这种想法笔者认为是极端错误的，是对聚集索引的一种浪费。虽然SQL SERVER默认是在主键上建立聚集索引的。<br>
　　通常，我们会在每个表中都建立一个ID列，以区分每条数据，并且这个ID列是自动增大的，步长一般为1。我们的这个办公自动化的实例中的列Gid就是如此。此时，如果我们将这个列设为主键，SQL SERVER会将此列默认为聚集索引。这样做有好处，就是可以让您的数据在数据库中按照ID进行物理排序，但笔者认为这样做意义不大。<br>
　　显而易见，聚集索引的优势是很明显的，而每个表中只能有一个聚集索引的规则，这使得聚集索引变得更加珍贵。<br>
　　从我们前面谈到的聚集索引的定义我们可以看出，使用聚集索引的最大好处就是能够根据查询要求，迅速缩小查询范围，避免全表扫描。在实际应用中，因为ID号是自动生成的，我们并不知道每条记录的ID号，所以我们很难在实践中用ID号来进行查询。这就使让ID号这个主键作为聚集索引成为一种资源浪费。其次，让每个ID号都不同的字段作为聚集索引也不符合&ldquo;大数目的不同值情况下不应建立聚合索引&rdquo;规则；当然，这种情况只是针对用户经常修改记录内容，特别是索引项的时候会负作用，但对于查询速度并没有影响。<br>
　　在办公自动化系统中，无论是系统首页显示的需要用户签收的文件、会议还是用户进行文件查询等任何情况下进行数据查询都离不开字段的是&ldquo;日期&rdquo;还有用户本身的&ldquo;用户名&rdquo;。<br>
　　通常，办公自动化的首页会显示每个用户尚未签收的文件或会议。虽然我们的where语句可以仅仅限制当前用户尚未签收的情况，但如果您的系统已建立了很长时间，并且数据量很大，那么，每次每个用户打开首页的时候都进行一次全表扫描，这样做意义是不大的，绝大多数的用户1个月前的文件都已经浏览过了，这样做只能徒增数据库的开销而已。事实上，我们完全可以让用户打开系统首页时，数据库仅仅查询这个用户近3个月来未阅览的文件，通过&ldquo;日期&rdquo;这个字段来限制表扫描，提高查询速度。如果您的办公自动化系统已经建立的2年，那么您的首页显示速度理论上将是原来速度8倍，甚至更快。<br>
　　在这里之所以提到&ldquo;理论上&rdquo;三字，是因为如果您的聚集索引还是盲目地建在ID这个主键上时，您的查询速度是没有这么高的，即使您在&ldquo;日期&rdquo;这个字段上建立的索引（非聚合索引）。下面我们就来看一下在1000万条数据量的情况下各种查询的速度表现（3个月内的数据为25万条）：<br>
<br>
（1）仅在主键上建立聚集索引，并且不划分时间段：</p>
<pre>Select gid,fariqi,neibuyonghu,title from tgongwen</pre>
<p>用时：128470毫秒（即：128秒）<br>
<br>
（2）在主键上建立聚集索引，在fariq上建立非聚集索引：</p>
<pre>select gid,fariqi,neibuyonghu,title from Tgongwen
where fariqi&gt; dateadd(day,-90,getdate())</pre>
<p>用时：53763毫秒（54秒）<br>
<br>
（3）将聚合索引建立在日期列（fariqi）上：</p>
<pre>select gid,fariqi,neibuyonghu,title from Tgongwen
where fariqi&gt; dateadd(day,-90,getdate())</pre>
<p>用时：2423毫秒（2秒）<br>
<br>
　　虽然每条语句提取出来的都是25万条数据，各种情况的差异却是巨大的，特别是将聚集索引建立在日期列时的差异。事实上，如果您的数据库真的有1000万容量的话，把主键建立在ID列上，就像以上的第1、2种情况，在网页上的表现就是超时，根本就无法显示。这也是我摒弃ID列作为聚集索引的一个最重要的因素。得出以上速度的方法是：在各个select语句前加：</p>
<pre>declare @d datetime
set @d=getdate()</pre>
<p>并在select语句后加：</p>
<pre>select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())</pre>
<p>2、只要建立索引就能显著提高查询速度<br>
　　事实上，我们可以发现上面的例子中，第2、3条语句完全相同，且建立索引的字段也相同；不同的仅是前者在fariqi字段上建立的是非聚合索引，后者在此字段上建立的是聚合索引，但查询速度却有着天壤之别。所以，并非是在任何字段上简单地建立索引就能提高查询速度。<br>
　　从建表的语句中，我们可以看到这个有着1000万数据的表中fariqi字段有5003个不同记录。在此字段上建立聚合索引是再合适不过了。在现实中，我们每天都会发几个文件，这几个文件的发文日期就相同，这完全符合建立聚集索引要求的：&ldquo;既不能绝大多数都相同，又不能只有极少数相同&rdquo;的规则。由此看来，我们建立&ldquo;适当&rdquo;的聚合索引对于我们提高查询速度是非常重要的。<br>
<br>
3、把所有需要提高查询速度的字段都加进聚集索引，以提高查询速度<br>
　　上面已经谈到：在进行数据查询时都离不开字段的是&ldquo;日期&rdquo;还有用户本身的&ldquo;用户名&rdquo;。既然这两个字段都是如此的重要，我们可以把他们合并起来，建立一个复合索引（compound index）。<br>
　　很多人认为只要把任何字段加进聚集索引，就能提高查询速度，也有人感到迷惑：如果把复合的聚集索引字段分开查询，那么查询速度会减慢吗？带着这个问题，我们来看一下以下的查询速度（结果集都是25万条数据）：（日期列fariqi首先排在复合聚集索引的起始列，用户名neibuyonghu排在后列）：</p>
<pre>（1）select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi&gt;''2004-5-5''</pre>
<p>查询速度：2513毫秒</p>
<pre>（2）select gid,fariqi,neibuyonghu,title from Tgongwen 
　　　　　　　　　　　　where fariqi&gt;''2004-5-5'' and neibuyonghu=''办公室''</pre>
<p>查询速度：2516毫秒</p>
<pre>（3）select gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu=''办公室''</pre>
<p>查询速度：60280毫秒<br>
<br>
　　从以上试验中，我们可以看到如果仅用聚集索引的起始列作为查询条件和同时用到复合聚集索引的全部列的查询速度是几乎一样的，甚至比用上全部的复合索引列还要略快（在查询结果集数目一样的情况下）；而如果仅用复合聚集索引的非起始列作为查询条件的话，这个索引是不起任何作用的。当然，语句1、2的查询速度一样是因为查询的条目数一样，如果复合索引的所有列都用上，而且查询结果少的话，这样就会形成&ldquo;索引覆盖&rdquo;，因而性能可以达到最优。同时，请记住：无论您是否经常使用聚合索引的其他列，但其前导列一定要是使用最频繁的列。<br>
<br>
<strong>四、其他书上没有的索引使用经验总结</strong><br>
<br>
1、用聚合索引比用不是聚合索引的主键速度快<br>
　　下面是实例语句：（都是提取25万条数据）</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''</pre>
<p>使用时间：3326毫秒</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid&lt;=250000</pre>
<p>使用时间：4470毫秒<br>
<br>
这里，用聚合索引比用不是聚合索引的主键速度快了近1/4。<br>
<br>
2、用聚合索引比用一般的主键作order by时速度快，特别是在小数据量情况下</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by fariqi</pre>
<p>用时：12936</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by gid</pre>
<p>用时：18843<br>
<br>
　　这里，用聚合索引比用一般的主键作order by时，速度快了3/10。事实上，如果数据量很小的话，用聚集索引作为排序列要比使用非聚集索引速度快得明显的多；而数据量如果很大的话，如10万以上，则二者的速度差别不明显。<br>
<br>
3、使用聚合索引内的时间段，搜索时间会按数据占整个数据表的百分比成比例减少，而无论聚合索引使用了多少个：</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi&gt;''2004-1-1''</pre>
<p>用时：6343毫秒（提取100万条）</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi&gt;''2004-6-6''</pre>
<p>用时：3170毫秒（提取50万条）</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''</pre>
<p>用时：3326毫秒（和上句的结果一模一样。如果采集的数量一样，那么用大于号和等于号是一样的）</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
　　　　　　　　　　　　where fariqi&gt;''2004-1-1'' and fariqi&lt;''2004-6-6''</pre>
<p>用时：3280毫秒<br>
<br>
4、日期列不会因为有分秒的输入而减慢查询速度<br>
　　下面的例子中，共有100万条数据，2004年1月1日以后的数据有50万条，但只有两个不同的日期，日期精确到日；之前有数据50万条，有5000个不同的日期，日期精确到秒。</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
　　　　　　　　　　where fariqi&gt;''2004-1-1'' order by fariqi</pre>
<p>用时：6390毫秒</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
　　　　　　　　　　　　where fariqi&lt;''2004-1-1'' order by fariqi</pre>
<p>用时：6453毫秒<br>
<br>
<strong>五、其他注意事项</strong><br>
<br>
　　&ldquo;水可载舟，亦可覆舟&rdquo;，索引也一样。索引有助于提高检索性能，但过多或不当的索引也会导致系统低效。因为用户在表中每加进一个索引，数据库就要做更多的工作。过多的索引甚至会导致索引碎片。<br>
　　所以说，我们要建立一个&ldquo;适当&rdquo;的索引体系，特别是对聚合索引的创建，更应精益求精，以使您的数据库能得到高性能的发挥。<br>
　　当然，在实践中，作为一个尽职的数据库管理员，您还要多测试一些方案，找出哪种方案效率最高、最为有效。</p> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/2814a9fd366f821209244db8.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/Sql%20Server">Sql Server</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/2814a9fd366f821209244db8.html#comment">查看评论</a>]]></description>
        <pubDate>2008年01月23日 星期三  10:36 A.M.</pubDate>
        <category><![CDATA[Sql Server]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/2814a9fd366f821209244db8.html</guid>
</item>

<item>
        <title><![CDATA[SQL Server 索引结构及其使用（二）——作者：freedk]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/97d7297a4cbc18e92e73b3b8.html]]></link>
        <description><![CDATA[
		
		<p><strong>改善SQL语句</strong><br>
<br>
　　很多人不知道SQL语句在SQL SERVER中是如何执行的，他们担心自己所写的SQL语句会被SQL SERVER误解。比如：</p>
<pre>select * from table1 where name=''zhangsan'' and tID &gt; 10000</pre>
<p>和执行:</p>
<pre>select * from table1 where tID &gt; 10000 and name=''zhangsan''</pre>
<p>　　一些人不知道以上两条语句的执行效率是否一样，因为如果简单的从语句先后上看，这两个语句的确是不一样，如果tID是一个聚合索引，那么后一句仅仅从表的10000条以后的记录中查找就行了；而前一句则要先从全表中查找看有几个name=''zhangsan''的，而后再根据限制条件条件tID&gt;10000来提出查询结果。<br>
　　事实上，这样的担心是不必要的。SQL SERVER中有一个&ldquo;查询分析优化器&rdquo;，它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间，也就是说，它能实现自动优化。<br>
　　虽然查询优化器可以根据where子句自动的进行查询优化，但大家仍然有必要了解一下&ldquo;查询优化器&rdquo;的工作原理，如非这样，有时查询优化器就会不按照您的本意进行快速查询。<br>
　　在查询分析阶段，查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数（SARG），那么就称之为可优化的，并且可以利用索引快速获得所需数据。<br>
　　SARG的定义：用于限制搜索的一个操作，因为它通常是指一个特定的匹配，一个值得范围内的匹配或者两个以上条件的AND连接。形式如下：</p>
<pre>列名 操作符 &lt;常数 或 变量&gt;

或

&lt;常数 或 变量&gt; 操作符列名</pre>
<p>列名可以出现在操作符的一边，而常数或变量出现在操作符的另一边。如：</p>
<pre>Name=&rsquo;张三&rsquo;

价格&gt;5000

5000&lt;价格

Name=&rsquo;张三&rsquo; and 价格&gt;5000</pre>
<p>　　如果一个表达式不能满足SARG的形式，那它就无法限制搜索的范围了，也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。<br>
　　介绍完SARG后，我们来总结一下使用SARG以及在实践中遇到的和某些资料上结论不同的经验：<br>
<br>
1、Like语句是否属于SARG取决于所使用的通配符的类型</p>
<pre>如：name like &lsquo;张%&rsquo; ，这就属于SARG

而：name like &lsquo;%张&rsquo; ,就不属于SARG。</pre>
<p>原因是通配符%在字符串的开通使得索引无法使用。<br>
<br>
2、or 会引起全表扫描<br>
　　Name=&rsquo;张三&rsquo; and 价格&gt;5000 符号SARG，而：Name=&rsquo;张三&rsquo; or 价格&gt;5000 则不符合SARG。使用or会引起全表扫描。<br>
<br>
3、非操作符、函数引起的不满足SARG形式的语句<br>
　　不满足SARG形式的语句最典型的情况就是包括非操作符的语句，如：NOT、!=、&lt;&gt;、!&lt;、!&gt;、NOT EXISTS、NOT IN、NOT LIKE等，另外还有函数。下面就是几个不满足SARG形式的例子：</p>
<pre>ABS(价格)&lt;5000

Name like &lsquo;%三&rsquo;

有些表达式，如：

WHERE 价格*2&gt;5000

SQL SERVER也会认为是SARG，SQL SERVER会将此式转化为：
WHERE 价格&gt;2500/2</pre>
<p>但我们不推荐这样使用，因为有时SQL SERVER不能保证这种转化与原始表达式是完全等价的。<br>
<br>
4、IN 的作用相当与OR<br>
<br>
语句：</p>
<pre>Select * from table1 where tid in (2,3)

和

Select * from table1 where tid=2 or tid=3</pre>
<p>是一样的，都会引起全表扫描，如果tid上有索引，其索引也会失效。<br>
<br>
5、尽量少用NOT<br>
<br>
6、exists 和 in 的执行效率是一样的<br>
　　很多资料上都显示说，exists要比in的执行效率要高，同时应尽可能的用not exists来代替not in。但事实上，我试验了一下，发现二者无论是前面带不带not，二者之间的执行效率都是一样的。因为涉及子查询，我们试验这次用SQL SERVER自带的pubs数据库。运行前我们可以把SQL SERVER的statistics I/O状态打开：</p>
<pre>（1）select title,price from titles where title_id in (select title_id from sales where qty&gt;30)</pre>
<p>该句的执行结果为：<br>
<br>
表 ''sales''。扫描计数 18，逻辑读 56 次，物理读 0 次，预读 0 次。<br>
表 ''titles''。扫描计数 1，逻辑读 2 次，物理读 0 次，预读 0 次。</p>
<pre>（2）select title,price from titles 
　　　　　　　where exists (select * from sales 
　　　　　　　where sales.title_id=titles.title_id and qty&gt;30)</pre>
<p>第二句的执行结果为：<br>
<br>
表 ''sales''。扫描计数 18，逻辑读 56 次，物理读 0 次，预读 0 次。<br>
表 ''titles''。扫描计数 1，逻辑读 2 次，物理读 0 次，预读 0 次。<br>
<br>
我们从此可以看到用exists和用in的执行效率是一样的。<br>
<br>
7、用函数charindex()和前面加通配符%的LIKE执行效率一样<br>
　　前面，我们谈到，如果在LIKE前面加上通配符%，那么将会引起全表扫描，所以其执行效率是低下的。但有的资料介绍说，用函数charindex()来代替LIKE速度会有大的提升，经我试验，发现这种说明也是错误的：<br>
　</p>
<pre>select gid,title,fariqi,reader from tgongwen 
　　　　　　　　　where charindex(''刑侦支队'',reader)&gt;0 and fariqi&gt;''2004-5-5''</pre>
<p>用时：7秒，另外：扫描计数 4，逻辑读 7155 次，物理读 0 次，预读 0 次。</p>
<pre>select gid,title,fariqi,reader from tgongwen 
　　　　　　　　　where reader like ''%'' + ''刑侦支队'' + ''%'' and fariqi&gt;''2004-5-5''</pre>
<p>用时：7秒，另外：扫描计数 4，逻辑读 7155 次，物理读 0 次，预读 0 次。<br>
<br>
8、union并不绝对比or的执行效率高<br>
　　我们前面已经谈到了在where子句中使用or会引起全表扫描，一般的，我所见过的资料都是推荐这里用union来代替or。事实证明，这种说法对于大部分都是适用的。</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
　　　　　　　　　　where fariqi=''2004-9-16'' or gid&gt;9990000</pre>
<p>用时：68秒。扫描计数 1，逻辑读 404008 次，物理读 283 次，预读 392163 次。</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' 
union
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid&gt;9990000</pre>
<p>用时：9秒。扫描计数 8，逻辑读 67489 次，物理读 216 次，预读 7499 次。<br>
<br>
看来，用union在通常情况下比用or的效率要高的多。<br>
<br>
　　但经过试验，笔者发现如果or两边的查询列是一样的话，那么用union则反倒和用or的执行速度差很多，虽然这里union扫描的是索引，而or扫描的是全表。<br>
　</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen 
　　　　　　　　　　where fariqi=''2004-9-16'' or fariqi=''2004-2-5''</pre>
<p>用时：6423毫秒。扫描计数 2，逻辑读 14726 次，物理读 1 次，预读 7176 次。</p>
<pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' 
union
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-2-5''</pre>
<p>用时：11640毫秒。扫描计数 8，逻辑读 14806 次，物理读 108 次，预读 1144 次。<br>
<br>
9、字段提取要按照&ldquo;需多少、提多少&rdquo;的原则，避免&ldquo;select *&rdquo;<br>
　　我们来做一个试验：</p>
<pre>select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc</pre>
<p>用时：4673毫秒</p>
<pre>select top 10000 gid,fariqi,title from tgongwen order by gid desc</pre>
<p>用时：1376毫秒</p>
<pre>select top 10000 gid,fariqi from tgongwen order by gid desc</pre>
<p>用时：80毫秒<br>
<br>
　　由此看来，我们每少提取一个字段，数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。<br>
<br>
10、count(*)不比count(字段)慢<br>
　　某些资料上说：用*会统计所有列，显然要比一个世界的列名效率低。这种说法其实是没有根据的。我们来看：</p>
<pre>select count(*) from Tgongwen</pre>
<p>用时：1500毫秒</p>
<pre>select count(gid) from Tgongwen</pre>
<p>用时：1483毫秒</p>
<pre>select count(fariqi) from Tgongwen</pre>
<p>用时：3140毫秒</p>
<pre>select count(title) from Tgongwen</pre>
<p>用时：52050毫秒<br>
<br>
　　从以上可以看出，如果用count(*)和用count(主键)的速度是相当的，而count(*)却比其他任何除主键以外的字段汇总速度要快，而且字段越长，汇总的速度就越慢。我想，如果用count(*)， SQL SERVER可能会自动查找最小字段来汇总的。当然，如果您直接写count(主键)将会来的更直接些。<br>
<br>
11、order by按聚集索引列排序效率最高<br>
　　我们来看：（gid是主键，fariqi是聚合索引列）：</p>
<pre>select top 10000 gid,fariqi,reader,title from tgongwen</pre>
<p>用时：196 毫秒。 扫描计数 1，逻辑读 289 次，物理读 1 次，预读 1527 次。</p>
<pre>select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc</pre>
<p>用时：4720毫秒。 扫描计数 1，逻辑读 41956 次，物理读 0 次，预读 1287 次。</p>
<pre>select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc</pre>
<p>用时：4736毫秒。 扫描计数 1，逻辑读 55350 次，物理读 10 次，预读 775 次。</p>
<pre>select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc</pre>
<p>用时：173毫秒。 扫描计数 1，逻辑读 290 次，物理读 0 次，预读 0 次。</p>
<pre>select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc</pre>
<p>用时：156毫秒。 扫描计数 1，逻辑读 289 次，物理读 0 次，预读 0 次。<br>
<br>
　　从以上我们可以看出，不排序的速度以及逻辑读次数都是和&ldquo;order by 聚集索引列&rdquo; 的速度是相当的，但这些都比&ldquo;order by 非聚集索引列&rdquo;的查询速度是快得多的。<br>
　　同时，按照某个字段进行排序的时候，无论是正序还是倒序，速度是基本相当的。<br>
<br>
12、高效的TOP<br>
　　事实上，在查询和提取超大容量的数据集时，影响数据库响应时间的最大因素不是数据查找，而是物理的I/0操作。如：</p>
<pre>select top 10 * from (
select top 10000 gid,fariqi,title from tgongwen
where neibuyonghu=''办公室''
order by gid desc) as a
order by gid asc</pre>
<p>　　这条语句，从理论上讲，整条语句的执行时间应该比子句的执行时间长，但事实相反。因为，子句执行后返回的是10000条记录，而整条语句仅返回10条语句，所以影响数据库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效方法之一就是使用TOP关键词了。TOP关键词是SQL SERVER中经过系统优化过的一个用来提取前几条或前几个百分比数据的词。经笔者在实践中的应用，发现TOP确实很好用，效率也很高。但这个词在另外一个大型数据库ORACLE中却没有，这不能说不是一个遗憾，虽然在ORACLE中可以用其他方法（如：rownumber）来解决。在以后的关于&ldquo;实现千万级数据的分页显示存储过程&rdquo;的讨论中，我们就将用到TOP这个关键词。<br>
　　到此为止，我们上面讨论了如何实现从大容量的数据库中快速地查询出您所需要的数据方法。当然，我们介绍的这些方法都是&ldquo;软&rdquo;方法，在实践中，我们还要考虑各种&ldquo;硬&rdquo;因素，如：网络性能、服务器的性能、操作系统的性能，甚至网卡、交换机等。</p> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/97d7297a4cbc18e92e73b3b8.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/Sql%20Server">Sql Server</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/97d7297a4cbc18e92e73b3b8.html#comment">查看评论</a>]]></description>
        <pubDate>2008年01月23日 星期三  10:34 A.M.</pubDate>
        <category><![CDATA[Sql Server]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/97d7297a4cbc18e92e73b3b8.html</guid>
</item>

<item>
        <title><![CDATA[SQL Server 索引结构及其使用（三）——作者：freedk]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/610024c7d63aaad8d10060be.html]]></link>
        <description><![CDATA[
		
		<p>在公司平常接触到数据库方面的知识还是很多的，有自己不知道的，也有自己知道的（不过好像很少，：））。所以平常也看看这方面的相关知识，前几天在网上看到SQL Server 索引结构这篇文章，觉得写的很好而且相当实用，至少对我这小菜鸟还是有相当帮助的，毕竟以前对这方面接触不是很多。</p>
<p><strong>实现小数据量和海量数据的通用分页显示存储过程<br>
<br>
</strong>　　建立一个 Web 应用，分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法是:ADO 纪录集分页法，也就是利用ADO自带的分页功能（利用游标）来实现分页。但这种分页方法仅适用于较小数据量的情形，因为游标本身有缺点：游标是存放在内存中，很费内存。游标一建立，就将相关的记录锁住，直到取消游标。游标提供了对特定集合中逐行扫描的手段，一般使用游标来逐行遍历数据，根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标（大的数据集合）循环很容易使程序进入一个漫长的等待甚至死机。<br>
　　更重要的是，对于非常大的数据模型而言，分页检索时，如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据，而非检索所有的数据，然后单步执行当前行。<br>
　　最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是&ldquo;俄罗斯存储过程&rdquo;。这个存储过程用了游标，由于游标的局限性，所以这个方法并没有得到大家的普遍认可。<br>
　　后来，网上有人改造了此存储过程，下面的存储过程就是结合我们的办公自动化实例写的分页存储过程：</p>
<pre>CREATE procedure pagination1
(@pagesize int, --页面大小，如每页存储20条记录
@pageindex int --当前页码
)
as

set nocount on

begin
declare @indextable table(id int identity(1,1),nid int) --定义表变量
declare @PageLowerBound int --定义此页的底码
declare @PageUpperBound int --定义此页的顶码
set @PageLowerBound=(@pageindex-1)*@pagesize
set @PageUpperBound=@PageLowerBound+@pagesize
set rowcount @PageUpperBound
insert into @indextable(nid) select gid from TGongwen 
　　　　　　where fariqi &gt;dateadd(day,-365,getdate()) order by fariqi desc
select O.gid,O.mid,O.title,O.fadanwei,O.fariqi from TGongwen O,@indextable t 
           where O.gid=t.nid and t.id&gt;@PageLowerBound 
                        and t.id&lt;=@PageUpperBound order by t.id
end

set nocount off</pre>
<p>　　以上存储过程运用了SQL SERVER的最新技术――表变量。应该说这个存储过程也是一个非常优秀的分页存储过程。当然，在这个过程中，您也可以把其中的表变量写成临时表：CREATE TABLE #Temp。但很明显，在SQL SERVER中，用临时表是没有用表变量快的。所以笔者刚开始使用这个存储过程时，感觉非常的不错，速度也比原来的ADO的好。但后来，我又发现了比此方法更好的方法。<br>
　　笔者曾在网上看到了一篇小短文《从数据表中取出第n条到第m条的记录的方法》，全文如下：</p>
<pre>从publish 表中取出第 n 条到第 m 条的记录： 
SELECT TOP m-n+1 * 
FROM publish 
WHERE (id NOT IN 
　　　　(SELECT TOP n-1 id 
　　　　 FROM publish)) 

id 为publish 表的关键字</pre>
<p>　　我当时看到这篇文章的时候，真的是精神为之一振，觉得思路非常得好。等到后来，我在作办公自动化系统（ASP.NET+ C#＋SQL SERVER）的时候，忽然想起了这篇文章，我想如果把这个语句改造一下，这就可能是一个非常好的分页存储过程。于是我就满网上找这篇文章，没想到，文章还没找到，却找到了一篇根据此语句写的一个分页存储过程，这个存储过程也是目前较为流行的一种分页存储过程，我很后悔没有争先把这段文字改造成存储过程：</p>
<pre>CREATE PROCEDURE pagination2
(
@SQL nVARCHAR(4000), --不带排序语句的SQL语句
@Page int, --页码
@RecsPerPage int, --每页容纳的记录数
@ID VARCHAR(255), --需要排序的不重复的ID号
@Sort VARCHAR(255) --排序字段及规则
)
AS

DECLARE @Str nVARCHAR(4000)

SET @Str=''SELECT TOP ''+CAST(@RecsPerPage AS VARCHAR(20))+'' * FROM 
(''+@SQL+'') T WHERE T.''+@ID+''NOT IN (SELECT TOP ''+CAST((@RecsPerPage*(@Page-1)) 
AS VARCHAR(20))+'' ''+@ID+'' FROM (''+@SQL+'') T9 ORDER BY ''+@Sort+'') ORDER BY ''+@Sort

PRINT @Str

EXEC sp_ExecuteSql @Str
GO</pre>
<p>其实，以上语句可以简化为：</p>
<pre>SELECT TOP 页大小 *
FROM Table1 WHERE (ID NOT IN (SELECT TOP 页大小*页数 id FROM 表 ORDER BY id))
ORDER BY ID</pre>
<p>但这个存储过程有一个致命的缺点，就是它含有NOT IN字样。虽然我可以把它改造为：</p>
<pre>SELECT TOP 页大小 *
FROM Table1 WHERE not exists
(select * from (select top (页大小*页数) * from table1 order by id) b where b.id=a.id )
order by id</pre>
<p>　　即，用not exists来代替not in，但我们前面已经谈过了，二者的执行效率实际上是没有区别的。既便如此，用TOP 结合NOT IN的这个方法还是比用游标要来得快一些。<br>
　　虽然用not exists并不能挽救上个存储过程的效率，但使用SQL SERVER中的TOP关键字却是一个非常明智的选择。因为分页优化的最终目的就是避免产生过大的记录集，而我们在前面也已经提到了TOP的优势，通过TOP 即可实现对数据量的控制。<br>
　　在分页算法中，影响我们查询速度的关键因素有两点：TOP和NOT IN。TOP可以提高我们的查询速度，而NOT IN会减慢我们的查询速度，所以要提高我们整个分页算法的速度，就要彻底改造NOT IN，同其他方法来替代它。<br>
　　我们知道，几乎任何字段，我们都可以通过max(字段)或min(字段)来提取某个字段中的最大或最小值，所以如果这个字段不重复，那么就可以利用这些不重复的字段的max或min作为分水岭，使其成为分页算法中分开每页的参照物。在这里，我们可以用操作符&ldquo;&gt;&rdquo;或&ldquo;&lt;&rdquo;号来完成这个使命，使查询语句符合SARG形式。如：</p>
<pre>Select top 10 * from table1 where id&gt;200</pre>
<p>于是就有了如下分页方案：</p>
<pre>select top 页大小 *
from table1 
where id&gt;
(select max (id) from 
(select top ((页码-1)*页大小) id from table1 order by id) as T
) 
order by id</pre>
<p>　　在选择即不重复值，又容易分辨大小的列时，我们通常会选择主键。下表列出了笔者用有着1000万数据的办公自动化系统中的表，在以GID（GID是主键，但并不是聚集索引。）为排序列、提取gid,fariqi,title字段，分别以第1、10、100、500、1000、1万、10万、25万、50万页为例，测试以上三种分页方案的执行速度：（单位：毫秒）</p>
<p>
<table style="color: #000000; border-collapse: collapse" cellspacing="0" cellpadding="0" width="70%" border="1">
    <tbody>
        <tr>
            <td align="center" width="22%"><strong>页码</strong></td>
            <td align="center" width="25%"><strong>方案1</strong></td>
            <td align="center" width="30%"><strong>方案2</strong></td>
            <td align="center" width="23%"><strong>方案3</strong></td>
        </tr>
        <tr>
            <td width="22%">1</td>
            <td width="25%">60</td>
            <td width="30%">30</td>
            <td width="23%">76</td>
        </tr>
        <tr>
            <td width="22%">10</td>
            <td width="25%">46</td>
            <td width="30%">16</td>
            <td width="23%">63</td>
        </tr>
        <tr>
            <td width="22%">100</td>
            <td width="25%">1076</td>
            <td width="30%">720</td>
            <td width="23%">130</td>
        </tr>
        <tr>
            <td width="22%">500</td>
            <td width="25%">540</td>
            <td width="30%">12943</td>
            <td width="23%">83</td>
        </tr>
        <tr>
            <td width="22%">1000</td>
            <td width="25%">17110</td>
            <td width="30%">470</td>
            <td width="23%">250</td>
        </tr>
        <tr>
            <td width="22%">10000</td>
            <td width="25%">24796</td>
            <td width="30%">4500</td>
            <td width="23%">140</td>
        </tr>
        <tr>
            <td width="22%">100000</td>
            <td width="25%">38326</td>
            <td width="30%">42283</td>
            <td width="23%">1553</td>
        </tr>
        <tr>
            <td width="22%">250000</td>
            <td width="25%">28140</td>
            <td width="30%">128720</td>
            <td width="23%">2330</td>
        </tr>
        <tr>
            <td width="22%">500000</td>
            <td width="25%">121686</td>
            <td width="30%">127846</td>
            <td width="23%">7168</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　从上表中，我们可以看出，三种存储过程在执行100页以下的分页命令时，都是可以信任的，速度都很好。但第一种方案在执行分页1000页以上后，速度就降了下来。第二种方案大约是在执行分页1万页以上后速度开始降了下来。而第三种方案却始终没有大的降势，后劲仍然很足。<br>
　　在确定了第三种分页方案后，我们可以据此写一个存储过程。大家知道SQL SERVER的存储过程是事先编译好的SQL语句，它的执行效率要比通过WEB页面传来的SQL语句的执行效率要高。下面的存储过程不仅含有分页方案，还会根据页面传来的参数来确定是否进行数据总数统计。<br>
<br>
--获取指定页的数据：</p>
<pre>CREATE PROCEDURE pagination3
@tblName varchar(255), -- 表名
@strGetFields varchar(1000) = ''*'', -- 需要返回的列 
@fldName varchar(255)='''', -- 排序的字段名
@PageSize int = 10, -- 页尺寸
@PageIndex int = 1, -- 页码
@doCount bit = 0, -- 返回记录总数, 非 0 值则返回
@OrderType bit = 0, -- 设置排序类型, 非 0 值则降序
@strWhere varchar(1500) = '''' -- 查询条件 (注意: 不要加 where)
AS

declare @strSQL varchar(5000) -- 主语句
declare @strTmp varchar(110) -- 临时变量
declare @strOrder varchar(400) -- 排序类型

if @doCount != 0
begin
if @strWhere !=''''
set @strSQL = &quot;select count(*) as Total from [&quot; + @tblName + &quot;] where &quot;+@strWhere
else
set @strSQL = &quot;select count(*) as Total from [&quot; + @tblName + &quot;]&quot;
end</pre>
<p>--以上代码的意思是如果@doCount传递过来的不是0，就执行总数统计。以下的所有代码都是@doCount为0的情况：</p>
<pre>else
begin
if @OrderType != 0
begin
set @strTmp = &quot;&lt;(select min&quot;
set @strOrder = &quot; order by [&quot; + @fldName +&quot;] desc&quot;</pre>
<p>--如果@OrderType不是0，就执行降序，这句很重要！</p>
<pre>end
else
begin
set @strTmp = &quot;&gt;(select max&quot;
set @strOrder = &quot; order by [&quot; + @fldName +&quot;] asc&quot;
end

if @PageIndex = 1
begin
if @strWhere != '''' 

set @strSQL = &quot;select top &quot; + str(@PageSize) +&quot; &quot;+@strGetFields+ &quot;
　　　　　　　　from [&quot; + @tblName + &quot;] where &quot; + @strWhere + &quot; &quot; + @strOrder
else

set @strSQL = &quot;select top &quot; + str(@PageSize) +&quot; &quot;+@strGetFields+ &quot; 
　　　　　　　　from [&quot;+ @tblName + &quot;] &quot;+ @strOrder</pre>
<p>--如果是第一页就执行以上代码，这样会加快执行速度</p>
<pre>end
else
begin</pre>
<p>--以下代码赋予了@strSQL以真正执行的SQL代码<br>
　</p>
<pre>set @strSQL = &quot;select top &quot; + str(@PageSize) +&quot; &quot;+@strGetFields+ &quot; from [&quot;
+ @tblName + &quot;] where [&quot; + @fldName + &quot;]&quot; + @strTmp + &quot;([&quot;+ @fldName + &quot;]) 
　　　　　　from (select top &quot; + str((@PageIndex-1)*@PageSize) + &quot; [&quot;+ @fldName + &quot;] 
　　　　　　from [&quot; + @tblName + &quot;]&quot; + @strOrder + &quot;) as tblTmp)&quot;+ @strOrder

if @strWhere != ''''
set @strSQL = &quot;select top &quot; + str(@PageSize) +&quot; &quot;+@strGetFields+ &quot; from [&quot;
+ @tblName + &quot;] where [&quot; + @fldName + &quot;]&quot; + @strTmp + &quot;([&quot;
+ @fldName + &quot;]) from (select top &quot; + str((@PageIndex-1)*@PageSize) + &quot; [&quot;
+ @fldName + &quot;] from [&quot; + @tblName + &quot;] where &quot; + @strWhere + &quot; &quot;
+ @strOrder + &quot;) as tblTmp) and &quot; + @strWhere + &quot; &quot; + @strOrder
end 

end 

exec (@strSQL)

GO</pre>
<p>　　上面的这个存储过程是一个通用的存储过程，其注释已写在其中了。 在大数据量的情况下，特别是在查询最后几页的时候，查询时间一般不会超过9秒；而用其他存储过程，在实践中就会导致超时，所以这个存储过程非常适用于大容量数据库的查询。 笔者希望能够通过对以上存储过程的解析，能给大家带来一定的启示，并给工作带来一定的效率提升，同时希望同行提出更优秀的实时数据分页算法。</p> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/610024c7d63aaad8d10060be.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/Sql%20Server">Sql Server</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/610024c7d63aaad8d10060be.html#comment">查看评论</a>]]></description>
        <pubDate>2008年01月23日 星期三  10:32 A.M.</pubDate>
        <category><![CDATA[Sql Server]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/610024c7d63aaad8d10060be.html</guid>
</item>

<item>
        <title><![CDATA[一切又该从0开始]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/16c73738259b5327b9998f1a.html]]></link>
        <description><![CDATA[
		
		好久没有来这里踩踩了，真对不起关心我的朋友们。其实平常还是有很多东西想写的，不过就是懒。也可能前段时间有很多繁琐的事情需要去处理吧。不过现在好多了，因为已经找到了自己的归属。有了新的前进目标，我想，一切又该从0开始了，加油！身边的朋友们，你们也要加油！ 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%D0%C4%C7%E9%CB%E6%CF%EB">心情随想</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/16c73738259b5327b9998f1a.html#comment">查看评论</a>]]></description>
        <pubDate>2007年11月22日 星期四  02:08 P.M.</pubDate>
        <category><![CDATA[心情随想]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/16c73738259b5327b9998f1a.html</guid>
</item>

<item>
        <title><![CDATA[朋友，一路顺风]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/6ef17809eaa905cd3ac76301.html]]></link>
        <description><![CDATA[
		
		<p>外面下着大雨，还夹杂着雷声，这一刻终于来临了，此时，我只机械般的来到了这里，然后重新装饰下我的版面，真的是好久没有更新我的版面了。一直认为白色和黑色是永远不会褪色的，给人以简洁和清爽的感觉，仿佛又回到了本科和中学时代。我记得好像就有朋友第一次登录我的blog这样评价到：进你的窝窝感觉像翻开中学时代的同学录一样。但这次，我觉得是应该换了，因为黑白让我想起了太多太多，一起去衡山，一起军训，一起扯淡，一起挤床板，一起作弊，一起K歌，一起过圣诞，一起打球，一起坐渡轮，一起逛南京街，一起发牢骚，一起走在街上时不时冒几句eg。。。。。。太多太多。虽然我们也经常会因为某些事情而互不理睬，但最终我们还是能一起笑对明天。呵呵</p>
<p>时间，地点总是不能如人所愿，我们彼此都在上海，他工作，我念书。但我们好像相隔好几个城市，很少聚在一起。不过QQ，mobilephone还是经常联系的。每次当我对他说，双休日来我学校玩吧，咱们聚聚，每次他都笑说道，太远了，坐车累啊，还是你来我这里吧。然后我哽咽了半天来了句经典语：晕，好像我不坐车一样。o(∩_∩)o...哈哈！我们每次谈到这个话题都轮番调侃这几句。我们有才吧，结果可想而知了。不过好像我妥协的次数多点，经常熬夜到凌晨1点多，第二天早早（好像不早诶，每次起来都是9点左右，汗。。。）起来赶北安跨线车。为了心里平衡，我几乎每次去都要带上我丢那没有洗的衣服，然后拿去他那里洗。久而久之，我俩就形成默契了，每次我去他那，他见我第一句话就说：靠，贱人，又背一包衣服过来了啊。记得给我买洗衣粉啊。然后我就委屈的说道：靠，你看这个背包这么大，不装点东西背起来怪难看的啊，再说了，我不来你这我自己早洗完了。然后我俩相视而笑。。。。。。</p>
<p>我俩在上海一起渡过了我们大学毕业后的第一年，这一年里，我觉得我俩都成长了许多，真的。希望你去了新的环境能有更好的发展，我也相信肯定会的，因为那里有我们那么多的同学，可以交流，可以一起出去洒脱，我也相信你在那边会过的更加开心。以后多来这里看看我，因为我也不知道这一别我们什么时候还能再见。我只能深深的祝福你，<font style="COLOR: #e10900">祝你一路顺风</font></p>
<p>无名的小宾<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们都需要一个自己的空间，一个能充分自由的发挥自己才智的空间，畅想我们的未来，为未来而奋斗！在此祝您一路顺风！——丹尼斯</p>
<p>今天还有我一朋友乐天要踏上回家的列车，我在这里也<font color="#ff0000">祝你一路顺风</font>！——dannis</p> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/6ef17809eaa905cd3ac76301.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%D0%C4%C7%E9%CB%E6%CF%EB">心情随想</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/6ef17809eaa905cd3ac76301.html#comment">查看评论</a>]]></description>
        <pubDate>2007年07月20日 星期五  04:04 P.M.</pubDate>
        <category><![CDATA[心情随想]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/6ef17809eaa905cd3ac76301.html</guid>
</item>

<item>
        <title><![CDATA[如何准确测试程序/算法运行时间（VC中实现）]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/b04498d6a2dbf52d06088b12.html]]></link>
        <description><![CDATA[
		
		<p>近来导师让我写一个能准确测试程序运行时间的程序。下面给出我用的两种测试方法：</p>
<p>方法一：插入汇编代码（精度高）</p>
<p><font color="#ff0000"> unsigned long HighStart,LowStart,HighEnd,LowEnd;//要是定义成long类型，出现负值的几率很高<br>
 unsigned long numhigh,numlow;<br>
 //long MaxCycle = 0;</font></p>
<p><font color="#ff0000"> __asm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
 {<br>
&nbsp;&nbsp; RDTSC <br>
&nbsp;&nbsp;&nbsp; mov HighStart, edx<br>
&nbsp;&nbsp;&nbsp; mov LowStart, eax<br>
 }</font></p>
<p><font color="#ff0000"> //获</font>取波门数据<br>
 PTNODE pt1, pt2;<br>
 pt1.x = m_leftPtX;<br>
 pt1.y = m_leftPtY;<br>
 pt2.x = pt1.x+m_PcWidth;<br>
 pt2.y = pt1.y+m_PcWidth;<br>
 BYTE* PTemp = (BYTE*)malloc(m_PcWidth*m_PcWidth);<br>
 memset(PTemp, 0, m_PcWidth*m_PcWidth);</p>
<p> pView-&gt;myImage-&gt;PickAreaData(pDest,PTemp,&amp;pt1, &amp;pt2);<br>
 //针对特定区域开始模拟<br>
 pView-&gt;myImage-&gt;SimulateOfVariance(PTemp, m_PcWidth, m_PcWidth);</p>
<p> //拷贝处理后的数据到原位置<br>
 pView-&gt;myImage-&gt;ReplaceAreaBmpData(pDest, PTemp, &amp;pt1, &amp;pt2);</p>
<p> pView-&gt;myImage-&gt;TransformDataBmp(pDest,pView-&gt;myImage-&gt;m_pData,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pView-&gt;myImage-&gt;m_width,pView-&gt;myImage-&gt;m_height);</p>
<p> //<br>
&nbsp;&nbsp;<font color="#ff0000">&nbsp;&nbsp;&nbsp; __asm<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp; RDTSC<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov HighEnd, edx<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Mov LowEnd,&nbsp;&nbsp; eax<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sub eax, LowStart<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numlow,&nbsp;&nbsp; eax<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax,edx<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sbb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax,HighStart <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numhigh,eax<br>
&nbsp;&nbsp;&nbsp; }<br>
</font>&nbsp;&nbsp;&nbsp;<br>
 <font color="#ff0000">&nbsp;&nbsp;&nbsp; __int64&nbsp;&nbsp; timer =0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp; timer |= numhigh;<br>
&nbsp;&nbsp;&nbsp; timer = timer&lt;&lt;32;<br>
&nbsp;&nbsp;&nbsp; timer |= numlow; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp; m_dTime = (double) (timer /1.99/1000000000);其中1.99/1000000000为电脑频率，比如我机子的CPU频率是1.99GHz。</font></p>
<p><font color="#ff0000">m_dtime的值就是我们所需要的</font></p>
<p>方法二，我自己实现了一个类</p>
<p>//.h</p>
<p>class CCalculateTime&nbsp;&nbsp;<br>
{<br>
public:<br>
 CCalculateTime();<br>
 virtual ~CCalculateTime();<br>
public:<br>
 double ReturnSpendTime();//返回最终运行时间<br>
 void GetEndPerformanceCounter();//取得结束运行时间<br>
 void GetStartPerformanceCounter();// 取得开始运行时间<br>
 void GetPerformanceFrequency();/ /取得CPU工作频率</p>
<p>private:<br>
 LARGE_INTEGER freq;<br>
 LONGLONG QPart1,QPart2;<br>
 double dfMinus, dfFreq, dfTim;<br>
};<br>
</p>
<p>//.cpp</p>
<p>CCalculateTime::CCalculateTime()<br>
: QPart1(0),QPart2(0)<br>
 ,dfMinus(0), dfFreq(0), dfTim(0)<br>
{</p>
<p>}</p>
<p>CCalculateTime::~CCalculateTime()<br>
{</p>
<p>}</p>
<p>void CCalculateTime::GetPerformanceFrequency()<br>
{<br>
 QueryPerformanceFrequency(&amp;freq); <br>
 dfFreq = (double)freq.QuadPart;&nbsp;&nbsp;</p>
<p>}</p>
<p>void CCalculateTime::GetStartPerformanceCounter()<br>
{<br>
 QueryPerformanceCounter(&amp;freq);<br>
 QPart1 = freq.QuadPart;<br>
}</p>
<p>void CCalculateTime::GetEndPerformanceCounter()<br>
{<br>
 QueryPerformanceCounter(&amp;freq);<br>
 QPart2 = freq.QuadPart;<br>
}</p>
<p>double CCalculateTime::ReturnSpendTime()<br>
{<br>
 dfMinus = (double)(QPart2-QPart1);<br>
&nbsp;&nbsp;&nbsp;&nbsp; return dfMinus / dfFreq;// 获得对应的时间值，单位为秒</p>
<p>}</p>
<p>测试：</p>
<p>CCalculateTime a;</p>
<p>a.GetPerformanceFrequency();</p>
<p>a.GetStartPerformanceCounter();</p>
<p>//测试的代码</p>
<p>a.GetEndPerformanceCounter();</p>
<p>long spentTime = a.ReturnSpendTime();</p>
<p>这两种方法精度都很高，都是通过处理CPU时钟频率来计算运行时间的。<br>
<br>
</p> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/b04498d6a2dbf52d06088b12.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/mfc%26%2347%3Bc%2B%2B%D1%A7%CF%B0%D0%C4%B5%C3%CC%E5%BB%E1">mfc&#47;c++学习心得体会</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/b04498d6a2dbf52d06088b12.html#comment">查看评论</a>]]></description>
        <pubDate>2007年07月17日 星期二  05:09 P.M.</pubDate>
        <category><![CDATA[mfc&#47;c++学习心得体会]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/b04498d6a2dbf52d06088b12.html</guid>
</item>

<item>
        <title><![CDATA[何时是头？]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/dd7073819e8e7edabd3e1e31.html]]></link>
        <description><![CDATA[
		
		<p>最近一直忙于跟导师搞红外图像处理，累啊，实现导师要求的算法同时还要去各个期刊上看相关论文。也不知道导师何时吧你叫过去，然后来一句“谈谈你近段时间的学习情况和对某一算法的认识等等”。虽然我没有想过将来出去从事图像处理方面的工作，但感觉对这些有所接触对自己将来的发展肯定是有利的。经过一个多月的学习，终于明白了许多。看这自己所做的一些成果，心里还是很开心的。至少我现在从事的这个项目已经成型了吧。</p>
<p>唉，人真的很不容易，o(∩_∩)o...，要不断要学习，很多很多不知道的东西！看了才知道，噢，原来是这么回事！这就是学习吧！我经常对着蓝天自问：学习，到何时是个头呢？我不知道，真的不知道。既然没有想到何时是头，那就继续吧！等何时想到了，就停止学习，开始不学习的生活！</p>
<p>在这里祝福大家，天天开心。</p> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/dd7073819e8e7edabd3e1e31.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%D0%C4%C7%E9%CB%E6%CF%EB">心情随想</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/dd7073819e8e7edabd3e1e31.html#comment">查看评论</a>]]></description>
        <pubDate>2007年07月16日 星期一  01:51 P.M.</pubDate>
        <category><![CDATA[心情随想]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/dd7073819e8e7edabd3e1e31.html</guid>
</item>

<item>
        <title><![CDATA[对我来说，这很特别，值得回忆]]></title>
        <link><![CDATA[http://hi.baidu.com/zh%5Fdaniel/blog/item/80ec88dd5526ff365882dd50.html]]></link>
        <description><![CDATA[
		
		<p>好久没有更新了，因为是黑色的学期末，一直都在忙。诶。。真是命苦。今天同学找我要AutoDesk公司来我院采访的图片和我们学生去公司采访的图片，于是我又一次浏览了这些图片。感触还是挺深的。在AutoDesk俱乐部呆了也有挺长时间的，认识了很多朋友，也做了些东西，同时也学到了很多东西，真的，特别对该公司和该公司的产品有了很深的认识。下面是这学期autodesk公司负责全球招聘的manager来俱乐部参观时，我给她演示我所做的demo.她人很好，非常平易近人、和蔼可亲，有点出乎我的意料之外。 这一刻还真的很紧张，虽然我有准备过，但真的还是紧张，因为面对的是这位和蔼可亲的manager，旁边还有老万院长和公司的其他人士。呵呵，不过最后还是有惊无险的过关了。。:-) 。</p>
<div forimg="1" align="left"><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/zh%5Fdaniel/pic/item/1e7c102405a3a234c89559be.jpg"></div>
<div forimg="1" align="left"><a target="_blank" href="http://hiphotos.baidu.com/zh%5Fdaniel/pic/item/c16d13f4e0aeb0e87609d7be.jpg"></a></div>
<p>希望以后还有机会见到他们。</p>
<div forimg="1" align="left"><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/zh%5Fdaniel/pic/item/6d169210dbed4206213f2ebf.jpg"></div>
<div forimg="1" align="left"></div> <a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/80ec88dd5526ff365882dd50.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/zh%5Fdaniel/blog/category/%D0%C4%C7%E9%CB%E6%CF%EB">心情随想</a>&nbsp;<a href="http://hi.baidu.com/zh%5Fdaniel/blog/item/80ec88dd5526ff365882dd50.html#comment">查看评论</a>]]></description>
        <pubDate>2007年07月10日 星期二  00:59 A.M.</pubDate>
        <category><![CDATA[心情随想]]></category>
        <author><![CDATA[zh_daniel]]></author>
		<guid>http://hi.baidu.com/zh%5Fdaniel/blog/item/80ec88dd5526ff365882dd50.html</guid>
</item>


</channel>
</rss>