﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-JAVA,JAVASCRIPT，PHP and Oracle-随笔分类-其他</title><link>http://www.blogjava.net/ljf-tianyi/category/40713.html</link><description>天一</description><language>zh-cn</language><lastBuildDate>Thu, 17 Mar 2011 17:19:51 GMT</lastBuildDate><pubDate>Thu, 17 Mar 2011 17:19:51 GMT</pubDate><ttl>60</ttl><item><title>网络攻击小结【DDos】</title><link>http://www.blogjava.net/ljf-tianyi/archive/2011/03/13/346173.html</link><dc:creator>天一</dc:creator><author>天一</author><pubDate>Sun, 13 Mar 2011 15:09:00 GMT</pubDate><guid>http://www.blogjava.net/ljf-tianyi/archive/2011/03/13/346173.html</guid><wfw:comment>http://www.blogjava.net/ljf-tianyi/comments/346173.html</wfw:comment><comments>http://www.blogjava.net/ljf-tianyi/archive/2011/03/13/346173.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljf-tianyi/comments/commentRss/346173.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljf-tianyi/services/trackbacks/346173.html</trackback:ping><description><![CDATA[<span style="font-family: times new roman,times;">现在网络技术日新月异</span>
，不断有新技术被不同类型软件所使用。在提高开发软件各个方面性能同时，也增加了系统安全隐患。例如：云技术能够为我们带来了一个更加有效地利用网络资源和整合网络数据模式；不过，这个新技术引出了安全的担心。
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网络安全是涉及到网络各个方面内容，现在最为突出问题就是网络攻击。根据近年来接触到问题，总结了下面几个现在比较常用网络攻击手法和一些防御测试。</p>
<h3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DDos--分布式拒绝服务攻击</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DDos 是 Distributed Denial of service&nbsp; , 这种攻击起源于1996年；此攻击主要利用合理的服务请求来占用过多的服务资源，从而使服务器无法处理合法用户的指令。有以下主要几种具体攻击手段：</p>
<p>（1）SYN 洪水攻击</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 原理：SYN 洪水攻击主要是利用TCP协议缺陷，通过&#8220;肉鸡&#8221;伪造地址和发送大量的半连接请求，使得主机一直等待半连接请求的回复。通过此方法不断耗费主机有限的CPU资源和内存资源。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 攻击手段：一般都是开发专门制造洪水攻击程序；程序核心主要是伪造一个TCP协议信息头和IP协议的信息头</p>
<div class="dp-highlighter">
<ol class="dp-cpp" start="1">
    <li class="alt"><span><span>TCP_HEADER&nbsp;&nbsp;tcpheader;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;IP_HEADER&nbsp;&nbsp;&nbsp;ipheader;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//填充IP首部</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.h_verlen=(4&lt;&lt;4&nbsp;|&nbsp;<span class="keyword">sizeof</span><span>(IP_HEADER)/</span><span class="keyword">sizeof</span><span>(unsigned&nbsp;</span><span class="datatypes">long</span><span>));&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.total_len&nbsp;=&nbsp;htons(<span class="keyword">sizeof</span><span>(IP_HEADER)+</span><span class="keyword">sizeof</span><span>(TCP_HEADER));&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.ident&nbsp;=&nbsp;1;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.frag_and_flags&nbsp;=&nbsp;0;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.ttl&nbsp;=&nbsp;128;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.proto&nbsp;=&nbsp;IPPROTO_TCP;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.checksum&nbsp;=0;&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.sourceIP&nbsp;=&nbsp;htonl(FakeIpHost+SendSEQ);&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;ipheader.destIP&nbsp;=&nbsp;inet_addr(DestIP);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//填充TCP首部</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_dport=htons(port);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_sport&nbsp;=&nbsp;htons(8080);&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_seq&nbsp;=&nbsp;htonl(SEQ+SendSEQ);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_ack&nbsp;=&nbsp;0;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_lenres&nbsp;=(<span class="keyword">sizeof</span><span>(TCP_HEADER)/4&lt;&lt;4|0);&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_flag&nbsp;=&nbsp;2;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_win&nbsp;=&nbsp;htons(16384);&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_urp&nbsp;=&nbsp;0;&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;tcpheader.th_sum&nbsp;=&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<textarea style="display: none;" cols="50" rows="15" name="code" class="cpp">TCP_HEADER  tcpheader;
IP_HEADER   ipheader;
//填充IP首部
ipheader.h_verlen=(4&lt;&lt;4 | sizeof(IP_HEADER)/sizeof(unsigned long));
ipheader.total_len = htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER));
ipheader.ident = 1;
ipheader.frag_and_flags = 0;
ipheader.ttl = 128;
ipheader.proto = IPPROTO_TCP;
ipheader.checksum =0;
ipheader.sourceIP = htonl(FakeIpHost+SendSEQ);
ipheader.destIP = inet_addr(DestIP);
//填充TCP首部
tcpheader.th_dport=htons(port);
tcpheader.th_sport = htons(8080);
tcpheader.th_seq = htonl(SEQ+SendSEQ);
tcpheader.th_ack = 0;
tcpheader.th_lenres =(sizeof(TCP_HEADER)/4&lt;&lt;4|0);
tcpheader.th_flag = 2;
tcpheader.th_win = htons(16384);
tcpheader.th_urp = 0;
tcpheader.th_sum =&nbsp;</textarea>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 防御手段：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）使用硬防火墙过滤；硬件防火墙明显提高防御性能，基本能拦截95%~99%的攻击信息包；服务器依然会接受到攻击的信息包。缺点：只能被动提高防御性能</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）使用门户代理过滤；防御效果非常明显，曾经试过被20G数据攻击。经过美国某防御门户过滤后，大概只有几十K有效数据发送到服务器上。缺点：在使用了防御门户后，服务端与客户端之交互延时非常严重（&gt;1000MS）。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）修改服务器一些网络安全参数设定;如：Window
可以修改下面一些配置SynAttackProtect，TcpMaxPortsExhausted，TcpMaxHalfOpen和
TcpMaxHalfOpenRetried等；更加详细相关配置设定介绍可以到网上搜索一下,应该不少。系统的防御性能提高有限，但无需要任何投入。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4）机器群集均衡负载；这个方法是一个最有效和成本最高的方法。这里我就不多讲最后这个方法啦。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总结：SYN洪水攻击主要是攻击方与防御方比拼硬件资源和防御策略。</p>
<p>（2）流量攻击</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
原理：流量攻击主要是&#8220;肉鸡&#8221;通过对目的主机的服务端口发送大量的垃圾数据，导致目的主机的网络堵塞。在网络上很多文章都会将SYN洪水攻击和流量攻击视
作为相同手段。从监控软件来看，被这两种攻击时候都会表现为网络流量暴涨导致网络堵塞。其实，这两种攻击的网络堵塞原因是有本质上区别的。流量攻击导致网
络堵塞是某些IP机器实际发送大量垃圾信息去耗尽主机带宽；SYN洪水攻击导致网络堵塞是目标主机本身所有资源被伪造半连接请求耗尽了，使得机器根本不能
继续接受新连接。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 攻击手段：最简单流量攻击程序都是将简单Socket 程序中的sendBuf 修改为大于64K数据块就可以了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<div class="dp-highlighter">
<ol class="dp-cpp" start="1">
    <li class="alt"><span><span class="comment">//&nbsp;一般都是将'sendBuf'&nbsp;设定到64K以上随机的垃圾数据</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>sendto(sock,sendBuf,dataSize,0,(<span class="keyword">struct</span><span>&nbsp;sockaddr*)&nbsp;&amp;sockAddr,</span><span class="keyword">sizeof</span><span>(sockAddr));&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<textarea style="display: none;" cols="50" rows="15" name="code" class="cpp:showcolumns">// 一般都是将'sendBuf' 设定到64K以上随机的垃圾数据
sendto(sock,sendBuf,dataSize,0,(struct sockaddr*) &amp;sockAddr,sizeof(sockAddr));</textarea>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 防御手段：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）使用硬防火墙过滤；根据服务程序现状设定合适策略，基本拦截95~99%的垃圾信息；流量攻击拦截非常依靠硬件防火墙设定策略，有效策略会大大提高系统防御性能。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）使用门户代理过滤；参照【SYN洪水攻击】相应描述.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）优化服务端程序解密算法</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在一般网络上C/S 或者B/S
架构模式的程序，在系统互相通信指令上基本都是密文。当系统服务端程序受到攻击时候，服务的解密算法就会受到巨大压力，很容易导致服务器资源耗尽。所以，
为了提高系统在高压力下生存率，选择高效解密方法是很有必要。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4）增加服务端程序网络异常处理</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在一定高压力情况下，除了需要确保服务端的&#8221;稳定性&#8220;；还需要确保系统的&#8221;准确性&#8220;。对一些网络异常中断的情况，制定一些补救性措施和机制。特别是一些实时性系统特别重要，按过往经验在一定压力情况下会出现非常离谱错误。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5）增加服务端程序防御策略</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 由于DDos
攻击往往都使用IP地址&#8221;欺骗&#8220;技术，在行业里面暂时没有比较有效的反击方法。所以，现在最流行防御策略就是服务端&#8221; 装死 &#8220;。身边其他人称为&#8221;
信息忽略回馈机制&#8220;，主要思想就是当系统收到一个不能识别的指令时候，立即掉弃连接和不对连接作出任何反馈信息。除了&#8221;
信息忽略回馈机制&#8220;外，还有一些商业上和业务上防御策略。如： 账户锁定策略，IP锁定策略和服务器认证策略等。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总结：流量攻击是检验防御方网络流量，系统安全策略，系统异常处理和系统性能。在项目时间允许情况下，这个测试是必不可少的。</p>
<p>（3）HTTP洪水攻击</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 原理：HTTP洪水是利用【应用层】中HTTP协议缺陷；不断发送没有完成的HTTP头，直到你的服务器耗尽所有的资源。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 攻击手段：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）首先向服务器发出如下HTTP头部：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GET / HTTP/1.1\r\n<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Host: host\r\n<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User-Agent: Mozilla/4.0 (compatible; MSIE 7.0;
Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.503l3; .NET
CLR 3.0.4506.2152; .NET CLR 3.5.30729; MSOffice 12)\r\n<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Content-Length: 42\r\n</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）然后每隔一定时间继续发出一个自定义的头部：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; X-a: b\r\n<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
须知根据HTTP协议，HTTP请求头部与请求主体的分隔是多一个\r\n。也就是说上述的HTTP头部一直没有发送完成，HTTP服务器会等在那里准备
接受余下的内容，一直到接受超时，然后关闭连接。默认的apache读取头部的超时据说是3000秒。Apache的情况是，每接受一个连接新开一个进程
或线程，这样新接受一个连接的资源消耗很大，我测试的过结果是，一般apache只需在超时时间内，持续发送500个以上的包，apache就不会再接收
新的连接了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 防御手段：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）减少HTTP头部连接超时的时间，尤其是HTTP请求中GET、HEAD方法的超时时间。注意一般POST方法的头部包含了上传的内容，所以传输时间会很长，要避免将合法的请求提前关闭。<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）限定单个IP的连接数。缺点是，有些学校、大公司都通过NAT方式连接互联网，所以同一个IP的连接数会很多。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）特别针对Apache，将Nginx此类反向服务器放在apache前面，用来撑连接，代理合法的请求。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4）使用硬防火墙过滤；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5）使用门户代理过滤；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总结：HTTP协议的缺陷其实是TCP/IP协议缺陷的一个延伸，只是表现在应用层网络协议面上。</p>
<p>本人水平有限，若有不准确地方欢迎提出。</p>
<img src ="http://www.blogjava.net/ljf-tianyi/aggbug/346173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljf-tianyi/" target="_blank">天一</a> 2011-03-13 23:09 <a href="http://www.blogjava.net/ljf-tianyi/archive/2011/03/13/346173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库设计和数据库重构--小小心得</title><link>http://www.blogjava.net/ljf-tianyi/archive/2008/11/25/204143.html</link><dc:creator>天一</dc:creator><author>天一</author><pubDate>Tue, 25 Nov 2008 13:53:00 GMT</pubDate><guid>http://www.blogjava.net/ljf-tianyi/archive/2008/11/25/204143.html</guid><wfw:comment>http://www.blogjava.net/ljf-tianyi/comments/204143.html</wfw:comment><comments>http://www.blogjava.net/ljf-tianyi/archive/2008/11/25/204143.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/ljf-tianyi/comments/commentRss/204143.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljf-tianyi/services/trackbacks/204143.html</trackback:ping><description><![CDATA[对于一个软件系统，数据库设计是整个系统最核心的部分。<br />
<br />
但由于系统的需求是不断变化，使得在数据库设计变得十分重要而且困难。<br />
在需求变化非常快情况下，有一部分人会认为要寻找一种设计方法以固定不变的表结构来适用不断变化需<br />
求。这个观点是十分不明智和以现时的技术上暂时不能实现。对于软件功能程序在需求不断变法时候，为<br />
了适应新的需求，不断重构系统的代码。以相同的道理，数据库设计也是程序设计的一部分。那么，数据<br />
库一样可以使用重构来实现适用不断变化的软件系统。<br />
<br />
本人认为数据库设计将会分为两个阶段进行：<br />
<br />
第一阶段：数据库功能上的设计，由于在软件系统的数据库建立初期，数据库也只是以实现系统同能为目<br />
标，对于系统性能优化将不会是数据库设计的重点。<br />
<br />
&#183;建立软件系统的比较通用功能基础表。在基础功能建立后，系统使用者会对系统部分功能作出评价和修<br />
改要求。而功能基础表设计为减少日后修改和维护量，会尽量设计通用和冗杂结构。<br />
<br />
&#183;收集软件系统的一些基本信息。对于软件系统设计者来说，对软件系统的中每个表数据量，程序上SQL的<br />
使用，系统的繁忙时段以及周期等都会有比较初步评估。但对于数据库设计者来说，这些估计都是只一些<br />
推断并没有实际数据支持。为第二阶段数据库修改和维护，对软件系统作一些基本数据收集是必要的。<br />
<br />
第二阶段为数据库系统能上优化，主要是通过第一阶段收集系统数据库一些信息来对系统做修改和优化<br />
数据库具体优化方案需要以收集信息为基础来之际来进行指定。<br />
<br />
下面本人总结下，数据库中一般有哪些方面需要进行优化。<br />
<br />
1优化系统的SQL，具体有下面几点可以进行：<br />
&#183;对使用频繁的SQL以创建具体功能存储过程来代替，可以减少数据库系统对SQL编译和解析<br />
&#183;涉及到数据量大的表，尽量建立基本视图来完成数据查询工作<br />
&#183;在程序中尽量使用批量提交<br />
(注：此方法在多数据更新和插入软件系统中 ，可以比较显著提高性能。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 在提高系统性能的同时，对程序的多线程控制技术上增加不少难度。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 若线程控制出现问题，会对数据库带来灾难性破坏)<br />
&#183;程序在使用SQL的时候，尽量使用少消耗数据库资源的运行方式<br />
<br />
2 数据库表结构的<br />
&#183;在数据量大表中，尽量减少非必要字段索引建立。<br />
（注： 索引建立多了查询速度是可以很有效的提高，但随之而来的是插入数据消耗的数据库资源也提高了很多）<br />
&#183;大表需要进行分区存储<br />
（注：现在主流数据库都已经开始支持分区存储数据）<br />
&#183;在不影响系统的业务逻辑上，清理数据表中被废弃使用的字段<br />
&nbsp;(注：在清理废弃的字段需要关注的确定这些字段是否真的已经被废弃，程序真的不再启用)<br />
<br />
3 修改有问题的SQL<br />
&#183;在实现功能时候，由于时间或者其他原因整个系统中肯定会有部分性能不优的SQL存在。第一阶段收集的数据，现在就可以有效的进行使用。通过这些数据我们可以很有效地把这些不优的SQL[甚至是很烂]找出来，一条一条进行调整<br />
&#183;在调整SQL外，还需要对数据库内存或者共享空间等等进行调整；使得数据库永远是处于最优的状态。<br />
<br />
以上是本人一些小小心得，如果不对的地方欢迎指教。<br />
<br />
<span style="font-size: 12pt; font-family: Georgia;">&nbsp;&nbsp;&nbsp; &nbsp; MK-TIANYI</span><br />
<img src ="http://www.blogjava.net/ljf-tianyi/aggbug/204143.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljf-tianyi/" target="_blank">天一</a> 2008-11-25 21:53 <a href="http://www.blogjava.net/ljf-tianyi/archive/2008/11/25/204143.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于MySQL奇怪的问题</title><link>http://www.blogjava.net/ljf-tianyi/archive/2007/03/10/101632.html</link><dc:creator>天一</dc:creator><author>天一</author><pubDate>Sat, 10 Mar 2007 14:38:00 GMT</pubDate><guid>http://www.blogjava.net/ljf-tianyi/archive/2007/03/10/101632.html</guid><wfw:comment>http://www.blogjava.net/ljf-tianyi/comments/101632.html</wfw:comment><comments>http://www.blogjava.net/ljf-tianyi/archive/2007/03/10/101632.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljf-tianyi/comments/commentRss/101632.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljf-tianyi/services/trackbacks/101632.html</trackback:ping><description><![CDATA[在MySQL中运行mysqldump出现一个比较奇怪的问题，就是用root 运行mysqldump，结果出现一个错误，就是can't create the file ...'select outfile'.<br />
给那个文件夹的权限为 : 777,但依然出现以下错误 : can't create the file ...'select outfile'.<br />
用mysqld_safe --user = root 启动数据库,再用mysqldump 把数据导出来就成功了.<br />
原因何在请各位指教?? 
<img src ="http://www.blogjava.net/ljf-tianyi/aggbug/101632.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljf-tianyi/" target="_blank">天一</a> 2007-03-10 22:38 <a href="http://www.blogjava.net/ljf-tianyi/archive/2007/03/10/101632.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Euclid 算法</title><link>http://www.blogjava.net/ljf-tianyi/archive/2006/04/20/42137.html</link><dc:creator>天一</dc:creator><author>天一</author><pubDate>Thu, 20 Apr 2006 04:46:00 GMT</pubDate><guid>http://www.blogjava.net/ljf-tianyi/archive/2006/04/20/42137.html</guid><wfw:comment>http://www.blogjava.net/ljf-tianyi/comments/42137.html</wfw:comment><comments>http://www.blogjava.net/ljf-tianyi/archive/2006/04/20/42137.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljf-tianyi/comments/commentRss/42137.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljf-tianyi/services/trackbacks/42137.html</trackback:ping><description><![CDATA[欧几里得算法就是求最大公约数的展转相除法。<br />
用c语言描述如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;Euclid_Algorithm&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;m,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;n)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;temp&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;m;<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">m&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">!</span><span style="color: #000000;">n)&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">; </span><span style="color: #0000ff;"><br />
&nbsp;&nbsp; if</span><span style="color: #000000;">&nbsp;(m&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;n)&nbsp;{m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;n;&nbsp;n&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;temp;<br />
}&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">1</span><span style="color: #000000;">)&nbsp;{ <br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">(m&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;m&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;n))&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;n; <br />
</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">!</span><span style="color: #000000;">(n&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;n&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;m))&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;m;&nbsp;}&nbsp; <br />
</span></div>
&nbsp;<br />
<br />
<br />
&nbsp;knuth说：当m,n取某两个巨大的数时，展转的次数超过百万次。<br />
&nbsp;我开始还不相信，又翻了几页发现用fibonacci数就能找到展转次数最多的两个数，这两个数就是F[n]和F[n+1]^_^，很容易验证最大展转次数k = log<g>(n)，就是以黄金分割G为底n的对数。
<br />
写到这里就算完了，但还须证明一个先决条件，就是fibonacci相临两项互质。一个方法是利用这个性质：
F[n-1] * F[n+1] - F[n]^2 = (-1)^n
=&gt;F[n-1]^2 + F[n-1] * F[n] - F[n]^2 = (-1)^n
说明F[n-1]与F[n]是互素的，因为其中任何公因子都将是(-1)^n的一个因子。
</g>
<img src ="http://www.blogjava.net/ljf-tianyi/aggbug/42137.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljf-tianyi/" target="_blank">天一</a> 2006-04-20 12:46 <a href="http://www.blogjava.net/ljf-tianyi/archive/2006/04/20/42137.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>匯編指令</title><link>http://www.blogjava.net/ljf-tianyi/archive/2006/04/19/41895.html</link><dc:creator>天一</dc:creator><author>天一</author><pubDate>Wed, 19 Apr 2006 06:14:00 GMT</pubDate><guid>http://www.blogjava.net/ljf-tianyi/archive/2006/04/19/41895.html</guid><wfw:comment>http://www.blogjava.net/ljf-tianyi/comments/41895.html</wfw:comment><comments>http://www.blogjava.net/ljf-tianyi/archive/2006/04/19/41895.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljf-tianyi/comments/commentRss/41895.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljf-tianyi/services/trackbacks/41895.html</trackback:ping><description><![CDATA[一、数据传输指令
───────────────────────────────────────
<br />
它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.
<br />
1. 通用数据传送指令.
<br />
MOV    传送字或字节.
<br />
MOVSX  先符号扩展,再传送.
<br />
MOVZX  先零扩展,再传送.
<br />
PUSH    把字压入堆栈.
<br />
POP    把字弹出堆栈.
<br />
PUSHA  把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
<br />
POPA    把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
<br />
PUSHAD  把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
<br />
POPAD  把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
<br />
BSWAP  交换32位寄存器里字节的顺序
XCHG    交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数)
<br />
CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX ) <br />
XADD    先交换再累加.( 结果在第一个操作数里 )<br />
XLAT    字节查表转换.
── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即
0-FFH); 返回 AL 为查表结果. ( [BX+AL]-&gt;AL )
<br />
<br />
2. 输入输出端口传送指令.
IN      I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
OUT    I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )
输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,
其范围是 0-65535.
<br />
3. 目的地址传送指令.
LEA    装入有效地址.
<br />
<br />
例: <br />
LEA DX,string  ;把偏移地址存到DX.
<br />
LDS    传送目标指针,把指针内容装入DS.
<br />
<br />
例: <br />
LDS SI,string  ;把段地址:偏移地址存到DS:SI.
<br />
LES    传送目标指针,把指针内容装入ES.
<br />
<br />
例: <br />
LES DI,string  ;把段地址:偏移地址存到ES:DI.
<br />
LFS    传送目标指针,把指针内容装入FS.
<br />
<br />
例: <br />
LFS DI,string  ;把段地址:偏移地址存到FS:DI.
<br />
LGS    传送目标指针,把指针内容装入GS.
<br />
<br />
例: <br />
LGS DI,string  ;把段地址:偏移地址存到GS:DI.
<br />
LSS    传送目标指针,把指针内容装入SS.
<br />
<br />
例: LSS DI,string  ;把段地址:偏移地址存到SS:DI. <br />
<br />
4. 标志传送指令.
<br />
LAHF    标志寄存器传送,把标志装入AH.
<br />
SAHF    标志寄存器传送,把AH内容装入标志寄存器.
<br />
PUSHF  标志入栈.
<br />
POPF    标志出栈.
<br />
PUSHD  32位标志入栈.
<br />
POPD    32位标志出栈.
<br />
<br />
二、算术运算指令
───────────────────────────────────────
<br />
<br />
ADD    加法.
<br />
ADC    带进位加法.
<br />
INC    加 <br />
1.
AAA    加法的ASCII码调整.
<br />
DAA    加法的十进制调整.
<br />
SUB    减法.
<br />
SBB    带借位减法.
<br />
DEC    减 1. <br />
NEC    求反(以 0 减之). <br />
CMP    比较.(两操作数作减法,仅修改标志位,不回送结果). <br />
AAS    减法的ASCII码调整.
<br />
DAS    减法的十进制调整.
<br />
MUL    无符号乘法. <br />
IMUL    整数乘法.
以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算),
<br />
AAM    乘法的ASCII码调整.
<br />
DIV    无符号除法.
<br />
IDIV    整数除法.
<br />
以上两条,结果回送:
商回送AL,余数回送AH, (字节运算);
或  商回送AX,余数回送DX, (字运算). <br />
AAD    除法的ASCII码调整. <br />
CBW    字节转换为字. (把AL中字节的符号扩展到AH中去)
<br />
CWD    字转换为双字. (把AX中的字的符号扩展到DX中去)
<br />
CWDE    字转换为双字. (把AX中的字符号扩展到EAX中去) <br />
CDQ    双字扩展.    (把EAX中的字的符号扩展到EDX中去)
<br />
<br />
三、逻辑运算指令
───────────────────────────────────────
<br />
<br />
AND    与运算.
<br />
OR      或运算.
<br />
XOR    异或运算.
<br />
NOT    取反.
<br />
TEST    测试.(两操作数作与运算,仅修改标志位,不回送结果).
<br />
SHL    逻辑左移.
<br />
SAL    算术左移.(=SHL)
<br />
SHR    逻辑右移.<br />
SAR    算术右移.(=SHR)
<br />
ROL    循环左移.
<br />
ROR    循环右移.
<br />
RCL    通过进位的循环左移.
<br />
RCR    通过进位的循环右移.
<br />
<br />
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码.  如 SHL AX,1.
移位&gt;1次时, 则由寄存器CL给出移位次数.
如  MOV CL,04
SHL AX,CL
<br />
<br />
四、串指令
───────────────────────────────────────
<br />
<br />
DS:SI  源串段寄存器  :源串变址.
<br />
ES:DI  目标串段寄存器:目标串变址.
<br />
CX      重复次数计数器.
AL/AX  扫描值.
<br />
D标志  0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志  用来控制扫描或比较操作的结束.
<br />
MOVS    串传送.
( MOVSB  传送字符.    MOVSW  传送字.    MOVSD  传送双字. )
<br />
CMPS    串比较.
( CMPSB  比较字符.    CMPSW  比较字. ) <br />
SCAS    串扫描.
把AL或AX的内容与目标串作比较,比较结果反映在标志位.
<br />
LODS    装入串.
把源串中的元素(字或字节)逐一装入AL或AX中.
( LODSB  传送字符.    LODSW  传送字.    LODSD  传送双字. )
<br />
STOS    保存串.
是LODS的逆过程.<br />
REP            当CX/ECX&lt;&gt;0时重复.
<br />
REPE/REPZ      当ZF=1或比较结果相等,且CX/ECX&lt;&gt;0时重复.
REPNE/REPNZ    当ZF=0或比较结果不相等,且CX/ECX&lt;&gt;0时重复.
<br />
REPC          当CF=1且CX/ECX&lt;&gt;0时重复.
REPNC          当CF=0且CX/ECX&lt;&gt;0时重复.
<br />
<br />
五、程序转移指令
───────────────────────────────────────
<br />
1&gt;无条件转移指令 (长转移)
JMP    无条件转移指令
CALL    过程调用
RET/RETF过程返回. <br />
2&gt;条件转移指令 (短转移,-128到+127的距离内)
( 当且仅当(SF XOR OF)=1时,OP1<op2 )="" ja="" jnbe=""  不小于或不等于时转移.="" jae="" jnb="" jb="" jnae="" jbe="" jna=""  以上四条,测试无符号整数运算的结果(标志c和z).="" jg="" jnle=""  大于转移.="" jge="" jnl=""  大于或等于转移.="" jl="" jnge=""  小于转移.="" jle="" jng=""  小于或等于转移.="" 以上四条,测试带符号整数运算的结果(标志s,o和z).="" je="" jz=""  等于转移.="" jne="" jnz=""  不等于时转移.="" jc=""  有进位时转移.="" jnc=""  无进位时转移.="" jno=""  不溢出时转移.="" jnp="" jpo=""  奇偶性为奇数时转移.="" jns="" 0="" jo=""  溢出转移.="" jp="" jpe=""  奇偶性为偶数时转移.="" js=""  符号位为="" 1=""  时转移.="" 3="">循环控制指令(短转移)
<br />
LOOP            CX不为零时循环.
<br />
LOOPE/LOOPZ    CX不为零且标志Z=1时循环. <br />
LOOPNE/LOOPNZ  CX不为零且标志Z=0时循环.
<br />
JCXZ            CX为零时转移.
<br />
JECXZ          ECX为零时转移.
<br />
<br />
4&gt;中断指令
<br />
INT    中断指令
<br />
INTO    溢出中断
<br />
IRET    中断返回
<br />
<br />
5&gt;处理器控制指令
<br />
HLT    处理器暂停, 直到出现中断或复位信号才继续.
<br />
WAIT    当芯片引线TEST为高电平时使CPU进入等待状态.
<br />
ESC    转换到外处理器.
<br />
LOCK    封锁总线.
<br />
NOP    空操作.
<br />
STC    置进位标志位.
<br />
CLC    清进位标志位.
<br />
CMC    进位标志取反.
<br />
STD    置方向标志位. <br />
CLD    清方向标志位.
<br />
STI    置中断允许位. <br />
CLI    清中断允许位.
<br />
<br />
六、伪指令
───────────────────────────────────────
<br />
DW      定义字(2字节).
<br />
PROC    定义过程.
<br />
ENDP    过程结束.
<br />
SEGMENT 定义段.
<br />
ASSUME  建立段寄存器寻址. <br />
ENDS    段结束.
<br />
END    程序结束 </op2>
<img src ="http://www.blogjava.net/ljf-tianyi/aggbug/41895.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljf-tianyi/" target="_blank">天一</a> 2006-04-19 14:14 <a href="http://www.blogjava.net/ljf-tianyi/archive/2006/04/19/41895.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>