in

SDT Community Server

SDT Forums, Blogs, Photos server.

Floating Heart

No description is bad.
  • ASP.NET的Session会导致的性能问题

    http://www.cnblogs.com/sumtec/archive/2009/07/10/1520216.html

    你的站点有被客户投诉很慢吗?是不是查了很多遍还是没有完全解决?是不是数据库没有发现异常,CPU也没有异常,内存占用量没有异常,GC计数没有异常,硬盘IO也没有异常,带宽没有异常,线路没有异常,没有丢包,但就是被投诉?而且还是阵发性的,有某个用户投诉慢的时候,你访问却很快,本地又复现不出来?今天你访问了博客园真是太幸运了,也许这里就有你想要的一个答案——假如你的站点动态处理了图片或者其他原本不会动态处理的非网页资源的话。没想到吧,这是Session惹的祸!

    我们公司某个站点访问量一直很大,几年前就已经发现客户经常投诉说很慢,而这个问题我们一直都在排查和解决。从线路问题,到数据库连接泄露,到数据库死锁、索引,以及程序的优化问题,我们都查找过,并且解决过。然而,这个问题总还是存在。比如说,在IIS日志中,就会经常看到time-taken大于10秒钟的访问。而最近我们的KPI要求解决这个问题,不得已,再次踏上这趟艰难的排查之旅。

    之所以说艰难,是因为这个现象在本地几乎无法复现,一个是这个现象是阵发性的,第二个是本地访问量或者数据量不够大。我们也尝试过在本地加载线上服务器的数据库,然后拿服务器的IIS的Log文件重播,结果确实是偶尔发现IIS日志中的time-taken也会比较长,但是本地服务器性能不如线上服务器的,比如说IO就差很远,于是总说不清楚到底是什么问题。而线上服务器也不方便用做Dump的形式查找:第一是因为线上一做Dump,站点就会在几分钟内失去响应,这样我们客服的电话就会被打爆;另一个原因还是阵发性的问题,我们不可能一直盯着性能看,然后在发生问题的瞬间做Dump。再说了,看性能也看不出来,因为那些响应时间很长的访问,其前后附近的响应都特别的快。不可避免的,我们只能够在代码里面塞入一些调试和日志的代码,以期望能够得到一些有用的信息。

    最开始的时候,我们认为最可能的原因是数据库阻塞,比如正好某一个访问锁住某个数据库对象(比如一张表或者某几行),如果这个时候访问特定的页面,可能就会比较慢。于是在数据库层塞入了一堆代码,这些代码会在数据库连接数量多,或者某个数据库连接时间特别长的时候,将所有数据库连接的当前访问语句、连接持续总时间,以及这些连接当前的堆栈情况都输出到文件中。与此同时,我们还打开Sql profiler对这个数据库进行监视,将持续时间超过1秒钟的都记录下来。然而跑了一天之后,却发现什么都没有被记录下来,但IIS日志中仍然在这段时间内出现许多10秒以上的访问。这个时候,我们就意识到,可能方向错了。

    接着,我们就开始塞另外一段代码:一个IHttpModule。这个模块就只是截获每一个页面访问的完整生命周期中的所有事件,比如BeginRequest、PreAuthenticateRequest等。同时在BeginRequest开始的时候设置一个定时器,每隔一秒钟就会出发一个事件,来记录本次访问过程中,本模块收集到的所有线程中当前的堆栈情况。最后,在EndRequest的时候,如果访问时间超过5秒,就将之前截获的所有信息输出到文件中。这一下子问题就变得非常的清晰了,比如说,下面这种输出(片断)就是非常典型的一个情况:

    #Steps:
    #Fields: date time threadId stepName
    #---------------------------------------------------
    2009-07-09 16:48:01.752 0024 BeginRequest
    2009-07-09 16:48:01.752 0024 AuthenticateRequest
    2009-07-09 16:48:01.752 0024 PostAuthenticateRequest
    2009-07-09 16:48:01.752 0024 AuthorizeRequest
    2009-07-09 16:48:01.752 0024 PostAuthorizeRequest
    2009-07-09 16:48:01.752 0024 ResolveRequestCache
    2009-07-09 16:48:01.752 0024 PostResolveRequestCache
    2009-07-09 16:48:01.752 0024 PostMapRequestHandler
    2009-07-09 16:48:06.284 0007 AcquireRequestState
    2009-07-09 16:48:06.284 0007 PostAcquireRequestState
    2009-07-09 16:48:06.284 0007 PreRequestHandlerExecute
    2009-07-09 16:48:06.284 0007 EndRequest
    #---------------------------------------------------
    #End of steps.

    也就是说,在PostMapRequestHandler之后,AcquireRequestState之前,有一大段的等待时间。而这个报告后面的堆栈情况,则显得很奇怪:线程7从第一次截快照的时候开始,一直到结束都是空白的!甚至在其他的一些报告中甚至会发现这个线程已经被分派处理其他页面的工作了(堆栈中的调用很明显指出是另一个aspx页面的代码)。结果一Google“PostMapRequestHandler”和“AcquireRequestState”这两个关键字,就找到了国外另一个有类似遭遇的受害者:

    http://forums.iis.net/t/1147300.aspx

    这个楼主是一个aspx页面里面有好几个iframe,并且每一个iframe里面都是访问同一个Web应用下的Aspx页面。现象就是iframe内的页面会一个个蹦出来,尤其是这些页面都比较慢的时候。和我这里截获到的情况一样,也是PostMapRequestHandler事件到AcquireRequestState之间有很长的空白时间。顺藤摸瓜,又找到了这么一个帖子:

    http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.dotnet.framework.aspnet&mid=7f56033f-caac-47c2-bd9c-95512aa14b47

    原来,在AcquireRequestState之前,需要等待上一个同SessionId的页面处理完毕之后,才会继续处理当前页面。其根本原因是:同一个SessionId下面的Session对象不应该被同时写入,否则就会全乱套了,原理和多线程竞争是一样的。因此在设计上,同一个SessionId的页面(或者IHttpHandler)就会顺序执行。

    好了,到这里真相又一次大白了!(指不定还有别的问题,还会有下一次大白的时候)在我们的系统中,由于特殊的原因,对图片的输出我们会通过Asp.Net来处理,比如说加上一些合适的缓存标记,甚至会动态生成图片输出(令人惊讶的是,这个动态输出的总时间消耗甚至不到100毫秒,所以不要说动态生成是一种不好的实施方式)。但是,由于没有经过特殊处理,Asp.Net底层认为这些访问时需要对Session进行写操作的,于是就在AcquireRequestState之前挂起,等待上一次同SessionId访问结束。可想而知,图片多了就会导致排队,甚至排很长的队。如果在排队结束之前访问下一个页面,正好系统又没有丢掉之前的队列,则这次访问就会变得比较漫长了。那么怎么做呢? 在一次顺藤摸瓜,找到了确切的说法:

    http://msdn.microsoft.com/en-us/library/ms178581.aspx

    注意下面的这段话:

    Concurrent Requests and Session State

    Access to ASP.NET session state is exclusive per session, which means that if two different users make concurrent requests, access to each separate session is granted concurrently. However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished. (The second session can also get access if the exclusive lock on the information is freed because the first request exceeds the lock time-out.) If theEnableSessionState value in the @ Page directive is set to ReadOnly, a request for the read-only session information does not result in an exclusive lock on the session data. However, read-only requests for session data might still have to wait for a lock set by a read-write request for session data to clear.

     也就是说,对于页面,我们可以简单的在Aspx上的<% @Page %>内设置EnableSessionState=”false”,或者EnableSessionState=”ReadOnly”,就可以减轻这种问题的症状。前一种设置将会禁止对Session的访问,而后一种设置则只能允许只读访问(你不能够对Session进行写操作)。正好,我们刚才提到的IHttpHandler中,对图片进行处理的部分,是不需要对Session进行写操作的,但是却需要读取Session(根据状态不同,而需要获取一些特殊信息),因此可以采取上述的措施来解决问题。

    上述参考文献中,并没有说明如何对不是Page的IHttpHandler如何设置,这里我特别说明一下。对于自定义的一个实现了IHttpHandler接口的类,只要同时实现IReadOnlySessionState,即可达到EnableSessionState="ReadOnly"的效果。同时,如果没有实现IRequiresSessionState,则等价于EnableSessionState=”false”的效果。

    注意:本文所说的,不是说你在代码里面有没有用到Session,Asp.Net不会扫描你的代码看看有没有访问Session,或者在你第一次访问Session的时候才会加锁。Asp.Net是在AcquireRequestState事件之前就首先申请这个锁——只要你的页面没有设置EnableSessionState=”false”或EnableSessionState=”ReadOnly”,或者你的IHttpHandler实现了IRequiresSessionState却没有实现IReadOnlySessionState接口就会这样。回复中有很多同学说“只要我不用Session不就行了吗?”或者“我从来不用Session”,这么想完全是错误的,只能说你没有理解这背后的机制,甚至可能连Asp.net生命周期都不太清楚。Asp.Net之所以在你的页面代码开始执行之前就锁定,是要保证整个环境的完整性,避免部分执行的情况。当然,也正如上面的一些引用中所提到的,你可以自己写一个SessionProvider而不做任何的锁工作,但这样做肯定有不确定性的风险,到时候只能你自己承担,并且更难复现和调试。

    后记:

    可能有不少人都知道Session是什么,也有很多人知道Asp.net的生命周期都包含哪些,比如一搜索"PostMapRequestHandler AcquireRequestState",就会出来很多中文的页面介绍HttpApplication类都有哪些事件,以及生命周期等等。而说到Session会造成特殊情况下站点性能问题的,似乎中文界我这还真是第一篇。当然了,这个问题可能比较偏,因为一般大家都只会处理Aspx页面而不会处理图片,甚至用Aspx页面来动态输出图片的机会都比较少,英文的似乎也只有文中提到的唯一一个同志提出来了。

    不过,有一个很常见的场景会受这个问题的影响,那就是“验证码”。如果验证码生成速度很慢,同时客户端浏览器选择长连接而服务器也接受长连接,则可能会影响在输出验证码完毕之前访问下一个页面的速度。反过来,我们也经常可以体验到,验证码出来的速度总是特别慢,总是“蹦”出来的,尤其是当前页面特别复杂的时候,似乎页面没有加载完就总不会出现验证码。估计我说的问题就是原因之一。

    不过验证码的问题还不是特别好解决,因为为了避免信息泄露的问题,验证码的答案通常是存在在Session里面的,而通常的设计也是一访问验证码图片,就会将验证码答案写到Session里面。所以,很不幸,文中提到的那个解决办法是行不通的,至少不是能够直接行得通的。这个问题有没有救药?有,当然有了。怎么救?哈,那就有劳你自己开动脑筋了,我这里算是点到即止了。

    Posted Feb 05 2010, 08:47 AM by wicky with no comments
    Filed under:
  • Unable to Disable Integrity Checks Cause Drivers Not Found in 64-bit Vista (x64)

    http://www.mydigitallife.info/2008/02/26/unable-to-disable-integrity-checks-cause-drivers-not-found-in-64-bit-vista-x64/

    Many Windows Vista users install non-certified or non-signed drivers on 64bit (x64) edition of Vista, which features Kernel Patch Protection that prevents unauthorized patch or change to the key resources used by the kernel or kernel code itself and its data structures from been modified. The workaround to run unsigned and uncertified drivers in 64-bit Vista is by using the following command:

    bcdedit /set loadoptions DDISABLE_INTEGRITY_CHECKS
    bcdedit -set loadoptions \”DDISABLE_INTEGRITY_CHECK”
    bcdedit -set loadoptions \DDISABLE_INTEGRITY_CHECKS”
    bcdedit.exe -set loadoptions DDISABLE_INTEGRITY_CHECKS
    Bcdedit.exe /set nointegritychecks ON

    However, when user attempts to run the above command to disable integrity checks on the loading drivers, the following error message appears:

    An error occurred while attempting to reference the specified entry.
    The system cannot find the file specified.

    And if you manage to apply setting above previously on load options, but suddenly, there are errors and problems related to rejected or unacceptable drivers or services. Vista simply does not accept any unsigned drivers or processes, causing old drivers or software processes that haven’t been updated cannot be found and installed in Vista x64. The issue is known to affect PeerGuardian, TV tuner cards, Gigabit Ethernet adapters, CD/DVD-ROM/RW drives, and many other devices. Although the devices are listed and shown in Device Manager in System Properties, but they’re not working due to the unsigned driver issue. It also affects and fails any modified system files such as patched tcpip.sys to unlock network speed potential.

    In System Event Log, there may be also log message saying something like: “Windows cannot verify the digital signature for this file. A recent hardware or software change might have installed a file that is signed incorrectly or damaged, or that might be malicious software from an unknown source.”

    The problem occurs because Microsoft has decided to disable DDISABLE_INTEGRITY_CHECKS support in updated x64 Vista, which mean users cannot disable the integrity checks anymore. Microsoft is reportedly rolled out the change various updates including KB932596, KB938979, KB938194 and KB941649 hotfixes, and probably Windows Vista Service Pack 1.

    The updates also remove the effectiveness of ignoring code signing for drivers in Group Policy. Previously, users can run “gpedit.msc” and navigate to User Configuration -> Administrative Templates -> System -> Driver Installation, and then enable the “Code signing for drivers” and set the option to “Ignore”. This option also no longer works.

    There are a few possible resolution or workaround to re-enable the ability to disable integrity checks and have DDISABLE_INTEGRITY_CHECKS option enabled so that it’s possible to load uncertified drivers or executables, such as suggestions below.

    1. Uninstall KB932596, KB938979, KB938194 and KB941649 updates from “Installed Updates” in “Programs and Features”, and never install them again. Best still, hide the updates from viewing and accidental install in Windows Update. After uninstalling and rebooting the computer, add the DDISABLE_INTEGRITY_CHECKS option and restart to disable integrity checks again. This method probably won’t work with the release of SP1, which incorporated all these changes.
    2. Press F8 key upon initial system boot up, and then choose to disable forced driver signing enforcement for that boot session. However, users have to apply this option every shutdown and restart. An easy solution to the hassle is put computer into sleep or hibernate mode instead of shutting down everytime.
    3. Use ReadyDriver Plus to permanently disable and turn off disable driver signing enforcement automatically on every system startup.
    4. Sign the driver with test certificate, which is supplied with Software Development Kit (SDK) for Windows Vista and .NET Framework 3.0 Runtime Components, and then turn of test signing mode in Vista x64 by suing “bcdedit.exe /set TESTSIGNING ON” command. This trick will need computer running consistently in testing mode, which meant for developers to try out drivers signed with self-signed or test certificate. Risk for running computer in test signing mode is unknown, and there will be “Test Mode” watermarks been labeled on four corner of desktop, although the 64-bit watermark can also be removed.

     

    Posted Jan 23 2010, 10:40 AM by wicky with no comments
    Filed under:
  • Driver Signature Enforcement Overrider 1.3b

    http://www.ngohq.com/home.php?page=dseo

    It seems that Microsoft has forgotten end users when it introduced a very restricted module of driver signature enforcement in Windows Vista and Windows 7. All drivers and system files must be digitally verified or they cannot run when using both 32-bit and 64-bit versions of Windows Vista and Windows 7. In the past, it was possible to turn that feature off in Vista, but due to new kernel security updates, it is impossible to turn it off without degrading security and stability of your operating system or putting your master boot records in risk by using other software alternatives.

    So what is the problem with digital certificates? Well, the problem is… developers have to pay Microsoft to receive verified certificates, and that makes many applications inaccessible under Windows Vista and Windows 7. However, it is still possible to turn it off by pressing the F8 function key during system boot up, but pressing F8 every time on boot up can be a serious pain in the butt. Others have found workarounds, but most of them are too risky and may trash your master boot records, at least until now thanks to our latest tool.

    How does it work?
    Microsoft is aware that developers cannot submit every beta build they are testing. Microsoft has provided a mode inside Windows Vista and Windows 7 that will allow developers to test their software before they submit it to Microsoft’s labs. Unfortunately, even in that test mode drivers and system files must have a test certificate before installation.

    The good thing is that it does not have to be digitally verified. That means we can load drivers by creating our own unverified certificates. Do not worry! You do not have to do anything; our Driver Signature Enforcement Overrider will do everything for you.

    False Positive Alert
    It has come to our attention that several Antivirus suites have listed our Driver Signature Enforcement Overrider (DSEO) as a dangerous file. That's nonsense! DSEO is safe. These Antivirus suites are being used as a tool to remove software that Microsoft deems contrary to its outlook, instead of protecting the customer from dangerous files. Read more about it here.

    Supported OSes
    * Windows Vista 32-bit
    * Windows Vista 64-bit
    * Windows Server 2008 32-bit
    * Windows Server 2008 64-bit
    * Windows 7 32-bit
    * Windows 7 64-bit

    Changes
    * Watermarks Removal Option
    * Support for Windows 7
    * Several Bug-fixes

    So how do I use it?
    First and foremost; you are using this software at your own risk, we do not take responsibility for any damages to your system, but we do not believe it can harm anyone anyway. Secondly, User Account Control (UAC) must be disabled in-order to use this tool as well.

    1. Go ahead download and launch the application from the link below. Inside its main menu, press on the “Enable Test Mode” button and follow the instructions on the screen. This will enable TESTSIGNING mode, which allows unverified system files to be loaded.

    2. Now all you have to do is to add the unverified signature to the required system files. To do so press on the “Sign a System File” button from the main menu, and enter specific filename including full path. For example: if ATITool64.sys from C:\Windows\System32\drivers refuses to load due to driver signature enforcement, you should type: “C:\Windows\System32\drivers\ATITool64.sys”, and if you would like to sign more than a single file, just repeat this procedure until you’re done, and finally reboot.

    After you enabled Test Mode and added signatures to the required system files, they should bypass Windows’s driver signature enforcement and load without any issues. However, if for some reason you are interested to revert it, you can re-launch the application, choose “Disable Test Mode” from the main menu, and reboot. If you encounter issues or having questions, feel free to post it on our forums.

    Note: User Account Control (UAC) must be disabled in-order to use this tool.
    Download

    Posted Jan 23 2010, 10:38 AM by wicky with no comments
    Filed under:
  • Outlook Express 6 (OE6) for Win7

    Outlook Express 6 (OE6) for Win7

    Outlook Express 6 (OE6) for Windows Vista,Windows 7,Windows 2008,Windows 2008 R2
     
    If you have tried Outlook 2010/2007/2003, Windows Mail, Windows Live Mail, Thunderbird, Becky, The Bat, Foxmail, Dream Mail ..., and still love Outlook Express 6, and still think it's your favorite email client, then this is the solution for you.
     
    HOW IT WORKS:
    The reason that OE6 cannot run in Vista or newer system, is Microsoft make some OE6 core DLLs incompatible, something called "DLL HELL".
    Mainly these files: inetcomm.dll, msoert2.dll, msoeacct.dll, directdb.dll.
    However, we cannot simply replace the system DLLs because that may make system or some applications stop working.
    So the trick is to let OE6 load old DLLs in current directory when running, and leave system DLLs untouched, then everything should be ok.
    The way to let this happen is to hijack NtQueryValueKey in ntdll.dll, then change the return Path to current directory if needed.
    Microsoft provide a free tool to do this kind of job, so we just use it: Detours.
     
    HOW TO USE:
    1. extract the zip file to a directory
    2. run setup.bat as administrator
    3. if you want to save password, you need to replace Protected Storage service with writable version:
    4. start msimn.exe
     
    DOWNLOAD:
     
    HISTORY:
    Version 0.1:  first release
    Posted Jan 21 2010, 08:37 AM by wicky with no comments
    Filed under:
  • BASE64编码作为QueryString时要注意的问题

        加号(+)是BASE64编码的一部分,而加号在QueryString中被当成是空格。
        因此,当一个含有BASE64编码的字符串直接作为URL的一部分时,如果其中含有加号,则使用QueryString读取时,再使用BASE64解码就会发生错误。

        解决的办法有两个:
    一是使用BASE64的字符串作为URL的一部分是,使用UrlEncode一类的函数进行编码;
    二是在接收BASE64字符串后,使用Replace将字符串中的空格替换成加号,然后再解码。

    Posted Jan 19 2010, 08:53 AM by wicky with no comments
    Filed under:
  • 如何解决TIME_WAIT过多的解决办法

    linux和windows下TIME_WAIT过多的解决办法

    如果使用了nginx代理,那么系统TIME_WAIT的数量会变得比较多,这是由于nginx代理使用了短链接的方式和后端交互的原因,使得nginx和后端的ESTABLISHED变得很少而TIME_WAIT很多。这不但发生在安装nginx的代理服务器上,而且也会使后端的app服务器上有大量的TIME_WAIT。查阅TIME_WAIT资料,发现这个状态很多也没什么大问题,但可能因为它占用了系统过多的端口,导致后续的请求无法获取端口而造成障碍。

    虽然TIME_WAIT会造成一些问题,但是要完全枪毙掉它也是不正当的,虽然看起来这么做没什么错。具体可看这篇文档:

    http://hi.baidu.com/tim_bi/blog/item/35b005d784ca91d5a044df1d.html

    所以目前看来最好的办法是让每个TIME_WAIT早点过期。

    在linux上可以这么配置:

    #让TIME_WAIT状态可以重用,这样即使TIME_WAIT占满了所有端口,也不会拒绝新的请求造成障碍
    echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
    #让TIME_WAIT尽快回收,我也不知是多久,观察大概是一秒钟
    echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle

    很多文档都会建议两个参数都配置上,但是我发现只用修改tcp_tw_recycle就可以解决问题的了,TIME_WAIT重用TCP协议本身就是不建议打开的。

    不能重用端口可能会造成系统的某些服务无法启动,比如要重启一个系统监控的软件,它用了40000端口,而这个端口在软件重启过程中刚好被使用了,就可能会重启失败的。linux默认考虑到了这个问题,有这么个设定:

    #查看系统本地可用端口极限值
    cat /proc/sys/net/ipv4/ip_local_port_range

    用这条命令会返回两个数字,默认是:32768 61000,说明这台机器本地能向外连接61000-32768=28232个连接,注意是本地向外连接,不是这台机器的所有连接,不会影响这台机器的80端口的对外连接数。但这个数字会影响到代理服务器(nginx)对app服务器的最大连接数,因为nginx对app是用的异步传输,所以这个环节的连接速度很快,所以堆积的连接就很少。假如nginx对app服务器之间的带宽出了问题或是app服务器有问题,那么可能使连接堆积起来,这时可以通过设定nginx的代理超时时间,来使连接尽快释放掉,一般来说极少能用到28232个连接。

    因为有软件使用了40000端口监听,常常出错的话,可以通过设定ip_local_port_range的最小值来解决:

    echo "40001 61000" > /proc/sys/net/ipv4/ip_local_port_range

    但是这么做很显然把系统可用端口数减少了,这时可以把ip_local_port_range的最大值往上调,但是好习惯是使用不超过32768的端口来侦听服务,另外也不必要去修改ip_local_port_range数值成1024 65535之类的,意义不大。

    因为使用了nginx代理,在windows下也会造成大量TIME_WAIT,当然windows也可以调整:

    在注册表(regedit)的HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,值就是秒数,即可。

    windows默认是重用TIME_WAIT,我现在还不知道怎么改成不重用的,本地端口也没查到是什么值,但这些都关系不大,都可以按系统默认运作。

    ------------------------------------------------------------------------------------------------------------------------

    TIME_WAIT状态

    根据TCP协议,主动发起关闭的一方,会进入TIME_WAIT状态,持续2*MSL(Max Segment Lifetime),缺省为240秒,在这个post中简洁的介绍了为什么需要这个状态。

    值得一说的是,对于基于TCP的HTTP协议,关闭TCP连接的是Server端,这样,Server端会进入TIME_WAIT状态,可想而知,对于访问量大的Web Server,会存在大量的TIME_WAIT状态,假如server一秒钟接收1000个请求,那么就会积压240*1000=240,000个TIME_WAIT的记录,维护这些状态给Server带来负担。当然现代操作系统都会用快速的查找算法来管理这些TIME_WAIT,所以对于新的TCP连接请求,判断是否hit中一个TIME_WAIT不会太费时间,但是有这么多状态要维护总是不好。

    HTTP协议1.1版规定default行为是Keep-Alive,也就是会重用TCP连接传输多个request/response,一个主要原因就是发现了这个问题。还有一个方法减缓TIME_WAIT压力就是把系统的2*MSL时间减少,因为240秒的时间实在是忒长了点,对于Windows,修改注册表,在HKEY_LOCAL_MACHINE\ SYSTEM\CurrentControlSet\Services\ Tcpip\Parameters上添加一个DWORD类型的值TcpTimedWaitDelay,一般认为不要少于60,不然可能会有麻烦。

    对于大型的服务,一台server搞不定,需要一个LB(Load Balancer)把流量分配到若干后端服务器上,如果这个LB是以NAT方式工作的话,可能会带来问题。假如所有从LB到后端Server的IP包的source address都是一样的(LB的对内地址),那么LB到后端Server的TCP连接会受限制,因为频繁的TCP连接建立和关闭,会在server上留下TIME_WAIT状态,而且这些状态对应的remote address都是LB的,LB的source port撑死也就60000多个(2^16=65536,1~1023是保留端口,还有一些其他端口缺省也不会用),每个LB上的端口一旦进入Server的TIME_WAIT黑名单,就有240秒不能再用来建立和Server的连接,这样LB和Server最多也就能支持300个左右的连接。如果没有LB,不会有这个问题,因为这样server看到的remote address是internet上广阔无垠的集合,对每个address,60000多个port实在是够用了。

    一开始我觉得用上LB会很大程度上限制TCP的连接数,但是实验表明没这回事,LB后面的一台Windows Server 2003每秒处理请求数照样达到了600个,难道TIME_WAIT状态没起作用?用Net Monitor和netstat观察后发现,Server和LB的XXXX端口之间的连接进入TIME_WAIT状态后,再来一个LB的XXXX端口的SYN包,Server照样接收处理了,而是想像的那样被drop掉了。翻书,从书堆里面找出覆满尘土的大学时代买的《UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI》,中间提到一句,对于BSD-derived实现,只要SYN的sequence number比上一次关闭时的最大sequence number还要大,那么TIME_WAIT状态一样接受这个SYN,难不成Windows也算BSD-derived?有了这点线索和关键字(BSD),找到这个post,在NT4.0的时候,还是和BSD-derived不一样的,不过Windows Server 2003已经是NT5.2了,也许有点差别了。

    做个试验,用Socket API编一个Client端,每次都Bind到本地一个端口比如2345,重复的建立TCP连接往一个Server发送Keep-Alive=false的HTTP请求,Windows的实现让sequence number不断的增长,所以虽然Server对于Client的2345端口连接保持TIME_WAIT状态,但是总是能够接受新的请求,不会拒绝。那如果SYN的Sequence Number变小会怎么样呢?同样用Socket API,不过这次用Raw IP,发送一个小sequence number的SYN包过去,Net Monitor里面看到,这个SYN被Server接收后如泥牛如海,一点反应没有,被drop掉了。

    按照书上的说法,BSD-derived和Windows Server 2003的做法有安全隐患,不过至少这样至少不会出现TIME_WAIT阻止TCP请求的问题,当然,客户端要配合,保证不同TCP连接的sequence number要上涨不要下降。

    ----------------------------------------------------------------------------------------------------------------------------

    Socket中的TIME_WAIT状态

    在高并发短连接的server端,当server处理完client的请求后立刻closesocket此时会出现time_wait状态然后如果client再并发2000个连接,此时部分连接就连接不上了,用linger强制关闭可以解决此问题,但是linger会导致数据丢失,linger值为0时是强制关闭,无论并发多少多能正常连接上,如果非0会发生部分连接不上的情况!(可调用setsockopt设置套接字的linger延时标志,同时将延时时间设置为0。
    TCP/IP的RFC文档。TIME_WAIT是TCP连接断开时必定会出现的状态。
    是无法避免掉的,这是TCP协议实现的一部分。
    在WINDOWS下,可以修改注册表让这个时间变短一些

    time_wait的时间为2msl,默认为4min.
    你可以通过改变这个变量:
    TcpTimedWaitDelay
    把它缩短到30s
    TCP要保证在所有可能的情况下使得所有的数据都能够被投递。当你关闭一个socket时,主动关闭一端的socket将进入TIME_WAIT状态,而被动关闭一方则转入CLOSED状态,这的确能够保证所有的数据都被传输。当一个socket关闭的时候,是通过两端互发信息的四次握手过程完成的,当一端调用close()时,就说明本端没有数据再要发送了。这好似看来在握手完成以后,socket就都应该处于关闭CLOSED状态了。但这有两个问题,首先,我们没有任何机制保证最后的一个ACK能够正常传输,第二,网络上仍然有可能有残余的数据包(wandering duplicates),我们也必须能够正常处理。
    通过正确的状态机,我们知道双方的关闭过程如下

    假设最后一个ACK丢失了,服务器会重发它发送的最后一个FIN,所以客户端必须维持一个状态信息,以便能够重发ACK;如果不维持这种状态,客户端在接收到FIN后将会响应一个RST,服务器端接收到RST后会认为这是一个错误。如果TCP协议能够正常完成必要的操作而终止双方的数据流传输,就必须完全正确的传输四次握手的四个节,不能有任何的丢失。这就是为什么socket在关闭后,仍然处于 TIME_WAIT状态,因为他要等待以便重发ACK。

    如果目前连接的通信双方都已经调用了close(),假定双方都到达CLOSED状态,而没有TIME_WAIT状态时,就会出现如下的情况。现在有一个新的连接被建立起来,使用的IP地址与端口与先前的完全相同,后建立的连接又称作是原先连接的一个化身。还假定原先的连接中有数据报残存于网络之中,这样新的连接收到的数据报中有可能是先前连接的数据报。为了防止这一点,TCP不允许从处于TIME_WAIT状态的socket建立一个连接。处于TIME_WAIT状态的socket在等待两倍的MSL时间以后(之所以是两倍的MSL,是由于MSL是一个数据报在网络中单向发出到认定丢失的时间,一个数据报有可能在发送图中或是其响应过程中成为残余数据报,确认一个数据报及其响应的丢弃的需要两倍的MSL),将会转变为CLOSED状态。这就意味着,一个成功建立的连接,必然使得先前网络中残余的数据报都丢失了。

    由于TIME_WAIT状态所带来的相关问题,我们可以通过设置SO_LINGER标志来避免socket进入TIME_WAIT状态,这可以通过发送RST而取代正常的TCP四次握手的终止方式。但这并不是一个很好的主意,TIME_WAIT对于我们来说往往是有利的。

     

     

    客户端与服务器端建立TCP/IP连接后关闭SOCKET后,服务器端连接的端口
    状态为TIME_WAIT
    是不是所有执行主动关闭的socket都会进入TIME_WAIT状态呢?
    有没有什么情况使主动关闭的socket直接进入CLOSED状态呢?
    主动关闭的一方在发送最后一个 ack 后
    就会进入 TIME_WAIT 状态 停留2MSL(max segment lifetime)时间
    这个是TCP/IP必不可少的,也就是“解决”不了的。

    也就是TCP/IP设计者本来是这么设计的
    主要有两个原因
    1。防止上一次连接中的包,迷路后重新出现,影响新连接
       (经过2MSL,上一次连接中所有的重复包都会消失)
    2。可靠的关闭TCP连接
       在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发
       fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以
       主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。

    TIME_WAIT 并不会占用很大资源的,除非受到攻击。

    还有,如果一方 send 或 recv 超时,就会直接进入 CLOSED 状态

     

    socket-faq中的这一段讲的也很好,摘录如下:
    2.7. Please explain the TIME_WAIT state.

    Remember that TCP guarantees all data transmitted will be delivered,
    if at all possible. When you close a socket, the server goes into a
    TIME_WAIT state, just to be really really sure that all the data has
    gone through. When a socket is closed, both sides agree by sending
    messages to each other that they will send no more data. This, it
    seemed to me was good enough, and after the handshaking is done, the
    socket should be closed. The problem is two-fold. First, there is no
    way to be sure that the last ack was communicated successfully.
    Second, there may be "wandering duplicates" left on the net that must
    be dealt with if they are delivered.

    Andrew Gierth (andrew@erlenstar.demon.co.uk) helped to explain the
    closing sequence in the following usenet posting:

    Assume that a connection is in ESTABLISHED state, and the client is
    about to do an orderly release. The client's sequence no. is Sc, and
    the server's is Ss. Client Server
    ====== ======
    ESTABLISHED ESTABLISHED
    (client closes)
    ESTABLISHED ESTABLISHED
    ------->>
    FIN_WAIT_1
    <<--------
    FIN_WAIT_2 CLOSE_WAIT
    <<-------- (server closes)
    LAST_ACK
    , ------->>
    TIME_WAIT CLOSED
    (2*msl elapses...)
    CLOSED

    Note: the +1 on the sequence numbers is because the FIN counts as one
    byte of data. (The above diagram is equivalent to fig. 13 from RFC
    793).

    Now consider what happens if the last of those packets is dropped in
    the network. The client has done with the connection; it has no more
    data or control info to send, and never will have. But the server does
    not know whether the client received all the data correctly; that's
    what the last ACK segment is for. Now the server may or may not care
    whether the client got the data, but that is not an issue for TCP; TCP
    is a reliable rotocol, and must distinguish between an orderly
    connection close where all data is transferred, and a connection abort
    where data may or may not have been lost.

    So, if that last packet is dropped, the server will retransmit it (it
    is, after all, an unacknowledged segment) and will expect to see a
    suitable ACK segment in reply. If the client went straight to CLOSED,
    the only possible response to that retransmit would be a RST, which
    would indicate to the server that data had been lost, when in fact it
    had not been.

    (Bear in mind that the server's FIN segment may, additionally, contain
    data.)

    DISCLAIMER: This is my interpretation of the RFCs (I have read all the
    TCP-related ones I could find), but I have not attempted to examine
    implementation source code or trace actual connections in order to
    verify it. I am satisfied that the logic is correct, though.

    More commentarty from Vic:

    The second issue was addressed by Richard Stevens (rstevens@noao.edu,
    author of "Unix Network Programming", see ``1.5 Where can I get source
    code for the book [book title]?''). I have put together quotes from
    some of his postings and email which explain this. I have brought
    together paragraphs from different postings, and have made as few
    changes as possible.

    From Richard Stevens (rstevens@noao.edu):

    If the duration of the TIME_WAIT state were just to handle TCP's full-
    duplex close, then the time would be much smaller, and it would be
    some function of the current RTO (retransmission timeout), not the MSL
    (the packet lifetime).

    A couple of points about the TIME_WAIT state.

    o The end that sends the first FIN goes into the TIME_WAIT state,
    because that is the end that sends the final ACK. If the other
    end's FIN is lost, or if the final ACK is lost, having the end that
    sends the first FIN maintain state about the connection guarantees
    that it has enough information to retransmit the final ACK.

    o Realize that TCP sequence numbers wrap around after 2**32 bytes
    have been transferred. Assume a connection between A.1500 (host A,
    port 1500) and B.2000. During the connection one segment is lost
    and retransmitted. But the segment is not really lost, it is held
    by some intermediate router and then re-injected into the network.
    (This is called a "wandering duplicate".) But in the time between
    the packet being lost & retransmitted, and then reappearing, the
    connection is closed (without any problems) and then another
    connection is established between the same host, same port (that
    is, A.1500 and B.2000; this is called another "incarnation" of the
    connection). But the sequence numbers chosen for the new
    incarnation just happen to overlap with the sequence number of the
    wandering duplicate that is about to reappear. (This is indeed
    possible, given the way sequence numbers are chosen for TCP
    connections.) Bingo, you are about to deliver the data from the
    wandering duplicate (the previous incarnation of the connection) to
    the new incarnation of the connection. To avoid this, you do not
    allow the same incarnation of the connection to be reestablished
    until the TIME_WAIT state terminates.

    Even the TIME_WAIT state doesn't complete solve the second problem,
    given what is called TIME_WAIT assassination. RFC 1337 has more
    details.

    o The reason that the duration of the TIME_WAIT state is 2*MSL is
    that the maximum amount of time a packet can wander around a
    network is assumed to be MSL seconds. The factor of 2 is for the
    round-trip. The recommended value for MSL is 120 seconds, but
    Berkeley-derived implementations normally use 30 seconds instead.
    This means a TIME_WAIT delay between 1 and 4 minutes. Solaris 2.x
    does indeed use the recommended MSL of 120 seconds.

    A wandering duplicate is a packet that appeared to be lost and was
    retransmitted. But it wasn't really lost ... some router had
    problems, held on to the packet for a while (order of seconds, could
    be a minute if the TTL is large enough) and then re-injects the packet
    back into the network. But by the time it reappears, the application
    that sent it originally has already retransmitted the data contained
    in that packet.

    Because of these potential problems with TIME_WAIT assassinations, one
    should not avoid the TIME_WAIT state by setting the SO_LINGER option
    to send an RST instead of the normal TCP connection termination
    (FIN/ACK/FIN/ACK). The TIME_WAIT state is there for a reason; it's
    your friend and it's there to help you :-)

    I have a long discussion of just this topic in my just-released
    "TCP/IP Illustrated, Volume 3". The TIME_WAIT state is indeed, one of
    the most misunderstood features of TCP.

    I'm currently rewriting "Unix Network Programming" (see ``1.5 Where
    can I get source code for the book [book title]?''). and will include
    lots more on this topic, as it is often confusing and misunderstood.

    An additional note from Andrew:

    Closing a socket: if SO_LINGER has not been called on a socket, then
    close() is not supposed to discard data. This is true on SVR4.2 (and,
    apparently, on all non-SVR4 systems) but apparently not on SVR4; the
    use of either shutdown() or SO_LINGER seems to be required to
    guarantee delivery of all data.

    -------------------------------------------------------------------------------------------

    讨厌的 Socket TIME_WAIT 问题

    netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

    会得到类似下面的结果,具体数字会有所不同:

    LAST_ACK 1
    SYN_RECV 14
    ESTABLISHED 79
    FIN_WAIT1 28
    FIN_WAIT2 3
    CLOSING 5
    TIME_WAIT 1669

    状态:描述
    CLOSED:无连接是活动的或正在进行
    LISTEN:服务器在等待进入呼叫
    SYN_RECV:一个连接请求已经到达,等待确认
    SYN_SENT:应用已经开始,打开一个连接
    ESTABLISHED:正常数据传输状态
    FIN_WAIT1:应用说它已经完成
    FIN_WAIT2:另一边已同意释放
    ITMED_WAIT:等待所有分组死掉
    CLOSING:两边同时尝试关闭
    TIME_WAIT:另一边已初始化一个释放
    LAST_ACK:等待所有分组死掉

    也就是说,这条命令可以把当前系统的网络连接状态分类汇总。

    下面解释一下为啥要这样写:

    一个简单的管道符连接了netstat和awk命令。

    ------------------------------------------------------------------

    每个TCP报文在网络内的最长时间,就称为MSL(Maximum Segment Lifetime),它的作用和IP数据包的TTL类似。

    RFC793指出,MSL的值是2分钟,但是在实际的实现中,常用的值有以下三种:30秒,1分钟,2分钟。

    注意一个问题,进入TIME_WAIT状态的一般情况下是客户端,大多数服务器端一般执行被动关闭,不会进入TIME_WAIT状态,当在服务

    器端关闭某个服务再重新启动时,它是会进入TIME_WAIT状态的。

    举例:
    1.客户端连接服务器的80服务,这时客户端会启用一个本地的端口访问服务器的80,访问完成后关闭此连接,立刻再次访问服务器的

    80,这时客户端会启用另一个本地的端口,而不是刚才使用的那个本地端口。原因就是刚才的那个连接还处于TIME_WAIT状态。
    2.客户端连接服务器的80服务,这时服务器关闭80端口,立即再次重启80端口的服务,这时可能不会成功启动,原因也是服务器的连

    接还处于TIME_WAIT状态。


    检查net.ipv4.tcp_tw当前值,将当前的值更改为1分钟:
    [root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
    net.ipv4.tcp_tw_reuse = 0
    net.ipv4.tcp_tw_recycle = 0
    [root@aaa1 ~]#

    vi /etc/sysctl
    增加或修改net.ipv4.tcp_tw值:
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1

    使内核参数生效:
    [root@aaa1 ~]# sysctl -p

    [root@aaa1 ~]# sysctl -a|grep net.ipv4.tcp_tw
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1

    用netstat再观察正常


    这里解决问题的关键是如何能够重复利用time_wait的值,我们可以设置时检查一下time和wait的值
    #sysctl -a | grep time | grep wait
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait = 120
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait = 60
    net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait = 120

    问一下TIME_WAIT有什么问题,是闲置而且内存不回收吗?

    是的,这样的现象实际是正常的,有时和访问量大有关,设置这两个参数: reuse是表示是否允许重新应用处于TIME-WAIT状态的

    socket用于新的TCP连接; recyse是加速TIME-WAIT sockets回收

     

    Q: 我正在写一个unix server程序,不是daemon,经常需要在命令行上重启它,绝大
    多数时候工作正常,但是某些时候会报告"bind: address in use",于是重启失
    败。

    A: Andrew Gierth
    server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项。至于
    TIME_WAIT状态,你无法避免,那是TCP协议的一部分。

    Q: 如何避免等待60秒之后才能重启服务

    A: Erik Max Francis

    使用setsockopt,比如

    --------------------------------------------------------------------------
    int option = 1;

    if ( setsockopt ( masterSocket, SOL_SOCKET, SO_REUSEADDR, &option,
    sizeof( option ) ) < 0 )
    {
    die( "setsockopt" );
    }
    --------------------------------------------------------------------------

    Q: 编写 TCP/SOCK_STREAM 服务程序时,SO_REUSEADDR到底什么意思?

    A: 这个套接字选项通知内核,如果端口忙,但TCP状态位于 TIME_WAIT ,可以重用
    端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,
    指明"地址已经使用中"。如果你的服务程序停止后想立即重启,而新套接字依旧
    使用同一端口,此时 SO_REUSEADDR 选项非常有用。必须意识到,此时任何非期
    望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不
    可能。

    一个套接字由相关五元组构成,协议、本地地址、本地端口、远程地址、远程端
    口。SO_REUSEADDR 仅仅表示可以重用本地本地地址、本地端口,整个相关五元组
    还是唯一确定的。所以,重启后的服务程序有可能收到非期望数据。必须慎重使
    用 SO_REUSEADDR 选项。

    Q: 在客户机/服务器编程中(TCP/SOCK_STREAM),如何理解TCP自动机 TIME_WAIT 状
    态?

    A: W. Richard Stevens <1999年逝世,享年49岁>

    下面我来解释一下 TIME_WAIT 状态,这些在<>
    中2.6节解释很清楚了。

    MSL(最大分段生存期)指明TCP报文在Internet上最长生存时间,每个具体的TCP实现
    都必须选择一个确定的MSL值。RFC 1122建议是2分钟,但BSD传统实现采用了30秒。

    TIME_WAIT 状态最大保持时间是2 * MSL,也就是1-4分钟。

    IP头部有一个TTL,最大值255。尽管TTL的单位不是秒(根本和时间无关),我们仍需
    假设,TTL为255的TCP报文在Internet上生存时间不能超过MSL。

    TCP报文在传送过程中可能因为路由故障被迫缓冲延迟、选择非最优路径等等,结果
    发送方TCP机制开始超时重传。前一个TCP报文可以称为"漫游TCP重复报文",后一个
    TCP报文可以称为"超时重传TCP重复报文",作为面向连接的可靠协议,TCP实现必须
    正确处理这种重复报文,因为二者可能最终都到达。

    一个通常的TCP连接终止可以用图描述如下:

    client server
    FIN M
    close -----------------> (被动关闭)
    ACK M+1
    <-----------------
    FIN N
    <----------------- close
    ACK N+1
    ----------------->

    为什么需要 TIME_WAIT 状态?

    假设最终的ACK丢失,server将重发FIN,client必须维护TCP状态信息以便可以重发
    最终的ACK,否则会发送RST,结果server认为发生错误。TCP实现必须可靠地终止连
    接的两个方向(全双工关闭),client必须进入 TIME_WAIT 状态,因为client可能面
    临重发最终ACK的情形。

    {
    scz 2001-08-31 13:28

    先调用close()的一方会进入TIME_WAIT状态
    }

    此外,考虑一种情况,TCP实现可能面临先后两个同样的相关五元组。如果前一个连
    接处在 TIME_WAIT 状态,而允许另一个拥有相同相关五元组的连接出现,可能处理
    TCP报文时,两个连接互相干扰。使用 SO_REUSEADDR 选项就需要考虑这种情况。

    为什么 TIME_WAIT 状态需要保持 2MSL 这么长的时间?

    如果 TIME_WAIT 状态保持时间不足够长(比如小于2MSL),第一个连接就正常终止了。
    第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二
    个连接。TCP实现必须防止某个连接的重复报文在连接终止后出现,所以让TIME_WAIT
    状态保持时间足够长(2MSL),连接相应方向上的TCP报文要么完全响应完毕,要么被
    丢弃。建立第二个连接的时候,不会混淆。

    A: 小四

    在Solaris 7下有内核参数对应 TIME_WAIT 状态保持时间

    # ndd -get /dev/tcp tcp_time_wait_interval
    240000
    # ndd -set /dev/tcp tcp_time_wait_interval 1000

    缺省设置是240000ms,也就是4分钟。如果用ndd修改这个值,最小只能设置到1000ms,
    也就是1秒。显然内核做了限制,需要Kernel Hacking。

    # echo "tcp_param_arr/W 0t0" | adb -kw /dev/ksyms /dev/mem
    physmem 3b72
    tcp_param_arr: 0x3e8 = 0x0
    # ndd -set /dev/tcp tcp_time_wait_interval 0

    我不知道这样做有什么灾难性后果,参看<>的声明。

    Q: TIME_WAIT 状态保持时间为0会有什么灾难性后果?在普遍的现实应用中,好象也
    就是服务器不稳定点,不见得有什么灾难性后果吧?

    D: rain@bbs.whnet.edu.cn

    Linux 内核源码 /usr/src/linux/include/net/tcp.h 中

    #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to successfully
    * close the socket, about 60 seconds */

    最好不要改为0,改成1。端口分配是从上一次分配的端口号+1开始分配的,所以一般
    不会有什么问题。端口分配算法在tcp_ipv4.c中tcp_v4_get_port中。

     

    Posted Jan 14 2010, 11:42 AM by wicky with no comments
    Filed under:
  • A Word on TIME_WAIT and CLOSE_WAIT


    http://blog.zhuzhaoyuan.com/2009/03/a-word-on-time_wait-and-close_wait/

    I’m surprised by the fact that so many network programmers don’t know TIME_WAIT and CLOSE_WAIT well, particularly those who use Java, C#, Python and etc.

    It is true, however, TIME_WAIT and CLOSE_WAIT are the most confusing two among TCP’s 11 states (CLOSED, LISTEN, SYN_SENT, SYN_RECV, ESTABLISHED, CLOSE_WAIT, LAST_ACK, FIN_WAIT1, FIN_WAIT2, CLOSING, and TIME_WAIT), which are displayed by netstat(1).

    Before going into detail, let me explain the terms first:
    Active Open: An end sends a SYN segment to the other end by calling connect(2). This end is usually called a client.
    Passive Open: An end issues a passive open by calling socket(2), bind(2), and listen(2) so that it can accept(2) the clients’ connections. This end is usually called a server.
    Active Close: An end performs active close when it calls close(2) first. It results a FIN segment being sent.
    Passive Close: The other end receives the FIN segment performs the passive close.
    MSL: Maximum Segment Lifetime, the maximum time a segment can live in the network before being discarded.

    Now take a look at the TCP state transition diagram.

    TCP State Transition Diagram 1

    TCP State Transition Diagram 1

    TCP State Transition Diagram 2

    TCP State Transition Diagram 2

    In the diagrams above, I denote the active open/close transitions with a green line and the passive open/close transitions with a blue line (Normal transitions are in bold). The end that performs the active close goes through the TIME_WAIT state; while the end performs the passive close enters the CLOSE_WAIT state. Note that either end (the server or the client) can perform the active close!

    tcp-close

    What’s the TIME_WAIT state for?
    1) When the final ACK being sent by the end that performed the active close was lost, the other end would resend a FIN. TCP maintains the information of the connection, hence it would resend the lost ACK rather than respond with an RST (interpreted as error).
    2) To allow wandering duplicates to expire in the network, so that the duplicate segments would not corrupt later connections.

    The value of TIME_WAIT delay is 2MSL, which is TCP implementation dependent and is generally about 1-4 minutes.

    CLOSE_WAIT happens when an end has received a FIN segment from the other end, to wait for the program to close the socket. Long duration of CLOSE_WAIT suggests that there might be a bug in your program. In fact, a TCP connection can stay in the CLOSE_WAIT state forever unless it is explicitly closed. It is the application’s responsibility to close its socket after use, to release the resource of the connection.

    Conclusion:
    In most cases, there is no need to worry about TIME_WAIT. It is a safety feature of TCP. But you really should take care of CLOSE_WAIT. Also note, if a connection is in CLOSE_WAIT, it would never end up in the TIME_WAIT state, and vice versa. BTW, if you haven’t read Richard Stevens’ Unix Network Programming, go out and buy one. It is a must-have for all network programmers, even if you do Windows programming.

    Download the dot files and msc file here:
    http://www.zhuzhaoyuan.com/download/tcp/tcp-state1.dot
    http://www.zhuzhaoyuan.com/download/tcp/tcp-state2.dot
    http://www.zhuzhaoyuan.com/download/tcp/tcp_close.msc

     

    Posted Jan 14 2010, 11:39 AM by wicky with no comments
    Filed under:
  • 震撼人心的新科技 - Sixth Sense

    http://www.cnbeta.com/articles/101755.htm

    美国MIT Media Lab(麻省理工学院媒体实验室)的天才学生普拉纳夫- (Prarnav Mistry),发明了一项结合实体世界和虚拟世界的科技,令人又惊又喜;喜的是,对于未來生活,悠游於实体和虚拟之间,将更自由无限,惊的是,对于现今的人们和企业而言,这场演讲是一提醒 :「讯息上身,才有未来」。

    以下是一段视频,长达13分52秒。但是,我相信你一定不会错过任何一秒。哪怕是它有关于科技,演讲人有浓重的印度口音,但是它如此贴近我们的生活,如此关怀人性,努力把人从“机器前的机器”里解放出来,以至于你会目不转睛地看完这段实况,而且遐想翩翩,愿意努力活到22世纪。

    如果说,Windows系统的图形化界面把人们从Dos系统下解放出来,用更符合直觉和人性的方法让人们对电脑进行操作是一次新技术的跨越的话,那么视频里这套Prarnav Mistry提供的第六感(Sixth Sense)装置,则是另外一次意义更为深远的腾跃。和它相比,目前甚嚣尘上的所谓“物流网”,只是这个新技术的小小注脚,无论在深度还是广度上,都无法与之比拟。 网络和电脑技术,终于使得数字世界和现实世界全面融合,人类升级为真正意义上的数位人!新时代就要开始了!

    Posted Jan 14 2010, 10:14 AM by wicky with no comments
    Filed under:
  • 身份证最后一位可能为X

    GB11643-1999 公民身份号码中规定,最后一位校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。
    公式如下:
      ∑(aIdea*WIdea) mod 11 ( i = 2, 3, ..., 18 ) (1)
      "*" 表示乘号
      i--------表示身份证号码每一位的序号,从右至左,最左侧为18,最右侧为1。
      aIdea-----表示身份证号码第 i 位上的号码
      WIdea-----表示第 i 位上的权值 WIdea = 2^(i-1) mod 11
      计算公式 (1) 令结果为 R
    根据下表找出 R 对应的校验码即为要求身份证号码的校验码C。
      R 0 1 2 3 4 5 6 7 8 9 10
      C 1 0 X 9 8 7 6 5 4 3 2
    由此看出 X 就是 10,罗马数字中的 10 就是X,所以在新标准的身份证号码中可能含有非数字的字母X。

    Posted Jan 04 2010, 08:28 PM by wicky with no comments
    Filed under:
  • Windows Messenger 5.1 and Vista/Win7 Scroll Bar Issue

    http://www.systemsabuse.com/2007/10/18/how-do-you-install-windows-messenger-51-on-vista-with-uac-enabled/ 

    Vista - Messenger 5.1 SIP - workaround:

    1) Setup windows messenger 5.1.0.639 (SIP protocol).
    2) Download riched20.dll (version 5.0.150.0) from, for instance: http://www.dll-files.com/dllindex/dll-files.shtml?riched20
    3) Copy riched20.dll to messenger folder application.

    This riched20.dll version resolve scrollbar issue.

    Posted Dec 28 2009, 12:11 PM by wicky with no comments
    Filed under:
  • Microsoft Windows XP Pro with SP3 VOL MSDN

    http://www.iamkane.com/article.asp?id=2

    序列号:
    MRX3F-47B9T-2487J-KWKMF-RPWBY(chs可用 )

    CM3HY-26VYW-6JRYC-X66GX-JVY2D

    DP7CM-PD6MC-6BKXT-M8JJ6-RPXGJ

    F4297-RCWJP-P482C-YY23Y-XH8W3

    HH7VV-6P3G9-82TWK-QKJJ3-MXR96

    HCQ9D-TVCWX-X9QRG-J4B2Y-GR2TT

    QC986-27D34-6M3TY-JJXP9-TBGMD

    MRX3F-47B9T-2487J-KWKMF-RPWBY

    M6TF9-8XQ2M-YQK9F-7TBB2-XGG88

    换Key的vbs

    ON ERROR RESUME NEXT
    Dim VOL_PROD_KEY
    if Wscript.arguments.count<1 then
    VOL_PROD_KEY=InputBox("使用说明(OEM版无效):"&vbCr&vbCr&" 本脚本程序将修改当前 Windows 的序列号。请先使用算号器算出匹配当前 Windows 的序列号,复制并粘贴到下面空格中。"&vbCr&vbCr&"输入序列号(默认为 XP VLK):","Windows XP/2003 序列号更换工具","请在此处输入正确的Microsoft Windows XP/2003 产品密钥")
    if VOL_PROD_KEY="" then
    Wscript.quit
    end if
    else
    VOL_PROD_KEY = Wscript.arguments.Item(0)
    end if
    VOL_PROD_KEY = Replace(VOL_PROD_KEY,"-","") ''remove hyphens if any
    for each Obj in GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf ("win32_WindowsProductActivation")
    result = Obj.SetProductKey (VOL_PROD_KEY)
    if err = 0 then
    Wscript.echo "您的 Windows CD-KEY 修改成功。请检查系统属性。"
    end if
    if err <> 0 then
    Wscript.echo "修改失败!请检查输入的 CD-KEY 是否与当前 Windows 版本相匹配。"
    Err.Clear
    end if
    Next

    Posted Dec 27 2009, 07:29 PM by wicky with no comments
    Filed under:
  • Windows 2008 R2 试用版序列号

    Svr 2008 评估版序列号,可以重置五次每次180天,总计可以免费使用900天
    Product Key Type = Retail:TB:Eval   (Evaluation Keys)
    Crypto Base ID = 168
    Rearm count = 5 !

    Windows Web Server 2008 R2 = KBV3Q-DJ8W7-VPB64-V88KG-82C49
    = 00500-001-0000554-84*** = X15-34676
    Windows Server 2008 R2 Standard = 4GGC4-9947F-FWFP3-78P6F-J9HDR
    = 00477-001-0000347-84*** = X15-34648
    Windows Server 2008 R2 Enterprise = 7PJBC-63K3J-62TTK-XF46D-W3WMD
    = 00486-001-0001204-84*** = X15-34815
    Windows Server 2008 R2 Datacenter = QX7TD-2CMJR-D7WWY-KVCYC-6D2YT
    = 00496-001-0001526-84*** = X15-34820
    下面是我用slmgr.vbs /rearm重置过一次后的截图
    这个激活为啥我要说是“官方”的,(加了引号),因为这个是在微软允许的范围之内的。
      现在激活的方法除了购买正版系列号外,网络上也流传了很多方法,但是那些免费的方法首先侵犯了微软的使用协议。另外很多方法是采用替换法,或刷BIOS,这样的结果是带来计算机的损坏或系统的不稳定,实在是得不偿失。下面说说我的方法。这个方法经过笔者的亲自测试。此方法适用于任何的 win7版本。
    1.首先安装后,有一个30天的使用期。

    2.在30天试用期即将结束时,用rearm命令后重启电脑,剩余时间又回复到30天。微软官方文档中声明该命令只能重复使用3次,也说是说总共可以免费体验120天。

    方法如下:打开附件—–命令提示符。(注意要使用右键管理员方式运行)。在命令行中输入“slmgr.vbs/rearm”的命令延长使用期30天

     

    Posted Dec 24 2009, 04:34 PM by wicky with 1 comment(s)
    Filed under:
  • KILL SESSION 还存在而不马上释放得问题

    http://www.sosdb.com/jdul/dispbbs.asp?boardID=2&ID=248

    我们知道,在Oracle数据库中,可以通过kill session的方式来终止一个进程,其基本语法结构为: 

    alter system kill session 'sid,serial#' ; 
     

    被kill掉的session,状态会被标记为killed,Oracle会在该用户下一次touch时清除该进程. 


    我们发现当一个session被kill掉以后,该session的paddr被修改,如果有多个session被kill,那么多个session
    的paddr都被更改为相同的进程地址:





    SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;
    

    SADDR SID SERIAL# PADDR USERNAME STATUS
    -------- ---------- ---------- -------- ------------------------------ --------
    542E0E6C 11 314 542B70E8 EYGLE INACTIVE
    542E5044 18 662 542B6D38 SYS ACTIVE


    SQL> alter system kill session '11,314';

    System altered.

    SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;

    SADDR SID SERIAL# PADDR USERNAME STATUS
    -------- ---------- ---------- -------- ------------------------------ --------
    542E0E6C 11 314 542D6BD4 EYGLE KILLED
    542E5044 18 662 542B6D38 SYS ACTIVE


    SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;

    SADDR SID SERIAL# PADDR USERNAME STATUS
    -------- ---------- ---------- -------- ------------------------------ --------
    542E0E6C 11 314 542D6BD4 EYGLE KILLED
    542E2AA4 14 397 542B7498 EQSP INACTIVE
    542E5044 18 662 542B6D38 SYS ACTIVE

    SQL> alter system kill session '14,397';

    System altered.

    SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null;

    SADDR SID SERIAL# PADDR USERNAME STATUS
    -------- ---------- ---------- -------- ------------------------------ --------
    542E0E6C 11 314 542D6BD4 EYGLE KILLED
    542E2AA4 14 397 542D6BD4 EQSP KILLED
    542E5044 18 662 542B6D38 SYS ACTIVE



    在这种情况下,很多时候,资源是无法释放的,我们需要查询spid,在操作系统级来kill这些进程. 

    但是由于此时v$session.paddr已经改变,我们无法通过v$session和v$process关联来获得spid 

    那还可以怎么办呢? 

    我们来看一下下面的查询:



      SQL> SELECT s.username,s.status,
    
    2 x.ADDR,x.KSLLAPSC,x.KSLLAPSN,x.KSLLASPO,x.KSLLID1R,x.KSLLRTYP,
    3 decode(bitand (x.ksuprflg,2),0,null,1)
    4 FROM x$ksupr x,v$session s
    5 WHERE s.paddr(+)=x.addr
    6 and bitand(ksspaflg,1)!=0;


    USERNAME STATUS ADDR KSLLAPSC KSLLAPSN KSLLASPO KSLLID1R KS D
    ------------------------------ -------- -------- ---------- ---------- ------------ ---------- -- -
    542B44A8 0 0 0
    ACTIVE 542B4858 1 14 24069 0 1
    ACTIVE 542B4C08 26 16 15901 0 1
    ACTIVE 542B4FB8 7 46 24083 0 1
    ACTIVE 542B5368 12 15 24081 0 1
    ACTIVE 542B5718 15 46 24083 0 1
    ACTIVE 542B5AC8 79 4 15923 0 1
    ACTIVE 542B5E78 50 16 24085 0 1
    ACTIVE 542B6228 754 15 24081 0 1
    ACTIVE 542B65D8 1 14 24069 0 1
    ACTIVE 542B6988 2 30 14571 0 1

    USERNAME STATUS ADDR KSLLAPSC KSLLAPSN KSLLASPO KSLLID1R KS D
    ------------------------------ -------- -------- ---------- ---------- ------------ ---------- -- -
    SYS ACTIVE 542B6D38 2 8 24071 0
    542B70E8 1 15 24081 195 EV
    542B7498 1 15 24081 195 EV

    SYS INACTIVE 542B7848 0 0 0
    SYS INACTIVE 542B7BF8 1 15 24081 195 EV

    16 rows selected.




    我们注意,红字标出的部分就是被Kill掉的进程的进程地址. 

    简化一点,其实就是如下概念:


    SQL> select p.addr from v$process p where pid <> 1
    2 minus
    3 select s.paddr from v$session s;

    ADDR
    --------
    542B70E8
    542B7498


     

    Ok,现在我们获得了进程地址,就可以在v$process中找到spid,然后可以使用Kill或者orakill在系统级来杀掉这些进程.

    实际上,我猜测:

    当在Oracle中kill session以后, Oracle只是简单的把相关session的paddr 指向同一个虚拟地址.

    此时v$process和v$session失去关联,进程就此中断.

    然后Oracle就等待PMON去清除这些Session.所以通常等待一个被标记为Killed的Session退出需要花费很长的时间.

    如果此时被Kill的process,重新尝试执行任务,那么马上会收到进程中断的提示,process退出,此时Oracle会立即启动PMON
    来清除该session.这被作为一次异常中断处理.

     

    Posted Dec 22 2009, 03:27 PM by wicky with 2 comment(s)
    Filed under:
  • Foxmail 6.5 收取hotmail live msn邮件

    http://sunya.org.cn/article.asp?id=1259

    今天,试了下用foxmail收取gmail 跟msn邮件
    能成功收下!

    在6.5 beta 3版本已经全面支持hotmail了,只是目前没有随安装包一起发放出来

    自己琢磨了一下,就缺一个文件msidcrl40.dll,找了半天都是4.0的都不能用

    后来直接在live mail里面挖出来一个5.0的

    将其放到Foxmail安装路径3rdParty目录下

    然后在到注册表HKEY_CURRENT_USER\Software\Aerofox\Foxmail\General下,新建“字符串值”SupportHotmail,值为1。

    重新启动foxmail就可以了,新增hotmail帐号时候就会有个http服务器

    还会有个路径
    http://mail.services.live.com/DeltaSync_v2.0.0/Sync.aspx

    填上用户名、密码就可以使用了。

    PS:由于是HTTP登录,那么在客户端上Foxmail删除邮件,会同步删除hotmail上的邮件。所以要特别注意下,以免重要邮件被删除。

    PS2:附上msidcrl40.dll版本是5的,从live mail客户端里扒出的,还有注册表信息,直接导入就可以了
    点击下载

    Posted Dec 12 2009, 08:46 PM by wicky with no comments
    Filed under:
  • Overview of SQL Server 2008 Servicing Installation

    http://msdn.microsoft.com/en-us/library/dd638062.aspx

    You can upgrade any installed SQL Server 2008 component with a SQL Server 2008 servicing update. If the version level of an existing SQL Server 2008 component is later than the update version level, the Setup program will exclude it from the update.

    The following considerations apply when you install SQL Server 2008 updates:

    • All features that belong to an instance of SQL Server must be updated at the same time. For example, when you update the Database Engine, you must also update Analysis Services and Reporting Services components if they are installed as part of the same instance of SQL Server. Shared features, such as Management Tools, Business Intelligence Development Studio, and SQL Server Integration Services, must always be updated to the most recent update. If a component or instance in the feature tree is not selected, the component or instance will not be updated.
    • By default, SQL Server 2008 update log files are saved to %Program Files%\Microsoft SQL Server\100\Setup Bootstrap\LOG\.
    • Starting with Service Pack 1 (SP1), you can now slipstream an update with the original media to run the original media and the update at the same time. For more information, see Slipstream a SQL Server Update.
    • Before you apply a SQL Server 2008 servicing update, we recommend that you consider backing up your data.
    • SQL Server updates are available through Microsoft Update. We recommend that you scan for updates regularly to keep your instance of SQL Server updated and secure.

    For more information, see How to apply a SQL Server 2008 update to a failover cluster instance in the Microsoft Knowledge Base.

    The recommended disk space requirements are approximately 2.5 times the size of the package to install, download, and extract the package.

    The size of SP1 packages are listed here:

    • X86: 270 MB
    • X64: 331 MB
    • Ia64: 320 MB

    After installing SP1, you can remove the downloaded package. Any temporary files are removed automatically.

    This section discusses the SQL Server 2008 update installation, including how to do the following:

    • Prepare for a SQL Server 2008 update installation
    • Install SQL Server 2008 updates
    • Restart services and applications

    Prepare for a SQL Server 2008 Update Installation

    You must do the following before you install SQL Server 2008 updates:

    • Back up your SQL Server 2008 system databases — Before you install SQL Server 2008 updates, back up the master, msdb, and model databases. Installing a SQL Server 2008 update changes these databases, making them incompatible with earlier versions of SQL Server 2008. Backups of these databases are required if you decide to reinstall SQL Server 2008 without these updates.
      It is also prudent to back up your user databases.
    Dd638062.note(en-us,SQL.100).gifImportant:
    When you apply updates to instances of SQL Server that participate in a replication topology, you must back up your replicated databases together with your system databases before you apply the update.

    • Back up your Analysis Services databases, configuration file, and repository — Before you update an instance of Analysis Services, you should back up the following:
      • Analysis Services databases. By default, these are installed to C:\Program Files\Microsoft SQL Server\MSAS10\<InstanceID>\OLAP\Data\.
      • Analysis Services configuration setting in the msmdsrv.ini configuration file. By default, this is located in the C:\Program Files\Microsoft SQL Server\MSAS10\<InstanceID>\OLAP\Config\ directory.
      • (Optional) The database that contains the Analysis Services repository. This step is required only if Analysis Services was configured to work with the Decision Support Objects (DSO) library.
    Dd638062.note(en-us,SQL.100).gifNote:
    Failure to back up your Analysis Services databases, configuration file, and repository will prevent you from reverting an updated instance of Analysis Services to the earlier version.

    • Verify that the system databases have sufficient free space — If the autogrow option is not selected for the master and msdb system databases, these databases each must have at least 500 KB of free space. To verify that the databases have sufficient space, run the sp_spaceused system stored procedure on the master and msdb databases. If the unallocated space in either database is less than 500 KB, increase the size of the database. For more information, see "Expanding a Database" in SQL Server Books Online.
    • Stop Services and Applications — To avoid a possible restart of the system, stop all applications and services that make connections to the instances of SQL Server that are being upgraded, before installing SQL Server 2008 updates. These include SQL Server Management Studio, Business Intelligence Development Studio, Control Panel, and Add or Remove Programs.
    Dd638062.note(en-us,SQL.100).gifNote:
    You cannot stop services in a failover cluster environment. For more information, see the failover cluster installation section later in this topic.

    • To eliminate the requirement to restart your computer after update installation, Setup will show a list of processes that are locking files. If the update Setup program must end a service during installation, it will restart the service after the installation finishes.
    • If Setup determines that files are locked during installation, you might have to restart your computer after the installation finishes. If it is required, Setup prompts you to restart your computer.

     

    Install SQL Server 2008 Updates

    This section describes the installation process.

    Dd638062.note(en-us,SQL.100).gifImportant:
       SQL Server 2008 updates must be installed under an account that has administrative privileges on the computer where they will be installed.

    Starting a SQL Server 2008 Update

    To install a SQL Server 2008 update, run the self-extracting package file SQLServer2008-KBxxxxxx-PPP.exe, where PPP indicates the specific platform.

    Dd638062.note(en-us,SQL.100).gifNote:
    To apply updates to SQL Server 2008 components that are part of a failover cluster, see the section for failover cluster installation. For more information about how to run an update installation in unattended mode, see How to: Install SQL Server 2008 (Setup).

    Slipstream a SQL Server Update

    Overview:

    Slipstreaming is integrating a SQL Server 2008 update and the original installation media so that the original media and the update are installed at the same time. When you run the original release version of SQL Server 2008 Setup, the Setup program copies itself on the local computer, and then re-runs from the local copy. Therefore, if there is a later version of Setup on the computer, the Setup program runs the updated Setup.

    Slipstreaming is supported in the following scenarios:

    • Original media and service pack
    • Original media, service pack, and cumulative update
      Dd638062.note(en-us,SQL.100).gifNote:
      Slipstreaming an update with the original media but without the service pack is not supported.

      Dd638062.note(en-us,SQL.100).gifImportant:
      For SQL Server Express, you must download the version with the service pack and slipstream cumulative updates as needed.

    There are several ways that you can slipstream an update:

    Option 1: Install the latest update with the original release version of SQL Server 2008 Setup directly:

    We recommend that you use this option if you are running the upgrade on a few computers.

    1. Install the following prerequisites that are required for SQL Server 2008.
      • Microsoft Windows Installer 4.5
      • Microsoft .NET Framework 3.5 Service Pack 1
        Dd638062.note(en-us,SQL.100).gifNote:
        On the IA-64 platform, the .NET Framework 3.5 is not supported, and the .NET Framework 2.0 SP2 is required. You must install the .NET Framework 2.0 SP2 from the source media because it is not available from the Microsoft Download Center. The .NET Framework 2.0 SP2 is located in the following folder on the source media:

        Drive_Letter:\ia64\redist\2.0\NetFx20SP2_ia64.exe

    2. Download the service package and cumulative update that you want to slipstream. Select the language or architecture package that matches your environment. Service packages must match both language and architecture; cumulative updates are language-neutral.
    3. Double-click the service pack to install the SQL Server 2008 Setup support files. To confirm that the updated setup is installed, search for the "SQL Server 2008 Setup Support Files" entry by using the Add or Remove Programs item in Control Panel in operating systems that are earlier than Windows Vista. In Windows Vista or later versions of Windows, view the entry by using the Programs and Features item in Control Panel.
    4. For each package, extract the contents of the package by running the following script at the command prompt:
      <name of the PCU or CU package>.exe /x:<Root of path to extract to>\<PCU | CU>
      Dd638062.note(en-us,SQL.100).gifNote:

      The name of the package is in the form:

      PCU: SQLServer2008SP1-<KB Article>-<Architecture>-<Language>.exe

      CU: SQLServer2008SP1-<KB Article>-<Architecture>.exe

      The architecture placeholder represents the different hardware platforms. For example, it can represent one of the following folders:

      x86

      x64

      IA64

      For example, run the following commands to extract the contents of the PCU package:

      SQLServer2008- KB123456-IA64.exe /x:c:\MyUpdate\PCU

      SQLServer2008- KB123456-x64.exe /x:c:\MyUpdate\PCU

      SQLServer2008- KB123456-x86.exe /x:c:\MyUpdate\PCU

      If you want to include a CU based on the PCU, extract out the CU packages to c:\MyUpdate\CU

    5. Start the SQL Server 2008 Setup program and specify the path for the service pack and cumulative update files by using the /PCUSource and /CUSource parameters. For example, here is a path based on the extracted location indicated in step 4:
      Setup.exe /PCUSource = c:\MyUpdate\PCU /CUSource= c:\MyUpdate\CU
      Dd638062.note(en-us,SQL.100).gifNote:

      For SQL Server Express SP1 or later, only the /CUSource parameter is supported.

      If you are slipstreaming SQL Server in WOW64, you need to do one of the following:

      • To skip the installation center, specify the /Action parameter and the /x86 parameter on the command line.
      • Or, on the Options page of the Installation Center, select x86.
    Option 2: Slipstream Express Core Service Pack with cumulative update:

    We recommend that you use this option if you are running the upgrade on a few computers.

    1. Install the following prerequisites that are required for SQL Server 2008.
      • Microsoft Windows Installer 4.5
      • Microsoft .NET Framework 3.5 Service Pack 1
      Dd638062.note(en-us,SQL.100).gifNote:
      SQL Server Express only requires .NET 2.0 SP2, but this version is not publicly available so you need to install .NET 3.5 SP1 instead.

    2. Download the SQL Server Express core package and cumulative update that you want to slipstream. Select the language or architecture of SQL Server Express that matches your environment. The cumulative updates are language-neutral.
    3. Extract the contents of the cumulative update package by running the following script at the command prompt:
      <CU package>.exe /x:<Root of path to extract to>\<CU>
      Dd638062.note(en-us,SQL.100).gifNote:

      The name of the package is in the form:

      CU: SQLServer2008-<KB Article>-<Architecture>.exe

      The architecture placeholder represents the different hardware platforms. For example, it can represent one of the following folders:

      x86

      x64

      IA64

      For example, run the following commands to extract the contents of the cumulative update package:

      SQLServer2008-KB123456-IA64.exe /x:c:\MyUpdate\CU

      SQLServer2008-KB123456-x64.exe /x:c:\MyUpdate\CU

      SQLServer2008-KB123456-x86.exe /x:c:\MyUpdate\CU

    4. Start the SQL Server 2008 Setup program and specify the path for the service pack and cumulative update files by using the /CUSource parameters.
      Dd638062.note(en-us,SQL.100).gifNote:

      For SQL Server Express SP1 or later, only the /CUSource parameter is supported.

    • Microsoft Windows Installer 4.5
    • Microsoft .NET Framework 3.5 Service Pack 1
    Option 3: Update the original media files:

    We recommend that you use this option for running a patched setup on many computers or large deployments, or for when an administrator wants to make this patched setup available to users. We also recommend that you test fully before you make this option available to other users. This option is supported in the following scenarios:

    • Original media and service pack
    • Original media, service pack, and cumulative update
    1. Download the service pack and the optional cumulative update based on the service pack that you want to use to update the original media files. You must download the service pack and updates for all platforms (x86, x64, and IA-64) because the original media contains the files for each platform. For example, you must either download three packages for merging the original media and just the service pack or six packages for merging the original media, service pack, and cumulative update.
    2. For each package, extract the contents of the package by running the following script at the command prompt:
      <name of the PCU or CU package>.exe /x:<Root of path to extract to>\<PCU | CU>
      Dd638062.note(en-us,SQL.100).gifNote:

      The name of the package is in the form:

      PCU: SQLServer2008SP1-<KB Article>-<Architecture>-<Language>.exe

      CU: SQLServer2008SP1-<KB Article>-<Architecture>.exe

      The architecture placeholder represents the different hardware platforms. For example, it can represent one of the following folders:

      x86

      x64

      IA64

      For example, run the following commands to extract the contents of the PCU package:

      SQLServer2008- KB123456-IA64.exe /x:c:\MyUpdate\PCU

      SQLServer2008- KB123456-x64.exe /x:c:\MyUpdate\PCU

      SQLServer2008- KB123456-x86.exe /x:c:\MyUpdate\PCU

      The previous command merges the three architectures into a single folder. If you want to include a CU based on the PCU, extract the cumulative update packages out to c:\MyUpdate\CU

    3. Copy the contents of the SQL Server 2008 DVD to a local folder, for example SQLServer2008RTM.
    4. To update the files in the original installation media, copy the SQLSupport.msi file from the C:\MyUpdate\PCU\<Architecture>\setup\<Language LCID>\sqlsupport.msi to C:\SQLServer2008RTM\<Architecture>\Setup\sqlsupport.msi. Ensure that you copy Sqlsupport.msi for each architecture.
      Dd638062.note(en-us,SQL.100).gifNote:
      If you are using slipstreaming to integrate a cumulative update package also, use the files in the extracted cumulative update folder instead

    5. Copy the Setup.exe and Setup.rll files from the C:\MyUpdate\PCU\ folder to the root folder that contains the source media from the DVD.
      Dd638062.note(en-us,SQL.100).gifNote:
      If you are using slipstream to integrate a cumulative update package also, use the files in the extracted cumulative update folder instead.

    6. To update the files in the original installation media, copy all files without the folders, except the Microsoft.SQL.Chainer.PackageData.dll, in c:\MyUpdate\PCU\<architecture> to C:\SQLServer2008RTM\<architecture>
      Dd638062.note(en-us,SQL.100).gifNote:
      If you are using slipstream to integrate a cumulative update package also, use the files in the extracted cumulative update folder instead

    7. Start the Setup.exe program that is located at C:\SQLServer2008RTM and specify the values for /PCUSource and /CUSource parameters. For example, C:\SQLServer2008RTM\Setup.exe /PCUSource=c:\MyUpdate\PCU /CUSource= c:\MyUpdate\CU.
      Dd638062.note(en-us,SQL.100).gifNote:
      If you place the folder on a share for user installs, set the /PCUSource and /CUSource parameters to a UNC path.

    Applying a SQL Server 2008 Update to a Failover Cluster Instance

    For more information about how to install updates to a SQL Server 2008 failover cluster, see How to apply a SQL Server 2008 update to a failover cluster instance in the Microsoft Knowledge Base.

    Rebuilding a SQL Server 2008 Failover Cluster Node

    If you must rebuild a node in the failover cluster after updates were applied, follow these steps:

    1. Rebuild the node in the failover cluster. For more information about rebuilding a node, see "How to: Recover from Failover Cluster Failure in Scenario 1" in SQL Server Books Online.
    2. Run the original SQL Server 2008 Setup program to install SQL Server 2008 on the failover cluster node.
    3. Run SQL Server 2008 updates Setup on the node that you have added.

    Restart Services and Applications

    When the Setup program is finished, it might prompt you to restart the computer. After the system restarts, or after the Setup program finishes without requesting a restart, use the Services node in Control Panel to restart the services that you stopped before you applied the SQL Server 2008 updates. This includes services such as Distributed Transaction Coordinator and the Microsoft Search services, or instance-specific equivalents.

    Restart the applications that you closed before you ran SQL Server 2008 update Setup. You might also want to make another backup of the upgraded master, msdb, and model databases immediately after successful installation.

    Uninstalling updates to SQL Server 2008

    You can uninstall SQL Server 2008 cumulative updates or service packs from Programs and Features in Control Panel. Each cumulative update is listed separately. However, when a service pack is installed that is higher than the cumulative updates, the cumulative update entries are hidden and become available only if you uninstall the service pack.

    To uninstall any service packs and updates, you must start with the latest update or service pack applied to the instance of SQL Server and work backward. In each of the following examples, SQL Server ends up with Cumulative Update 1 after uninstall has been completed for the other service packs or updates:

    • For an instance of SQL Server 2008 with Cumulative Update 1 and SP1 installed, uninstall SP1.
    • For an instance of SQL Server 2008 with Cumulative Update 1, SP1, and Cumulative Update 2 installed, uninstall Cumulative Update 2 first and then uninstall SP1.
    Posted Dec 05 2009, 09:43 PM by wicky with no comments
    Filed under:
  • 任何IP均可申请微软学生KEY及下载系统镜像

    Posted Dec 02 2009, 04:40 PM by wicky with no comments
    Filed under:
  • Install Microsoft .NET Framework 1.1 on Windows 7

    http://www.mydigitallife.info/2007/12/27/install-microsoft-net-framework-11-on-windows-vista-fix-regsvcsexe-fails-error/

    将.net framework1.1安装到win7上还是有解决办法的,我把每一步的操作都列出来,请楼主照做:
    1,在C盘下创建一个新文件夹(如C:\DotNet);
    2,下载.net framework1.1安装包,一定要将此安装包的安装文件名命名为dotnetfx.exe;
    3,下载.net framework1.1 sp1(NDP1.1 SP1-KB867460-X86.exe),重命名此SP1的安装文件为dotnetfxsp1.exe;
    4,将这两个文件(dotnetfx.exe,dotnetfxsp1.exe)都拷入c:\DotNet文件夹下;
    5,打开DOS命令行(“开始”--“运行”--敲入“CMD”);
    6,用DOS命令进入C:\DotNet文件夹(cd c:\DotNet)
    7,依次运行下列命令:
       第一步 dotnetfx.exe /c:"msiexec.exe /a netfx.msi TARGETDIR=C:\DotNet"
       当弹出对话框提安装完成时点“确定”
       第二步 dotnetfxsp1.exe /Xp:C:\DotNet\netfxsp.msp
       第三步 msiexec.exe /a c:\DotNet\netfx.msi /p c:\DotNet\netfxsp.msp
       等待,完成后相关对话框会自动消失
    8,运行文件夹里的netfx.msi
    此时.net framework1.1已经成功安装到win7上。

     

    Posted Nov 22 2009, 02:01 PM by wicky with no comments
    Filed under:
  • Silverlight 4 Beta正式发布

    今天上午在洛杉矶举行的Professional Developer's Conference,微软正式发布了Silverlight 4 Beta。该版本属于开发人员使用版本,终端用户暂时不能下载Silverlight 4 Runtime。从下面的功能列表中可以看出,Silverlight技术越来越强大,相信不久的将来大多数企业级项目多会倾向使用Silverlight技术。

    官方发布网址: http://www.silverlight.net/getstarted/silverlight-4-beta/

    Silverlight 4 Beta版本新功能详解: http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx

    ------------------------------------------------------------------------------------------------------------------------

    2009年11月18日,微软在洛杉矶Professional Developer's Conference(PDC) 正式发布Silverlight 4 Beta版本。

    Silverlight 4 Beta新功能列表:

    增强企业级应用开发功能 -

    1.打印支持
    2.提供超过60中可自定义,可样式化的控件,其中提供了新控件RichTextBox;另外增强了Datagrid功能,允许对于列数据进行排序和改变区域尺寸,另外支持行复制和粘贴;
    3.发布WCF RIA Service,方便在n-tiers 应用中对于网络和数据库的存取;
    4.增强项目本地化功能,提供双向文本功能,支持30多种新语言切换;
    5.支持.Net CLR类库引用,对于Silverlight桌面项目不用再做另行编译;
    6.增强数据绑定功能,使数据分组,编辑以及字符格式化更加灵活,效率更高;
    7.VS2010全新的设计开发工具,包括全套编辑设计界面,拖拉数据绑定功能,自动绑定控件,数据源选择,全代码自动感应系统;


    增强多媒体影像功能 -

    1.网络摄像和麦克录音功能,允许共享视频和语音;
    2.在不用请求服务器交互的情况下,进行录音或者录像;
    3.允许拖拉或者复制粘贴外部数据到应用中;
    4.桌面应用,支持右键菜单;
    5.对于长列表控件,增加鼠标滚动效果;
    6.支持Google Chrome Browser;
    7.性能大幅度优化,Silverlight 4比Silverlight 3运行要快200%;
    8.Deep Zoom功能强化,增加硬件加速,另外,支持大型dataset,动画效果更加流畅;
    9.多点触控支持;
    10.组播网络支持,支持互动性网络会议,以及网络教学功能;
    11.H.264媒体内容保护;
    12.多媒体数据流输出保护;


    强化客户端功能 -

    1.允许读取客户本地文件,例如读取我的文档,我的音乐,我的图片,我的视频等本地目录;
    2.允许运行本地桌面应用,例如Office,发送报告到Word文档,发送Email等功能;
    3.COM操作;
    4.组策略功能;
    5.增强键盘支持和全屏支持;
    6.增强网络支持,允许在没有策略文件下支持跨域访问应用;


    需要了解更多Silverlight 4 Beta新功能,请访问:http://www.silverlight.net/getstarted/silverlight-4-beta/

    Posted Nov 19 2009, 08:23 AM by wicky with 2 comment(s)
    Filed under:
  • How to choose an Inheritance Strategy in Entity Framework?

    http://blogs.msdn.com/alexj/archive/2009/04/15/tip-12-choosing-an-inheritance-strategy.aspx

    The Entity Framework supports 3 primary inheritance strategies:

    Table Per Hierarchy (TPH):

    In TPH, all data for a type hierarchy is stored in one table, and there is a discriminator column that is used to establish the type of a particular row (i.e. 'C' for Car or 'B' for Boat).

    Columns for Properties that are not shared across all types need to be nullable, even if they aren't nullable properties. Which means the database is not completely enforcing your null-ability constraints.

    A TPH table might look something like this:

    ID Description Discriminator HorsePower KeelLength
    1 Porsche 911 C 600 NULL
    2 Yacht - KZ7 B NULL 2.2

    Table Per Type (TPT):

    In TPT properties in a base type are stored in a shared table. For example a Vehicle table:

    ID Description
    1 Porsche 911
    2 Yacht - KZ7

    And then there is a table for each sub type, with columns for just newly declared properties and the key, so the tables can be joined. So there would be a Car table:

    ID HorsePower
    1 600

    and Boat table:

    ID KeelLength
    2 2.2

    Table Per Concrete Class (TPC):

    In Table per Concrete Class there is a table for each class, and each of those tables has a column for every property of that type, i.e. a Car table:

    ID Description HorsePower
    1 Porsche 911 600

    And a Boat table:

    ID Description KeelLength
    2 Yacht - KZ7 2.2

    Which strategy is the Best?

    Trick question! In isolation of your requirements there is no 'Best' strategy.

    But...

    While the EF runtime supports TPC, the designer doesn't, and using TPC in the EF forces you to avoid associations in your base type. Because of these issues we generally discourage the use of TPC with the Entity Framework.

    This means in most situations the question comes down to TPH or TPT?

    Here are some of the things you might want to consider when making your decision:

    Concern Winner Reasoning
    Performance TPH Table Per Hierarchy is generally better performing, because no joins are necessary, everything is in one table.

    The decision becomes even more clear cut once the inheritance hierarchy gets wide or deep.
    Flexibility TPT Table Per Type is often used by ISVs, as it allows customizations without modifying the 'base' table.

    I.e. new subtypes can be added simply by creating new tables for those sub-types.
    Database Validation TPT TPH requires columns in derived types to be NULLABLE in the database, so that other derived types can be stored in the same table.

    Because of this it is possible to create rows in the table that are not valid according to the conceptual model. I.e. the column is NULLABLE but the combination of a particular column being NULL and a particular discriminator or type is not valid.

    This means the database is not enforcing the conceptual model for you anymore. This is fine if all access to the database is via the EF, but if anything else is used, you can end up with 'dirty' data.
    Aesthetics TPT This one is completely subjective, but TPT feels more Object Oriented to me :)
    Storage Space TPT Ward Bell pointed this one out:

    If your inheritance hierarchy has lots of types, then using TPH will result in lots of empty cells.

    If your database can handle 'sparse' columns well this probably isn't a real concern.

    As you can see once you know what it is you are looking for it should be a pretty easy task to choose a strategy. Most of the time the recommendation is TPH because generally performance trumps these other concerns.

    But every situation is different, and the key is to understand exactly what you value, and then make the decision accordingly.

    Let me know if you have any questions.

    Posted Nov 17 2009, 02:10 PM by wicky with no comments
    Filed under:
  • Configuring Kerberos Delegation

    http://dunnry.com/blog/ConfiguringKerberosDelegation.aspx

    One of the challenges to using something like System.DirectoryServices with web apps is managing the security context.  By default, your web application runs with the security context of a local account (often ASPNET or NETWORK SERVICE).  Those accounts are not domain accounts (unless you did something stupid like install IIS on a domain controller), so naturally any code that attempts to read or write to Active Directory is going to fail when the security context is unknown.

    First of all, there are many approaches to getting your code in web apps to work.  I am not going to go into all of them, it would take far too long of a post.  Whenever possible, I tell people to use a trusted subsystem model, where the application runs with the desired security context.  When that is not possible, or the application requires fine-grain ACL control (or auditing), you need to actually get the client's security context down through the layers, which means we have to use delegation.

    We can break down how to configure delegation based on the deployment of your IIS server.  I am talking about IIS6 here, but this would apply to some degree to IIS5 as well (sans App Pool).  I am also going to make the assumption that your IIS server is a member of a domain with appropriate trust relationships if necessary.  Kerberos delegation doesn't really work without this.

    Step 1:  Determine the current security context of your IIS application

    You should be able to rattle this off (it is that important to know), but if you are unsure, just open your IIS MMC (Start > Run > 'inetmgr'), find your application and check which application pool it is in (Properties > Virtual Directory > Application Pool).

    Next, you should find this application pool in the MMC and check the identity (Properties > Identity).  It might be set to a predefined local account (e.g. NETWORK SERVICE), or it might be set explicitly to some other account.

    This is your unmanaged security context.  Now, depending on the type of account this is, we will configure Kerberos delegation differently.  The next two steps 2 and 2a, work slightly differently depending on what your current security context has been determined to be.

    Step 2: Is your current security context a local account (i.e. non-domain account like NETWORK SERVICE)?

    If you are running IIS as a local account, you should understand that your application will still have an Active Directory identity on the network.  It will be that of the IIS machine account.  Keith Brown has a good write-up on this if you need more clarification why this happens.  Here are the steps to allow the current IIS server to delegate.

    1. IIS server must be a member of the domain and <identity impersonate="true"/> should be in web.config
    2. Set IIS server computer account in AD Users & Computers MMC as "Trusted for Delegation"
    3. IIS Server must be rebooted for this policy to take effect.
    4. Integrated Windows Authentication only must be selected for site / virtual directory
    5. IIS must not have NTLM only set as authentication method (this is usually not a problem, NEGOTIATE is default, so unless you specifically ran a script to change this, don't worry about it).
    6. IIS server name either must match exactly account name in AD, or SetSPN tool should be used in cases where IIS site is set as alternative name (e.g. server is called server01.domain.com, and website is called www.application.com).

    Step 2a: Is your current security context a domain account?

    1. IIS server must be a member of the domain and <identity impersonate="true"/> should be in web.config
    2. Set Domain's App Pool Identity account in AD Users & Computers MMC as "Trusted for Delegation"
    3. SetSPN must be used to add SPN to domain service account (e.g. "HTTP/www.myapplication.com").
    4. Integrated Windows Authentication only must be selected for site / virtual directory
    5. IIS must not have NTLM only set as authentication method (this is usually not a problem, NEGOTIATE is default, so unless you specifically ran a script to change this, don't worry about it).

    Step 3:  Make sure your clients are configured to use Kerberos

    The final step to getting this all to work is to make sure your clients are configured such that they will attempt Kerberos.  This requires a few items to check.

    1. Client must be using IE 5.x+. If client is running IE 6, ensure that "Enable Integrated Windows Authentication (requires restart)" is selected from Tools > Internet Options > Advanced.
    2. Web site MUST be recognized as Local Intranet (not Internet Zone) or Trusted site to client. Since Kerberos is not really considered an internet protocol, IE does not even try Kerberos if the current zone is determined to be Internet.  If necessary, specifically add this to Local Intranet sites list.
    3. Client account must not be marked as "Sensitive, Do not Delegate" in AD Users and Computers MMC.  Smart administrators often mark their admin accounts with this option to prevent them from being abused.  Delegation will fail if you (the client) are trying to delegate one of these types of credentials.

    Troubleshooting

    The service principal name (SPN) can be a tripping point for a lot of applications.  Load balancing IIS servers adds additional complication as well.  I would really recommend reading Keith's explanation of Kerberos and how it works.  This should make it clear what the SPN is and why it is necessary.

    Finally, Microsoft has a support article out there that is fairly decent.  Check it out if you have problems.

     

    Posted Nov 06 2009, 08:20 PM by wicky with no comments
    Filed under:
  • Sql Function Reference: Oracle vs. SQL Server

    Math Functions
    Function Oracle SQL Server
    Absolute value ABS ABS
    Arc cosine ACOS ACOS
    Arc sine ASIN ASIN
    Arc tangent of n ATAN ATAN
    Arc tangent of n and m ATAN2 ATN2
    Smallest integer >= value CEIL CEILING
    Cosine COS COS
    Hyperbolic cosine COSH COT
    Exponential value EXP EXP
    Round down to nearest integer FLOOR FLOOR
    Natural logarithm LN LOG
    Logarithm, any base LOG(N) N/A
    Logarithm, base 10 LOG(10) LOG10
    Modulus (remainder) MOD USE MODULO (%) OPERATOR
    Power POWER POWER
    Random number N/A RAND
    Round ROUND ROUND
    Sign of number SIGN SIGN
    Sine SIN SIN
    Hyperbolic sine SINH N/A
    Square root SQRT SQRT
    Tangent TAN TAN
    Hyperbolic tangent TANH N/A
    Truncate TRUNC N/A
    Highest number in list GREATEST N/A
    Lowest number in list LEAST N/A
    Convert number if NULL NVL ISNULL
    Standard deviation STDDEV STDEV
    Variance VARIANCE VAR
    String Functions
    Function Oracle SQL Server
    Convert character to ASCII ASCII ASCII
    String concatenate CONCAT (expression + expression)
    Convert ASCII to character CHR CHAR
    Return starting point of character in character string (from left) INSTR CHARINDEX
    Convert characters to lowercase LOWER LOWER
    Convert characters to uppercase UPPER UPPER
    Pad left side of character string LPAD N/A
    Remove leading blank spaces LTRIM LTRIM
    Remove trailing blank spaces RTRIM RTRIM
    Starting point of pattern in character string INSTR PATINDEX
    Repeat character string multiple times RPAD REPLICATE
    Phonetic representation of character string SOUNDEX SOUNDEX
    String of repeated spaces RPAD SPACE
    Character data converted from numeric data TO_CHAR STR
    Substring SUBSTR SUBSTRING
    Replace characters REPLACE STUFF
    Capitalize first letter of each word in string INITCAP N/A
    Translate character string TRANSLATE N/A
    Length of character string LENGTH DATALENGTH or LEN
    Greatest character string in list GREATEST N/A
    Least character string in list LEAST N/A
    Convert string if NULL NVL ISNULL
    Date Functions
    Function Oracle SQL Server
    Date addition (use +) DATEADD
    Date subtraction (use -) DATEDIFF
    Last day of month LAST_DAY N/A
    Time zone conversion NEW_TIME N/A
    First weekday after date NEXT_DAY N/A
    Convert date to string TO_CHAR DATENAME
    Convert date to number TO_NUMBER(TO_CHAR()) DATEPART
    Convert string to date TO_DATE CAST
    Get current date and time SYSDATE GETDATE()

    Posted Oct 30 2009, 05:06 PM by wicky with no comments
    Filed under:
  • 关于Oracle Table/Column名字的大小写问题

    Oracle有个极其愚蠢的“功能”,在创建表或者字段的时候,如果你想好看一些,加了引号使用了小写,那么以后访问的时候,都需要加上引号。比如create table "OrderDetails"....你用select * from OrderDetails或者select * from orderdetails等等都是不能访问的,需要用select * from "OrderDetails"。一旦这样用上,你的痛苦就会无休无止。

    下面两个语句可以帮助你很快把这个错误纠正过来。
    select 'alter table "'||tname||'" rename to ' || upper(tname) ||';' from tab where tabtype='TABLE' And tname<>upper(tname)
    select 'alter table "' || TNAME || '" rename column "' || CNAME || '" to "' || upper(CNAME) || '";' s from col Where CNAME<>upper(CNAME)

     

    Posted Oct 29 2009, 09:52 PM by wicky with 1 comment(s)
    Filed under:
  • How can I perform bitwise operations in Oracle

    http://www.jlcomp.demon.co.uk/faq/bitwise.html

    How can I perform bitwise operations in Oracle


    Author's name: Connor McDonald

    Author's Email: connor_mcdonald@yahoo.com

    Date written: June 20th, 2001

    Oracle version(s): 8.1.x

    Finally, Oracle have got around to adding their BITAND function to the documentation, but there is a little more to bitwise operations that is important to consider. (Updated July 15th, 2005)

    Back to index of questions


    Ever since Oracle 7 and probably even previous, Oracle has contained a BITAND function that returns the logical AND of two integers. Somewhere around 8i they finally decided to stick it in the documentation. You can safely rely on this function being retained in future versions of Oracle, because it is used extensively throughout the data dictionary. For example, a column is deemed to be "hidden" if bitand(property, 32) = 0 on the SYS.COL$ table.

    Note that BITAND returns a binary integer, so to use it in SQL you will need to convert it to a numeric.

    SQL> select bitand(49,54) from dual;
    ERROR:
    ORA-00932: inconsistent datatypes
    
    
    SQL> select bitand(49,54)+0 from dual;
    
    BITAND(49,54)+0
    ---------------
                 48
    

    Using this function, its trivial to build the other logical operations

    function bitor(p_dec1 number, p_dec2 number) return number is
    begin
      return p_dec1-bitand(p_dec1,p_dec2)+p_dec2;
    end;
    
    function bitxor(p_dec1 number, p_dec2 number) return number is
    begin
      return bitor(p_dec1,p_dec2)-bitand(p_dec1,p_dec2);
      -- or you could use: return p_dec1-2*bitand(p_dec1,p_dec2)+p_dec2;
    end;
    

    Note that BITAND only supports positive integers, so if you want to include support for negatives you will need to wrap some of your own code around the above to handle them.

    Because many people were unaware of the BITAND builtin, they often sought solace in the UTL_RAW package which looks promising when you describe it.

    SQL> desc UTL_RAW
    FUNCTION BIT_AND RETURNS RAW
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     R1                             RAW                     IN
     R2                             RAW                     IN
    
    FUNCTION BIT_COMPLEMENT RETURNS RAW
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     R                              RAW                     IN
    
    FUNCTION BIT_OR RETURNS RAW
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     R1                             RAW                     IN
     R2                             RAW                     IN
    
    FUNCTION BIT_XOR RETURNS RAW
     Argument Name                  Type                    In/Out Default?
     ------------------------------ ----------------------- ------ --------
     R1                             RAW                     IN
     R2                             RAW                     IN
    

    But you need to be careful here, as can be best shown with an example. First we'll use the standard BITAND to see what the real result should be:

    SQL> exec dbms_output.put_line(bitand(147,63));
    19
    
    PL/SQL procedure successfully completed.
    

    Now we'll try UTL_RAW to accomplish the same thing

    SQL> declare
      2    x  number := 147;
      3    y  number := 63;
      4  begin
      5    dbms_output.put_line(utl_raw.bit_and(x,y));
      6  end;
      7  /
    
    ERROR at line 1:
    ORA-06550: line 5, column 24:
    PLS-00306: wrong number or types of arguments in call to 'BIT_AND'
    ORA-06550: line 5, column 3:
    PL/SQL: Statement ignored
    

    This is because the UTL_RAW package (as the name suggests) only works with RAW data. "No problem" we think, we'll just do some datatype conversions...

    SQL> declare
      2    x  number := 147;
      3    y  number := 63;
      4    x_raw raw(4) := utl_raw.cast_to_raw(x);
      5    y_raw raw(4) := utl_raw.cast_to_raw(y);
      6  begin
      7    dbms_output.put_line(utl_raw.bit_and(x_raw,y_raw));
      8  end;
      9  /
    303037
    
    PL/SQL procedure successfully completed.
    

    So the PL/SQL worked, but the result is not what we were expecting. Then you may click onto the fact that since the result is raw, an additional conversion is needed:

    SQL> declare
      2    x  number := 147;
      3    y  number := 63;
      4    x_raw raw(4) := utl_raw.cast_to_raw(x);
      5    y_raw raw(4) := utl_raw.cast_to_raw(y);
      6  begin
      7    dbms_output.put_line(utl_raw.cast_to_varchar2(utl_raw.bit_and(x_raw,y_raw)));
      8  end;
      9  /
    007
    
    PL/SQL procedure successfully completed.
    

    Still no joy! The reason for this behaviour is that we not taking into account all of the datatype conversions that are taking place. What is really happening is:

    The number 147 is converted to varchar2 '147', which as a raw is "31,34,37" (that is, ascii 49, ascii 52, ascii 55). Similarly, 63 becomes raw "36,33" (ascii 54, ascii 51). It is these values that get passed to the BIT_AND function, which gives

    	49      52      55
    AND     54      51       -
    	==================
    	48      48      55
    

    which when converted back to varchar2 yields 007.

    It is possible to use UTL_RAW, but you just need to take care with all of the conversions. A package to do this is:

    create or replace
    package bitops2 is
    
    function bitand(p_dec1 number, p_dec2 number) return varchar2 ;
    function bitor(p_dec1 number, p_dec2 number) return varchar2 ;
    function bitxor(p_dec1 number, p_dec2 number) return varchar2 ;
    
    end;
    /
    create or replace
    package body bitops2 is
    
    function raw_ascii(p_dec number) return raw is
      v_result varchar2(1999);
      v_tmp1   number := p_dec;
    begin
      loop
        v_result := chr(mod(v_tmp1,256)) || v_result ;
        v_tmp1 := trunc(v_tmp1/256);
        exit when v_tmp1 = 0;
      end loop;
      return utl_raw.cast_to_raw(v_result);
    end;
    
    function ascii_raw(p_raw varchar2) return number is
      v_result number := 0;
    begin
      for i in 1 .. length(p_raw) loop
        v_result := v_result * 256 + ascii(substr(p_raw,i,1));
      end loop;
      return v_result;
    end;
    
    function bitand(p_dec1 number, p_dec2 number) return varchar2 is
    begin
      return
       ascii_raw(
         utl_raw.cast_to_varchar2(
           utl_raw.bit_and(
             raw_ascii(p_dec1),
             raw_ascii(p_dec2)
           )
         )
       );
    end;
    
    function bitor(p_dec1 number, p_dec2 number) return varchar2 is
    begin
      return
       ascii_raw(
         utl_raw.cast_to_varchar2(
           utl_raw.bit_or(
             raw_ascii(p_dec1),
             raw_ascii(p_dec2)
           )
         )
       );
    end;
    
    function bitxor(p_dec1 number, p_dec2 number) return varchar2 is
    begin
      return
       ascii_raw(
         utl_raw.cast_to_varchar2(
           utl_raw.bit_xor(
             raw_ascii(p_dec1),
             raw_ascii(p_dec2)
           )
         )
       );
    end;
    
    end;
    /
    

    If your bitwise requirements extend larger than the maximum size of the number datatype, or if you would rather deal with bit strings directly, the following package will assist:

    create or replace
    package bitops is
    
    function bitand(p_bit1 varchar2, p_bit2 varchar2) return varchar2 ;
    function bitor(p_bit1 varchar2, p_bit2 varchar2) return varchar2 ;
    function bitxor(p_bit1 varchar2, p_bit2 varchar2) return varchar2 ;
    
    end;
    /
    
    create or replace
    package body bitops is
    
    function bitand(p_bit1 varchar2, p_bit2 varchar2) return varchar2 is
      v_result varchar2(1999);
      v_tmp1   varchar2(1999) := p_bit1;
      v_tmp2   varchar2(1999) := p_bit2;
      v_len1   number         := length(p_bit1);
      v_len2   number         := length(p_bit2);
      v_len    number         := greatest(v_len1,v_len2);
    begin
      v_tmp1 := lpad(v_tmp1,v_len,'0');
      v_tmp2 := lpad(v_tmp2,v_len,'0');
      for i in 1 .. v_len loop
        v_result := v_result || least(substr(v_tmp1,i,1),substr(v_tmp2,i,1));
      end loop;
      return v_result;
    end;
    
    function bitor(p_bit1 varchar2, p_bit2 varchar2) return varchar2 is
      v_result varchar2(1999);
      v_tmp1   varchar2(1999) := p_bit1;
      v_tmp2   varchar2(1999) := p_bit2;
      v_len1   number         := length(p_bit1);
      v_len2   number         := length(p_bit2);
      v_len    number         := greatest(v_len1,v_len2);
    begin
      v_tmp1 := lpad(v_tmp1,v_len,'0');
      v_tmp2 := lpad(v_tmp2,v_len,'0');
      for i in 1 .. v_len loop
        v_result := v_result || greatest(substr(v_tmp1,i,1),substr(v_tmp2,i,1));
      end loop;
      return v_result;
    end;
    
    function bitxor(p_bit1 varchar2, p_bit2 varchar2) return varchar2 is
      v_result varchar2(1999);
      v_tmp1   varchar2(1999) := p_bit1;
      v_tmp2   varchar2(1999) := p_bit2;
      v_len1   number         := length(p_bit1);
      v_len2   number         := length(p_bit2);
      v_len    number         := greatest(v_len1,v_len2);
    begin
      v_tmp1 := lpad(v_tmp1,v_len,'0');
      v_tmp2 := lpad(v_tmp2,v_len,'0');
      for i in 1 .. v_len loop
        v_result := v_result || to_char(abs(to_number(substr(v_tmp1,i,1))-to_number(substr(v_tmp2,i,1))));
      end loop;
      return v_result;
    end;
    
    end;
    /
    
    SQL> declare
      2    x varchar2(20) := '10101010101010101010';
      3    y varchar2(20) := '11110000111100001111';
      4  begin
      5    dbms_output.put_line(bitops.bitand(x,y));
      6  end;
      7  /
    10100000101000001010
    
    PL/SQL procedure successfully completed.
    

    Addenda

    Bart Pots has extended the package to handle bit strings of differing length and provided numeric input and output. The code is below:

    create or replace
    package bitops2 is
    
    	function raw_ascii(p_dec number) return raw;
    	function ascii_raw(p_raw varchar2) return number;
    	
    	function bitand(p_dec1 number, p_dec2 number) return number;
    	function bitor(p_dec1 number, p_dec2 number) return number;
    	function bitxor(p_dec1 number, p_dec2 number) return number;
    	
    end;
    /
    create or replace
    package body bitops2 is
    
    	function raw_ascii(p_dec number) return raw is
    	
    		v_result varchar2(1999);
    		v_tmp1   number := p_dec;
    		
    	begin
    	
    		loop
    			
    			v_result := chr(mod(v_tmp1,256)) || v_result ;
    			v_tmp1 := trunc(v_tmp1/256);
    			
    			exit when v_tmp1 = 0;
    			
    		end loop;
    		
    		return utl_raw.cast_to_raw(v_result);
    	end;
    	
    	function ascii_raw(p_raw varchar2) return number is
    	
    		v_result number := 0;
    		
    	begin
    		
    		for i in 1 .. length(p_raw) loop
    		
    			v_result := v_result * 256 + ascii(substr(p_raw,i,1));
    		
    		end loop;
    		
    		return v_result;
    		
    	end;
    	function bitand(p_dec1 number, p_dec2 number) return number is
    	
    		v_tmp_raw1 raw(1999);
    		v_tmp_raw2 raw(1999);
    		
    		nr_diff_length number(4,0);
    		
    		nr_pos number(4,0);
    		
    		v_tmp_raw_zero raw(1999) := raw_ascii(0);
    	
    	begin
    		
    		v_tmp_raw1 := raw_ascii(p_dec1);
    		v_tmp_raw2 := raw_ascii(p_dec2);
    		
    		nr_diff_length := greatest( utl_raw.length(v_tmp_raw1),
    					   	  		 	utl_raw.length(v_tmp_raw2));
    
    		for nr_pos in utl_raw.length(v_tmp_raw1) + 1.. nr_diff_length loop
    		
    			v_tmp_raw1 := utl_raw.concat( v_tmp_raw_zero,v_tmp_raw1 );
    		
    		end loop;
    		
    		for nr_pos in utl_raw.length(v_tmp_raw2) + 1 .. nr_diff_length loop
    		
    			v_tmp_raw2 := utl_raw.concat( v_tmp_raw_zero,v_tmp_raw2 );
    		
    		end loop;
    
    		return ascii_raw( utl_raw.cast_to_varchar2( utl_raw.bit_and( v_tmp_raw1, v_tmp_raw2)));
    		
    	end;
    	
    	function bitor(p_dec1 number, p_dec2 number) return number is
    	
    		v_tmp_raw1 raw(1999);
    		v_tmp_raw2 raw(1999);
    		
    		nr_diff_length number(4,0);
    		
    		nr_pos number(4,0);
    		
    		v_tmp_raw_zero raw(1999) := raw_ascii(0);
    	
    	begin
    	
    		v_tmp_raw1 := raw_ascii(p_dec1);
    		v_tmp_raw2 := raw_ascii(p_dec2);
    		
    		nr_diff_length := greatest( utl_raw.length(v_tmp_raw1),
    					   	  		 	utl_raw.length(v_tmp_raw2));
    
    		for nr_pos in utl_raw.length(v_tmp_raw1) + 1.. nr_diff_length loop
    		
    			v_tmp_raw1 := utl_raw.concat( v_tmp_raw_zero,v_tmp_raw1 );
    		
    		end loop;
    		
    		for nr_pos in utl_raw.length(v_tmp_raw2) + 1 .. nr_diff_length loop
    		
    			v_tmp_raw2 := utl_raw.concat( v_tmp_raw_zero,v_tmp_raw2 );
    		
    		end loop;
    	
    		return ascii_raw( utl_raw.cast_to_varchar2( utl_raw.bit_or( v_tmp_raw1, v_tmp_raw2)));
    	
    	end;
    	
    	function bitxor(p_dec1 number, p_dec2 number) return number is
    	
    		v_tmp_raw1 raw(1999);
    		v_tmp_raw2 raw(1999);
    		
    		nr_diff_length number(4,0);
    		
    		nr_pos number(4,0);
    		
    		v_tmp_raw_zero raw(1999) := raw_ascii(0);
    	
    	begin
    	
    		v_tmp_raw1 := raw_ascii(p_dec1);
    		v_tmp_raw2 := raw_ascii(p_dec2);
    		
    		nr_diff_length := greatest( utl_raw.length(v_tmp_raw1),
    					   	  		 	utl_raw.length(v_tmp_raw2));
    
    		for nr_pos in utl_raw.length(v_tmp_raw1) + 1.. nr_diff_length loop
    		
    			v_tmp_raw1 := utl_raw.concat( v_tmp_raw_zero,v_tmp_raw1 );
    		
    		end loop;
    		
    		for nr_pos in utl_raw.length(v_tmp_raw2) + 1 .. nr_diff_length loop
    		
    			v_tmp_raw2 := utl_raw.concat( v_tmp_raw_zero,v_tmp_raw2 );
    		
    		end loop;
    	
    		return ascii_raw( utl_raw.cast_to_varchar2( utl_raw.bit_xor( v_tmp_raw1, v_tmp_raw2)));
    		
    	end;
    end;
    

    Further reading: Technet documentation on BITAND (may require OTN registration)

     

    Posted Oct 29 2009, 05:04 PM by wicky with no comments
    Filed under:
  • TNS-12542 Error When Executing Batch Jobs or in High Transaction Environment


    http://blog.csdn.net/jerry_of/archive/2007/06/05/1638686.aspx

    TNS-12542 Error When Executing Batch Jobs or in High Transaction Environment

    The information in this document applies to:
    Oracle Net Services - Version: 8.1.7.4 to 10.1.0.0
    Microsoft Windows 2000
    Microsoft Windows XP (64-bit Itanium)
    Microsoft Windows (32-bit)

    Errors
    TNS-00512 "Address already in use"
    TNS-12542 TNS:address already in use
    TNS-12560 "TNS:protocol adapter error"

    Symptoms
    TNS-12542 errors in log files when executing batch jobs or in high transaction environments. Client trace files will show

    CLIENT TRACE FILE:
    ================

    (3752) [10-JUN-2004 15:20:50:899] niotns: Calling address:
    (DESCRIPTION=(SOURCE_ROUTE=OFF)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=tst81)(PORT=1526)))(CONNECT_DATA=(SID=sec)(SRVR=DEDICATED)(CID=(PROGRAM=c:windowssystem32inetsrvw3wp.exe)(HOST=SRVPDFTEST)(USER=userarchive))))
    (3752) [10-JUN-2004 15:20:50:899] nscall: connecting...
    (3752) [10-JUN-2004 15:20:50:899] nttgetport: port resolved to 1526
    (3752) [10-JUN-2004 15:20:50:899] nttbnd2addr: looking up IP addr for host:tst81
    (3752) [10-JUN-2004 15:20:50:899] nsopen: opening transport...
    (3752) [10-JUN-2004 15:20:50:899] nttcnp: Validnode Table IN use; err 0x0
    (3752) [10-JUN-2004 15:20:50:899] nttcni: trying to connect to socket 6628.
    (3752) [10-JUN-2004 15:20:50:899] ntt2err: soc 6628 error - operation=1, ntresnt[0]=512, ntresnt[1]=48, ntresnt[2]=0
    (3752) [10-JUN-2004 15:20:50:899] nserror: nsres: id=0, op=65, ns=12542,ns2=12560; nt[0]=512, nt[1]=48, nt[2]=0; ora[0]=0, ora[1]=0, ora[2]=0
    (3752) [10-JUN-2004 15:20:50:899] nsopen: unable to open transport
    (3752) [10-JUN-2004 15:20:50:899] nioqper: error from nscall
    (3752) [10-JUN-2004 15:20:50:899] nioqper: nr err code: 0
    (3752) [10-JUN-2004 15:20:50:899] nioqper: ns main err code: 12542
    (3752) [10-JUN-2004 15:20:50:899] nioqper: ns (2) err code: 12560
    (3752) [10-JUN-2004 15:20:50:899] nioqper: nt main err code: 512
    (3752) [10-JUN-2004 15:20:50:899] nioqper: nt (2) err code: 48
    (3752) [10-JUN-2004 15:20:50:899] nioqper: nt OS err code: 0
    (3752) [10-JUN-2004 15:20:50:899] niqme: reporting NS-12542 error as ORA-12542
    (3752) [10-JUN-2004 15:20:50:899] niomapnserror: returning error 12542
    (3752) [10-JUN-2004 15:20:50:899] niotns: Couldn't connect, returning 12542
    (432) [10-JUN-2004 15:20:50:899] nstimarmed: no timer allocated


    SQLNET.LOG file:
    =============
    Fatal NI connect error 12542, connecting to:

    (DESCRIPTION=(SOURCE_ROUTE=OFF)(ADDRESS=(PROTOCOL=TCP)(HOST=tst81)(PORT=1526))(CONNECT_DATA=(SID=sec)(SRVR=DEDICATED)(CID=(PROGRAM=c:windowssystem32inetsrvw
    3wp.exe)(HOST=SRVPDFTEST)(USER=userarchive))))

    VERSION INFORMATION:
    TNS for 32-bit Windows: Version 9.2.0.1.0 - Production
    Windows NT TCP/IP NT Protocol Adapter for 32-bit Windows: Version 9.2.0.1.0 - Production
    Time: 10-JUN-2004 15:20:50
    Tracing to file: E:oracleora92tempcli_1732.trc
    Tns error struct:
    nr err code: 0
    ns main err code: 12542
    TNS-12542: TNS:address already in use
    ns secondary err code: 12560
    nt main err code: 512
    TNS-00512: Address already in use
    nt secondary err code: 48
    nt OS err code: 0

    Cause
    Problem is caused due to the fact that the free ports in the windows client has been exhausted and it is trying to make use of a port which is in TIME_WAIT state which gives the error TNS-12542: Address already in use.

    Fix
    There are 2 solutions available:

    1.) Increase the free port range:
    ======================
    Start Registry Editor (Regedt32.exe).

    Locate the following key in the registry:

    HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters

    On the Edit menu, click Add Value, and then add the following registry value:

    Value Name: MaxUserPort Data Type: REG_DWORD Value: 65534

    Valid Range: 5000-65534 (decimal) Default: 0x1388 (5000 decimal)

    Description: This parameter controls the maximum port number used when an application requests any
    available user port from the system. Normally, ephemeral (that is, short-lived) ports are allocated between the values of 1024 and 5000 inclusive.


    2.) Decrease the value for TIME_WAIT state:
    ================================

    TcpTimedWaitDelay (new in Windows NT versions 3.51 SP5 and later)
    Key: TcpipParameters
    Value Type: REG_DWORD - Time in seconds
    Valid Range: 30-300 (decimal)
    Default: 0xF0 (240 decimal)

    Description: This parameter determines the length of time that a connection will stay in the TIME_WAIT state when being closed. While a connection is in the TIME_WAIT state, the socket pair
    cannot be re- used. This is also known as the "2MSL" state, as by RFC the value should be twice
    the maximum segment lifetime on the network. See RFC793 for further details.

    Posted Oct 28 2009, 01:19 PM by wicky with no comments
    Filed under:
  • VS2010 and .Net 4.0 Beta2 发布

    Posted Oct 21 2009, 04:50 PM by wicky with 2 comment(s)
    Filed under:
  • 我是如何带领团队开发工作流项目的

    http://www.cnblogs.com/foundation/archive/2009/10/17/1584875.html

    最近有不少朋友写信问我一些关于团队开发的问题,由于这段时间有些忙,没有回复.今天写一篇这方面的文章向大家介绍一下我是如何带领团队开发工作流项目的

    关于团队建设,项目管理的文章网上已经有很多了,在这里我就不谈这些理论了,直接给大家展示一个我在 项目开发方,后台服务开发方式,前台UI开发方式,后台服务与前台UI对接方式,代码文档,页面的开发文档,源码管理,单元测试,以及单元测试文档,实现思路设计文档,数据库文档,数据库设计规范,编码规范,操做数据的方法命名规则 方面的一些片断,这是一个为期6个月的工作流平台开发项目,是今年3月份启动的,现在已完成,比计划时间多出25天.核心开发人员(不包括美工,需求,黑盒测试)共有12人(编号从114到125)

    补充一点:在UI草图设计上,这次想用绘图板,但最后还是使用铅笔绘制+扫描的方式制做的.

     

    目录

    项目开发方式说明图    1

    后台服务开发方式说明图    1

    前台UI开发方式说明图    2

    后台服务与前台UI对接方式说明图    3

    代码文档(片断节选)    4

    页面的开发文档(片断节选)    5

    源码管理    6

    单元测试,以及单元测试文档(片断节选)    7

    实现思路设计文档(片断节选)    9

    数据库文档    11

    数据库设计规范(片断节选)    13

    编码规范(片断节选)    13

    操做数据的方法命名规则    13

     

    Posted Oct 17 2009, 03:15 PM by wicky with no comments
    Filed under:
  • 公司绝不会告诉你的20大秘密 值得一看很受用


    1.入职时的工资高低不重要,只要你努力工作你会得到相应待遇的......NO!

      我估计几乎找过工作的人都听过这句话,当我们确定被聘用跟公司谈工资时,他们都会说“如果以后你业绩突出、努力工作,你的报酬也会相应增加的”,特别是当第一次找工作的时候大多数人会相信这些话,但是千万~~别相信。
      刚入职时,你的工资就是你的全部(当然有一些岗位,比如销售或弹性工资的岗位除外),而且你入职以后大部分待遇都会跟着你的工资而浮动,工资调整也是按你目前的工资乘于一定的百分比,保险、公积金也跟工资有关系,当你的基本工资低的时候你今后的报酬增长空间也不大。
      所以,找工作时千万不要心软,多争取一些基本工资,因为这是你的所有。
      我第一次找工作时就是犯了这个错误,当时心软没要求更高的工资,当时觉得基本工资比别人低几百块钱无所谓,但是后来才发现它有一个杠杆作用,尽管以后每年你工资涨幅比别人大,但是工资还是比别人低。
      比如你入职时的基本工资为4000,第二年涨幅为20% (一般的企业极少数人能涨20%),那第二年工资为4800; 如果你的同事入职时基本工资为4500,第二年涨幅为10%(一般涨幅),那他第二年工资为4950。
      是不是看到差距了? 请记住,入职时工资就是你的全部,一定不能心软。

    2.人事部不是你的倾谈对象

      我在公司看过很多员工找人事部经理谈话,而且人事部员工可能会定期找员工谈话,问员工在工作中有没有遇到什么问题? 有没有人事部需要帮员工解决的事情?
      但是请你记住, 公司人事部并不是你的倾谈对象,人事部的首要任务不是去帮助雇员,而是保护公司利益不受雇员损害,这才是最为重要的。 可能很多人认为人事部门是自己的朋友,有时甚至连对公司、对老板的真实态度都会告知于人事部门。(如果你经常这样的话,我可以肯定的说,你会跌得很惨,而且不会有人告知你原因的)
      无论人事部的人员表现得何等友好,你均要认清,你跟他们的谈话内容,他们必然会与决策部门分享这些信息,例如你的老板、经理、主管及首席执行官。人事部门的职责就是(有时也是合法的)告知公司决策部门你那些所谓的“ 秘密”。
      比如你不喜欢你目前的工作内容、或与老板的关系处理的不好,你千万不能找人事部抱怨,你应该直接跟你的老板沟通。可能当时谈话时人事部的员工会给予同情,说自己向自己的上司反映这个情况,但是大多数情况下人事部门会将你与他们的对话原封不动地转达给你的老板,而你的老板对此是绝对无法原谅的,出现问题首先不去找老板解决,而是直接找到人事部门,这样你的处境就很被动了,有可能被迫离开公司了。

    3.你的能力并不能确保你的安全

      很多公司在招聘员工或对外宣传时说我们公司注重员工的能力,提倡员工能发挥自己的主观能动性 (确实有一些公司是提倡创新的,但是极少数,大部分都只是打打口号而已)。对于刚入职的员工来说可能都会有一种心理,那就是向同事或领导展示你的才华、展示你的能力,但是请注意: 公司或你的领导倒希望先看到你的忠诚,而不是显摆自己的能力。不管你的目的是什么,这个并不重要,如果你一贯展示你的能力,很有可能上司觉得你卖弄小聪明、是一个不值得信赖的人,或他会感受到威胁,如果他认为你在威胁他的位置,他才不管你有多聪明,他宁愿要一个愚笨但对自己忠诚的人。
      所以,当你刚入职或刚调到一个新部门的时候,千万不能先自作聪明,你首先要做的是熟悉环境熟悉上司同事的性格,即使你是一个专家也要先摆低姿态,当然必要的是关键时刻也需要显示自己的能力,让别人觉得你是深藏不露。
      韩国有一个俗语说“要想让婚姻生活幸福,就要当3年聋子,3年哑巴,3年盲人” ,因为以前在韩国婆婆对媳妇很是虐待,你必须是装聋作哑才能熬过去(当然现在已经不是这种情况了),我说这个的目的是新来乍到,你应该学会作哑装聋,刚开始多听、多学,听到闲言碎语要装聋。

    4.报销单是公司测试你的一个工具

      看到这个题目或许你会纳闷?报销单也能测试员工?是的,我们平时不以为常的报销单也是公司或领导测试你的一个工具。
      大部分公司都会有月底报销(餐费、交通费、电话费等)或出差报销吧?
      你让你的领导在你的报销单上签字的时候,他有没有说过什么?或他有没有做过什么表情? 请注意,其实大部分情况下领导们都会看你报销的金额,而且如果他们愿意的话财务部门可以随时提供每个人的报销明细。
      以前看过一些在公司里面贪小便宜的人,餐费、交通费里总是放着一些自己私人用的(而不是为了公司业务)费用,或许这些费用只有100元,但正是这些小钱会坏了你的前程。
      我认识的一个老板跟我说过这样一句话:“某某员工哪天报了业务餐费,但是那天明明是我付款了。”或许这位员工太大意了。
      但是我认识的老板当中也有一些人,他连你打的票上面的时间也核对,然后把属下每个员工的每月费用都记录下来,或许你报销的时候他可能不会说什么,但是到时候你丢掉的并不仅仅是金钱。

    5.在工作场合中透露私事很危险

      现在我们大部分人有太多时间跟同事一起过,我们跟同事在一起的时间有时甚至超过跟家人在一起的时间,这种情况使我们有时分不清公事和私事,有时候觉得跟同事的关系像亲人一样,跟同事分享自己的私事,孩子养育问题,个人健康问题,经济上遇到的一些困难等,但是请记住,职场就是职场,你这样做很危险。
      我的一位同事经常在工作场合说他儿子现在是青春期,跟我们描述怎么怎么叛逆,由于儿子的叛逆,每天回家以后家里的氛围都很紧张,有可能他是想通过倾述减少来自家庭的压力,但是最近公司开始了一个重大的项目,他一直以为自己是最佳候选人负责这个项目,但是结果令人意外,公司领导层选了其他人选,为什么呢?因为公司领导层觉得“他家里的事情已经够多了,估计他没有余力做这么重要的项目”或讲得更冷静一点就是“你连自己家里的事情都解决不了,你还能负责这么重要的项目吗?”
      如果你自己身体不太好,不需要把自己的健康情况告诉同事或上司,因为对上司来说你不健康说明你不能百分之百投入或有可能影响工作,这样你的上司会不安,他甚至会提前想对策或再额外招人,这样的话到时候即使你的身体恢复了,你有可能会面临失去自己位置的尴尬局面。

    6.如果你与老板作对,必然会被逐出公司大门 

      在公司里有一个对你产生很大影响的人,如果没有他的支持你不能得到公司的认可,晋升也很难甚至有可能丢掉你的工作,他就是你的顶头上司。
      或许你的上司没有你聪明、没有你能干,你或许对他并不服气,但是请记住,他就像是一个守门人一样,你想绕开守门人,但最终的结果是你也失去了给你敞开的一扇机会门。或许你觉得如果你自己足够有能力,公司领导层会让你绕开你的上司直接让你晋升或给你另外的机会,但是不要做白日梦了,公司往往会站在你上司的角度想一个组织的稳定性,跟自己的上司斗99%受伤的都是你自己。
      或许你的上司能力没有你强,但是既然他能上升到那个位置就说明他必然有一些其他方面的能力,领导力或组织管理能力或对公司的忠诚,当上司和你产生冲突时公司会站在你上司这一边,请你记住这一点。
      我的一个同事很有能力,当他调到一个新部门的时候发现上司根本没有能力而且往往做不了决定,所以很多情况下他绕开自己的上司直接跟总经理沟通,而且在业务上总经理也认可了他,这让他很得意以为自己能力强上司不能拿他怎么样,但是有一次,上司说他工作太辛苦了,让他去马尔代夫休假(公司出钱),当他从马尔代夫回来以后发现,他不在的时候公司发了一个人事调令,把他调到一个无关紧要的部门。
      所以,不管碰到什么样的上司,如果你还想呆在这个部门,呆在这个公司,你需要配合你的上司,这样他会帮你打开一扇机会的门。

    7.按了发送键? STOP~~ 公司邮件很危险

      如果我说你用公司邮箱收发的邮件都被你的上司所看到,你是不是觉得天要塌下来了? 如果不是的话,那就说明你很光明正大。其实很多人都不知道公司或上司能看到你的邮件,而且公司也绝不会给员工发个警告,说要注意互相往来的E-mail,如果你用公司邮箱给朋友发私人邮件,或跟同事用邮件谈论上司或公司的政策,一定要睁大眼睛看一下:公司邮箱很危险。
      
      (1)你利用公司邮箱收发邮件时,你一定要想着有可能公司某人正在看这封邮件,因为真的有些公司会定期检查一下邮件内容(当然是不告知于员工的情况下),我不知道之前我任职的公司是不是也这样,但是我听过一些国际知名公司会定期查员工的邮件。
      (2) 邮件会永远留在公司服务器: 你或许不知道,就算有些邮件发完了你后悔了马上删除了,可能在你的邮箱里面是已经没有了,公司服务器永远记录这封邮件的。
      (3)按发送键的时候一定要三思:你或许通过邮件给人事部或你的上司提一些建议或者对公司制度做一些评论,一定要注意,这些邮件在一些重要时刻会成为呈堂证供,很多情况下往往对你不利。
      
      在公司里面我经常收到一些群发的搞笑邮件,如果以前你给同事群发过这些邮件,我建议你以后不要再发了。因为你经常发这些会让别人觉得你整天没事做,所以才发这种邮件。或许收到这些邮件的他(或她)把这个邮件转发给一些领导了,或许他也是为了让领导搞笑、高兴,但是领导们可不会这么想,你在领导的眼里会变成整天无所事事的人的。

    8.我努力工作公司会给我加薪?No,你必须要求!

      对于工资,公司和员工之间永远都不能达到双赢,很多人对自己目前的工资并不满意。那么怎么办呢? 等着公司给你加薪?很多人认为如果我做好自己的事情,我出业绩了,公司肯定会给我加薪,是的,公司会给你加薪,但是~~ 加薪的幅度肯定不能满足你的期望。
      我在公司里看过很多案例,很多人都幻想“到时候”公司会给我加薪,或害怕自己提要求以后老板有什么想法所以不敢提出来,但是如果你不敢提出加薪,公司给你的可能就是一个平均值或略高于平均值的薪水,它不是你所期待的。
      
      当然你想要求加薪,首先你要弄清楚你的“价值”,而且必须是站在公司的角度想,如果公司认为你没有“加薪的价值”还提出要求,那你很有可能会被裁掉的。
      (1)证明你的“价值”:如果你在公司整天无所事事,那公司肯定不会给你加薪的,在要求之前你必须要证明你的“价值”,让你成为公司不可缺少的人才。
      (2)提要求: 像前面所说的一样,公司每天都想着怎么削减成本,如果你不要求公司觉得这是一件好事情,除非你要求了,公司绝不会自愿给你涨很多工资的。不要想着哪天会出现奇迹,如果你觉得你有价值,就要求吧,如果上司认可你,他会倾听你的话语的,并且千万不能让你老板成为你的敌人, 交流的最后一定要强调我还是尊重你的决定,因为有些时候由于客观的原因老板也有身不由己的时候。
      (3)不要威胁上司:如果你还想待在公司,在要求加薪时,千万不要威胁上司,比如不加薪就离开公司或跟上司说谎说已经拿了别的公司的OFFER等,你的立场必须是“我很喜欢这个公司还有目前的业务,但是我觉得目前的工资跟我实际做的工作有差距,我希望工资能体现我的价值”等,你威胁的结果很有可能是得打包走人。
      (4)不要抱怨:即使最后的结果不是很好,比如不给你加薪或加了很少一部分,通过主动出击你可能明白了自己的短处或老板对你的看法,也让老板明白了你不满足于现状。如果你没有打算离开这个公司,你就要现在开始弥补自己的短处或提高自己的业绩,下次再用更强烈的事实来证明,可能这次没有成功,但是你离下次成功就不远了 。
      我知道跟老板提加薪要求很难,因为你害怕“如果我要求提工资,老板会炒我或以后他对我不给好脸色怎么办呢?”,但是大多数情况下那些你想像的最坏的情况并没有发生,大多数是happy ending。而且即使有一些副作用,公司或老板很健忘的,因为如果这个公司的OWNER不是你上司的话,钱不是从他口袋里出来,过一两个月他就会忘掉这件事情的。
      这个我可以很肯定的告诉你,因为我曾试过。

    9. 加薪必须要求,那晋升呢? NO,千万要管好自己的嘴巴~~

      既然说加薪必须要求,那晋升呢?这个千万不能要求,一旦你申请或要求晋升机会,它就会与你失之交臂,晋升不是要求的,而是上司通过认真考虑之后给予你的。
      上司还没有确信你能不能成为管理人员之前你先要求,这就像是你不从大门进,而是要跳过墙进到内部。因为如果上司还没有确信你是一个当领导的料,但你先提出来,他会觉得你还没有成熟或认为你比起公司的利益更在意自己的私利。
      领导们在决定晋升人选时除了业绩、工作能力之外,还会考察很多其他能力,比如领导能力,组织能力,对公司的忠诚度等,而且作为管理人员应该要沉得住气、该谦虚的时候需要谦虚,你事先提出来会破坏你的形象的。
      难道要坐等吗?当然不是,你可以主动负责一些重要的项目、要提出帮助其他部门面临的棘手的项目等,一定要抓住机会让上司看到你的能力,看到你的热情。
      
    10.如果遇到新上司要积极配合他 

      现在的公司经常会发生人事变动,一般来说遇到新上司属下的员工都会有一点被别人侵入的感觉,特别是当你和前任上司关系非常好的时候这种感觉更强烈。但是如果你想在公司继续混下去,你要尽快配合新上司,熟悉他的工作作风。
      很多时候新上司赴任以后下属员工都期望新来的上司适应部门原来的工作方式,但是这种事情不会发生的,大部分新上司都会对目前的工作方式进行变更,这种时候千万不要带头抵触或提意见,所谓新官上任三把火,这时候你要做的是积极配合他,如果别的员工有不满情绪,你应该要中间周旋一下,这样新上司会觉得你是站在他这一边的,这个第一印象特别重要。同时,新上司刚来时,你觉得新上司还不懂部门的情况,所以就出面给他一些忠告或建议,就算你是为了新上司好,千万不要提忠告或建议,这是一个禁忌。如果他主动问你,你可以说,但是~~这种时候也尽量说事实,不要涉及到你个人的意见或负面的信息,你要让你的上司根据这些事实自己做出决定。况且新上司问你的意见或建议,是想测试你们的忠诚,想知道你们对公司或同事的真实想法,这很有可能是一个圈套。
      在这里你要记住一点的是,新上司来了熟悉业务的时候对你来说是一个很好的表现自己的机会,记住,少说,默默配合新上司的工作,他会把这些都会记在心里的。

    11. 想成为公司中最有价值的员工?那你就必须停止说“我做不了”而主动请缨

    是不是人人都想成为公司的MVP? 那你必须要停止说"我做不了"而主动请缨,每次上司给你分配任务的时候你是不是说 “我没做过这个,我做不了这个”或“我现在没时间这个”。
      就算是你觉得这个任务对你来说有点难,你觉得你有可能完成不了, 这种时候很多人可能条件反射地说”这个我做不来”, 千万不要这样说. 其实领导给你分配这个任务, 他肯定是考虑过你的能力,而且可能这件事情即使没做好他也有后路的. (一般领导不会给你安排很重要而且如果搞砸了没有后路的事情) 这种时候即使你完成的不够好可能也不会损失什么, 这种时候你的态度应该是" 这个我做起来有些难, 但是我会试试的” . 然后就得通宵加班或使上你全身力气把问题给解决. 如果你做的过程中发现按你现在的能力完成不了, 你一定要在deadline之前提交给领导(不要在最后一天提交完成度不高的答案, 领导最讨厌这种人),让他有更多时间来修改。
      
      如果你习惯性的说"我做不了",过一段时间以后他会觉得"给你任务你肯定说做不了",所以干脆不给你指派任务.
      
      如果你们部门里有所有人都不想做的项目或任务,如果你主动请缨接收这个"烫山芋",那领导会对你刮目相看,给予你很好的评价的,当然这种烫山芋不需要太多,只要一个就可以.
      
    12. 想要脱颖而出?让领导感到150%满足感

      在职场成功的一个秘诀, 不要只干领导让你做的事情,。如果你只是按照领导说的话100% 执行, 那你永远也无法脱颖而出。在公司做领导给你分配的任务的时候,一定要多长一个心眼, 除了他布置的任务以外, 你可以提出你的建议或者是一些改善意见, 而且完成度不能是100%, 而是要达到150%.
      
      “做女人要像希拉里一样”中希拉里用的战略中一个很重要的战略就是: ” 让雇佣我的人或者是接受我提供的服务的人感到200%的满足感”, 这样看希拉里的目标更高.
      
      很多人都觉得你只要做好领导分配的任务让你的领导满足100%, 做好自己分内的事情就可以了,但是如果这样做, 你在职场永远不能混好.

    13. 你们公司允许言论自由吗?职场没有言论自由

      或许当你第一天上班的时候人事部的人会对你我们公司很OPEN,而且在很多时候开会的时候总经理会说“大家畅所欲言吧,我会尽力满足你们的要求、尽量解决你们所提的意见”,千万不要陷进这个陷阱。大多数时候公司是没有言论自由的,特别是当你对公司的政策,环境或制度说出了真实的想法,在公开场合上反对公司的政策制度,公司会视你为影响公司氛围的反动派,他们觉得你很危险所以通过一些方法让你打包走人的。
      我不知道有些真的开放的公司是不是有言论自由,但是我看到的版本是每当总经理跟员工面谈时都会让他们畅所欲言,但是等他们真正说出了真实想法,马上他就失去了公司的信任。
      还有一点,我经常看到一些人在电梯里跟同事或朋友说公司里面的事情,这个是一个很不专业的行为,因为不管你是在你办公室的电梯还是在客户公司电梯,跟你一起乘坐电梯的人有可能是你上司的朋友,重要的客户,你称赞公司可以,但是反对或不满的话语千万不要在电梯里面说,不然到时候你都不知道自己为什么死得这么快了。

    14. 你的办公桌专业化吗?

      现在大部分外企的办公桌都是一格一格的小格子,或许你认为办公桌是我私人的地方,我想放什么就放什么,但是请注意,办公桌也是体现你价值的地方,所以要让你的办公桌也变得专业化。
      那怎么样的办公桌才是专业化的呢?

    (1)不能太乱,我在公司里看到很多人的办公桌都是乱七八糟的,各种各样的文件摆在那里,太乱的话很容易给别人这个人工作没有条理的印象。

    (2)不能太整洁,如果你办公桌上什么都没有太整洁了,那别人会觉得你根本没事做。

    (3)不能有太多装饰品。现在80后追求个性,办公桌上面放着各种各样的东西,曾经我的同事中有一个人的办公桌可以看作是一个礼品店,各种各样的娃娃还有各种小东西,可能自己觉得这样很有创意,但是别人都在背后说她。

    (4)跟业务无关或跟你的调不符的书籍千万不要放在让人看到的地方。
      
      总的来说,我觉得白天你可以把你的文件或资料放在桌上,但是下班的时候一定要整理,那些重要的资料一定要放在抽屉里(最好是锁着),这样可以显示出你做事很专业。而且现实生活中有些上司习惯下班以后转一圈看看下属的办公桌,一是看看你的桌上有没有公司重要的资料敞开着,二是通过你办公桌上的东西看看你最近的动向(如果你桌上有“8个方法教你找好工作”之类的书,那你应该是有跳槽的打算了吧?^^)
      
    15.业绩考核结果跟你的业绩不相符?业绩也需要进行宣传

      大部分公司每年都会进行1到2次(或4次)的业绩考核,业绩考核结果会影响到你的奖金/晋升等,但是很多员工发现业绩考核结果跟自己想象的完全不一样,这是为什么呢?因为业绩考核中你主观性的判断根本不重要,重要的是你的上司怎么判断你的业绩。如果你做的工作是拿数据说话的,像销售等,可能还好一点,但是我们很多人做的工作可能没有具体的数据来支持,这种时候你平时也要对自己的业绩进行宣传了。
      我看过很多人平时都不怎么跟上司沟通,但是一到年底对考核结果不满,就找上司透漏不满,这种做法无法改变什么,你需要做的是
      (1) 要跟上司做定期的沟通:跟自己的顶头上司定期沟通是很重要,因为通过这种沟通你可以让上司知道你正在做的工作,同时你也可以了解上司到底想什么,对你期待什么。按自己的标准来做事在公司里是站不住脚的,如果想要获得好的绩效评价,你必须要满足上司的期待和标准。
      (2)对自己的业绩进行宣传:大家肯定会问这个怎么宣传啊?上司不都在看着吗?但是很多时候你做的一些事情上司还真不知道,不管你多么努力工作,如果上司不知道的话就没用,所以必要的时候一定要把一些工作进展的情况CC给上司,或我一般是采取定期把自己正在做的工作列个目录,详细描述进行情况发给上司,上司在进行绩效考核的时候可以参照这些书面的东西。
      (3)即使上司给了你一个不好的评价,你不能透漏不满。因为上司这样做肯定是有他的理由的,而且他有权力给你不好的评价。你需要做的是让上司说出来他的意见,你要根据上司的意见来进行改正,因为你有义务迎合上司的工作方式、工作作风,谁让他是你的上司呢?

    16. 你是不是公司里的“好好人”?如果一味地讨好他人,你便会失去他人的尊重

      每个公司都会有好好人,他们对于所有人都笑眯眯,对于所有人的要求都不会说“NO”。如果你是新进入公司的员工,可能刚开始要得到其他同事的信任,需要讨好别人,当然这个是需要的,但是请你不要搞混”谦虚、摆正态度”和 “没有自己主见的好好人” 。如果你一味地讨好他人没有一点自己的主见,你会失去他人对你的尊重,在工作中别人也会把你看作是没有真学问的空瓶。
      
      我知道这个说起来简单做起来难,有些时候是需要讨好人,但是面对重要的事情或重要的业务时,如果你认为你的想法是正确的,你应该坚持,不能一味同意别人的观点,要有自己的主见。
      
      以前听朋友说他们公司有一个人,对于任何人拜托他的事情他都说好,结果到后来公司里的所有杂事都摊到他那里去了,他自己是为了这些琐事而整天忙碌,但是别人在后面则会笑话他。当时听的时候我想,他的同事们怎么这样啊?但是一想,估计这些事情都是他咎由自取的。对于不合适的工作或拜托,或对工作的正确的意见,如果你认为正确的话,你都应该要提出来,不能做个“好好人”,这两者的度怎么掌握,那还是看个人所处的环境或性格了。^^
      
    17.不要隐藏自己的失误

      我们在工作中难免会犯一些失误,所有人都有一种心理,那就是想在别人不知道的情况下隐藏自己的失误。但是有一点请注意,如果你所犯的失误涉及到你们部门或你的上司,你一定不能隐藏,因为很多时候隐藏自己的失误带来的是更大的失误,正所谓越遮越丑,就算你犯的是一个很低级的错误,你也要告知部门负责人或相关人员。
      
      我刚开始工作的时候犯了这个错误,刚开始写企划案的时候修改的次数会比较多,因为上司和我之间来来回回的版本比较多,所以最后把最终版本发给上司以后自己发现有一些数字错了,因为是刚开始负责企划案,不想让别人知道我的疏忽,我就偷偷改了这些数字,因为第二天上司跟老总开会时我会把资料打印出来给他们。第二天当我把打印出来的资料递给上司,上司瞅了几眼,正好看到了那些数字,他就大发雷霆。他发火不是因为我出现了失误,因为每个人都难免会失误,问题是我想偷偷隐藏这个失误,并没有考虑上司的立场。如果当时他没发现这个,到时候给老总报告时发现了,老总正好也对这个数据有印象(因为资料是提前发给老总的),而他自己不能自圆其说的话会有什么样的后果。
      
      这件事情对我的启示很大。我并不是说所有的失误都要公开,如果这个事情不涉及到别人,你自己一个人就解决的话你就不用公开。但是如果这个失误会波及到你的上司或组织,一定要提前告知他们,并想办法解决。所有人都会失误,如果你非常负责地处理你所犯的失误,它不会让你难堪,反而会给你加分的,因为领导们觉得你很诚实而且有责任心。但是请注意,事情过去以后同样的错误你不能再犯一次。

    18.休了病假或产假吗?你需要注意了

      病假和产假是一个很好的福利制度,最近发现公司里怀孕的人比较多,大多数人认为法定的“病假或产假”是严格受法律保护的权利,但是你一定要注意,这有可能会把你陷入两难境地。当然,当你休长期病假(法定的)或产假还有哺乳期间公司是不能解雇你,但是如果这段期间你处理不好的话,一旦过了这个时期你就会上“黑名单”上。因为公司的员工数基本上是固定的,一旦你休几个月的假,这段期间你的工作会分到别人的头上或公司要额外的招人,过了几个月以后当你回来很可能已经没有你的位置或让你做的工作了。
      那么怎么样才能防止这种情况呢?
      (1)假期期间,持续跟公司的联系,特别是跟你上司的联系:我知道对于刚生孩子休产假的人来说这个应该很难,因为有太多事情让你操心,但是我还是希望你能定期抽时间跟上司或同事联系,聊一下工作的事情,或有重要的项目时如果可以的话你也可以给一些建议,但是这些,必须要让你的上司。
      (2)一定要与时俱进,不能丢”业务感觉”。我们学外语的时候语感很重要,但是一旦你放了很久,你就没有语感了,这样你整个外语水平就会下降。工作也是一样的,你必须对你的业务保持那种“业务感觉”,如果可以的话在家里也看一下相关资料(当然是在你的身体允许的情况下),因为你一旦上班,公司或上司会有一段时间“观察”你,看你的工作能力或效率是不是跟以前一样。
      
      我朋友的一个同事就是刚生完孩子上班之后状态特别不好,其实这个是情有可原的,因为小孩晚上闹精神状态就不太好,肯定会影响白天上班。但是公司不能接受她不能集中精力工作,休完产假以后过了1个月后,上司就慢慢不给她工作,而且把她手头上的工作也慢慢分给别人,最后是那个同事自己受不了无所事事就提出辞职了,这个可能就是公司所愿意的。如果她没有主动提出辞职,估计过了哺乳期以后公司也会用各种理由裁她的。
      
    19. 劳动法并不能保护你

      可能很多人会觉得现在随着法律的完善,特别是随着劳动合同法的修订等,劳动法会保护我们,但是不要对劳动法抱有幻想,它并不能保护我们。因为正所谓“上有政策下有对策”,公司的人事部或外部的人事机构会巧妙的绕过法律,保护公司的利益。

      举一个例子,从新劳动合同法第39条中明确规定 劳动者有下列情形之一的,用人单位可以解除劳动合同,如“严重违反用人单位的规章制度的”,用人单位的规章制度很多样化,我们公司以前制定一个“公司员工手册”时,我们看到光是工作纪律这块就列了100多条^^ 几乎你所想到的或没想到的都列了出来,到时候如果公司真的要辞掉你,很简单,在这么多条当中肯定适用于你的。
      
      而且一般公司想裁你会通过一些措施来让你“主动辞职”,比如上司经常给你分配你无法完成的任务,或上司对你的态度很冷淡让你无法忍受,你的办公桌移到非常不好的位置,给你一个很短的期限完成一个根本不可能完成的任务,给你很低的评价等,如果有这种征兆的话,你应该好好考虑自己的职业规划并做打算才行。

    20.赢才是硬道理

      说了这么多,或许给一些即将进入社会或刚进入社会的师弟师妹们一种恐惧的心理,想着公司怎么都这样啊。或许这个不是适用于所有的公司,因为我也碰到过好的公司,好的上司。
      
      但是不怕一万就怕万一,我希望大家都提前准备能保护自己的武器,可以绕过这些陷阱。如果你有才能,你必须要充分发挥出来并让别人知道,并让他们给你打开一扇机会之门。
      
      我们的人生就像是一场赌博,职场更是一场赌博,你可以选择你出的牌,从而决定自己的输赢。
      
      在职场无望的等待天上掉馅饼不是明智之举,你应该积极地占据主动位置,学会“赌博”,学会扭转局势,因为赢才是硬道理。

    文章摘自 漂泊者 原文地址:http://www.piaobozhe.com/read.php?tid=5195

    Posted Sep 27 2009, 08:30 PM by wicky with no comments
    Filed under:
  • NLS_LANG FAQ

    http://www.oracle.com/technology/tech/globalization/htdocs/nls_lang%20faq.htm#_Toc110410556

    As an FAQ you can easily navigate to the sections of interest. It is recommended to start with the NLS_LANG Parameter Fundamentals section first to get a basic understanding of how the NLS_LANG parameter works.

    NLS_LANG Parameter Fundamentals

    Common NLS_LANG Myths

    Checking the current NLS_LANG Setting

    The Priority of NLS Parameters related to NLS_LANG

    Session Parameters

    Instance Parameters

    Database Parameters

    An example of a wrong NLS_LANG setup

    How to setup the NLS_LANG Properly for UNIX

    How to setup the NLS_LANG Properly for Windows and DOS Code Pages

    Where to set the NLS_LANG in Windows

    Determine your Windows ANSI code page

    The correct NLS_LANG for Windows Command Line Operations

    List of common NLS_LANG settings used in the Windows Registry:

    List of common NLS_LANG settings used in the Command Prompt (DOS box)

    Other Frequently asked questions regarding NLS_LANG

    What does the LANGUAGE component of the NLS_LANG parameter control?

    What does the TERRITORY component of the NLS_LANG parameter control?

    How to see what's really stored in the database?

    Where is the Character Conversion Done?

    Windows SQL*Plus is not showing all my extended characters?

    I get a question mark or inverted question mark when selecting back just inserted characters?

    Is iSQL*Plus the only unicode enabled client we support?

    What about command line tools like SQL*Loader, Import, Export, utilities?

    What about database links?

    What about Multiple Homes on Windows?

    Is there an Oracle Unicode Client on Windows?

    What is a Character set or Code Page?

    Why Are There Different Character sets?

    What is the difference between 7 bit, 8 bit and Unicode Character sets?

    How to choose the right database character set?

     

    NLS_LANG Parameter Fundamentals

    A locale is a set of information addressing linguistic and cultural requirements that corresponds to a given language and country. Traditionally, the data associated with a locale provides support for formatting and parsing of dates, times, numbers, and currencies, etc. Providing current and correct locale data has historically been the responsibility of each platform owner or vendor, leading to inconsistencies and errors in locale data.

    Setting the NLS_LANG environment parameter is the simplest way to specify locale behavior for Oracle software. It sets the language and territory used by the client application and the database server. It also indicates the client's character set, which corresponds to the character set for data to be entered or displayed by a client program.

    NLS_LANG is set as a local environment variable on UNIX platforms. NLS_LANG is set in the registry on Windows platforms.

    The NLS_LANG parameter has three components: language, territory, and character set. Specify it in the following format, including the punctuation:

    NLS_LANG = language_territory.charset

    Each component of the NLS_LANG parameter controls the operation of a subset of globalization support features:

    Language

    Specifies conventions such as the language used for Oracle messages, sorting, day names, and month names. Each supported language has a unique name; for example, AMERICAN, FRENCH, or GERMAN. The language argument specifies default values for the territory and character set arguments. If the language is not specified, then the value defaults to AMERICAN.

    Territory

    Specifies conventions such as the default date, monetary, and numeric formats. Each supported territory has a unique name; for example, AMERICA, FRANCE, or CANADA. If the territory is not specified, then the value is derived from the language value.

    Charset

    Specifies the character set used by the client application (normally the Oracle character set that corresponds to the user's terminal character set or the OS character set). Each supported character set has a unique acronym, for example, US7ASCII, WE8ISO8859P1, WE8DEC, WE8MSWIN1252, or JA16EUC. Each language has a default character set associated with it.

    Note:

    All components of the NLS_LANG definition are optional; any item that is not specified uses its default value. If you specify territory or character set, then you must include the preceding delimiter [underscore (_) for territory, period (.) for character set]. Otherwise, the value is parsed as a language name.

    For example, to set only the territory portion of NLS_LANG, use the following format: NLS_LANG=_JAPAN

    The remainder of this document will focus on the charset component of the NLS_LANG setting, as it is the least understood and most important piece to set correctly.

    Top of the Document

    Common NLS_LANG Myths

    ·         Setting the NLS_LANG to the character set of the database MAY be correct but IS often not correct. DO NOT assume that NLS_LANG needs to be the same as the database character set. THIS IS OFTEN NOT TRUE.

    ·         The character set defined with the NLS_LANG parameter does NOT CHANGE your client's character set. It is used to let Oracle know what character set you are USING on the client side, so Oracle can do the proper conversion. You cannot change the character set of your client by using a different NLS_LANG!

    ·         If you don't set the NLS_LANG on the client it uses the NLS_LANG of the server. This is also NOT true! For example, if the Oracle Installer does not populate NLS_LANG, and it is not otherwise set then its value by default is AMERICAN_AMERICA.US7ASCII. The language is AMERICAN, the territory is AMERICA, and the character set is US7ASCII.

    ·         Setting the LANGUAGE and TERRITORY parameters of NLS_LANG has nothing to do with the ability to store characters in a database. A NLS_LANG set to JAPANESE_JAPAN.WE8MSWIN1252 will not allow you to store Japanese, as WE8MSWIN1252 doesn't support Japanese characters. However a NLS_LANG set to AMERICAN_AMERICA.JA16SJIS will allow you to store Japanese providing the input data is truly JA16SJIS and if the database is also in a character set that can store Japanese like UTF8 or JA16SJIS)

    Top of the Document

    Checking the current NLS_LANG Setting

    In many cases the NLS_LANG has been already set during the Oracle install or thereafter manually. To be sure you can use these methods to get back the value of NLS_LANG for SQL*Plus:

    On UNIX:

    SQL> HOST ECHO $NLS_LANG

    This returns the value of the parameter.

    On Windows:

    On Windows you have two possible options, normally the NLS_LANG is set in the registry, but it can also be set in the environment, however this is not often done. The value in the environment takes precedence over the value in the registry and is used for ALL Oracle_Homes on the server. Also note that any USER environment variable takes precedence over any SYSTEM environment variable (this is Windows behavior, and has nothing to do with Oracle) if set.

    To check if it's set in the environment:

     SQL> HOST ECHO %NLS_LANG% 

    If this reports just %NLS_LANG% back, the variable is not set in the environment.

    If it's set it reports something like

     ENGLISH_UNITED KINGDOM.WE8ISO8859P1 

    If NLS_LANG is not set in the environment, check the value in the registry:

    SQL>@.[%NLS_LANG%].

    If you get something like:

     Unable to open file.[ENGLISH_UNITED KINGDOM.WE8ISO8859P1].

    The "file name" between the braces is the value of the registry parameter.

    If you get this as result:

    Unable to open file ".[%NLS_LANG%]." then the parameter NLS_LANG is also not set in the registry.

    Note the @.[%NLS_LANG%]. technique reports the NLS_LANG known by the SQL*Plus executable, it will not read the registry itself. But if you run the HOST command first and the NLS_LANG is not set in the environment then you can be sure the variable is set in the registry if the @.[%NLS_LANG%]. returns a valid value.

    All other NLS parameters can be retrieved by a:

    SELECT * FROM NLS_SESSION_PARAMETERS; 

    Note:

    SELECT USERENV ('language') FROM DUAL; gives the session's <Language>_<territory> but the DATABASE character set not the client, so the value returned is not the client's complete NLS_LANG setting!

    Top of the Document

    The Priority of NLS Parameters related to NLS_LANG

    This section explains the order in which NLS parameters are taken into account in the database client/server model. (This does NOT cover Thin JDBC connections)

    There are 3 levels at which you can set NLS parameters: Database, Instance and

    Session. If a parameter is defined at more than one level then the rules on which one takes precedence are quite straightforward:

    1. NLS database settings are superseded by NLS instance settings

    2. NLS database & NLS instance settings are superseded by NLS session settings

    Session Parameters

    SELECT * from NLS_SESSION_PARAMETERS;

    These are the settings used for the current SQL session.

    These reflect (in this order):

    1) The values of NLS parameters set by "ALTER SESSION "

    ALTER SESSION set NLS_DATE_FORMAT = 'DD/MM/YYYY';

    2) If there is no explicit "ALTER SESSION " statement done then it reflects the setting of the corresponding NLS parameter on the client derived from the NLS_LANG variable.

    3) If NLS_LANG is specified with only the <Territory> part then AMERICAN is used as default <Language>.

    So if you set NLS_LANG=_BELGIUM. WE8MSWIN1252 then you get this:

    PARAMETER VALUE

    ------------------------------ --------------

    NLS_LANGUAGE AMERICAN

    NLS_TERRITORY BELGIUM

    NLS_CURRENCY <euro sign here>

    NLS_ISO_CURRENCY BELGIUM

    ....

    Note:

    The difference between NLS_LANG=_BELGIUM.WE8MSWIN1252 (correct) and

    NLS_LANG=BELGIUM.WE8MSWIN1252 (incorrect), you need to set the "_" as separator.

    4) If NLS_LANG is specified with only the <Language> part then the <Territory> defaults to a setting based on <Language>.

    So if you set NLS_LANG=ITALIAN_.WE8MSWIN1252 then you get this:

    PARAMETER VALUE

    ------------------------------ --------------

    NLS_LANGUAGE ITALIAN

    NLS_TERRITORY ITALY

    NLS_CURRENCY <euro sign here>

    NLS_ISO_CURRENCY ITALY

    .....

    Note:

    Note the difference between NLS_LANG=ITALIAN_.WE8MSWIN1252 (correct) and

    NLS_LANG=ITALIAN.WE8MSWIN1252 (incorrect), you need to set the "_" as separator.

    5) If NLS_LANG is specified without the <Language>_<Territory> part then the <Language>_<Territory> part defaults to AMERICAN_AMERICA.

    So if you set NLS_LANG=.WE8MSWIN1252 then you get this:

    PARAMETER VALUE

    ------------------------------ ----------

    NLS_LANGUAGE AMERICAN

    NLS_TERRITORY AMERICA

    NLS_CURRENCY $

    NLS_ISO_CURRENCY AMERICA

    ....

    Note:

    The difference between NLS_LANG=.WE8MSWIN1252 (correct) and

    NLS_LANG=WE8MSWIN1252 (incorrect), you need to set the "." as separator.

    6) If the NLS_LANG is set (either like in point 3, 4 or 5) then parameters like

    NLS_SORT, NLS_DATE_FORMAT, etc. can be set as a "standalone" setting and will overrule the defaults derived from NLS_LANG <Language>_<Territory> part.

    So if you set NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252 and NLS_ISO_CURRENCY=FRANCE then you get this:

    PARAMETER VALUE

    ------------------------------ -----------

    NLS_LANGUAGE AMERICAN

    NLS_TERRITORY AMERICA

    NLS_CURRENCY $

    NLS_ISO_CURRENCY FRANCE

    ...

    Defaults:

    ---------

    * If NLS_DATE_LANGUAGE or NLS_SORT are not set then they are derived from

    NLS_LANGUAGE.

    * If NLS_CURRENCY, NLS_DUAL_CURRENCY, NLS_ISO_CURRENCY, NLS_DATE_FORMAT, NLS_TIMESTAMP_FORMAT, NLS_TIMESTAMP_TZ_FORMAT, NLS_NUMERIC_CHARACTERS are not set then they are derived from NLS_TERRITORY

    7) If the NLS_LANG is not set at all, then it defaults to

    <Language>_<Territory>.US7ASCII and the values for the

    <Language>_<Territory> part used are the ones found in

    NLS_INSTANCE_PARAMETERS. Parameters like NLS_SORT defined as "standalone" on the client side are ignored.

    Note:

    * If set, client parameters (NLS_SESSION_PARAMETERS) always take precedence over NLS_INSTANCE_PARAMETERS and NLS_DATABASE_PARAMETERS.

    * This behavior cannot be disabled on/from the server, so a parameter set on the client always has precedence above an instance or database parameter.

    * NLS_LANG cannot be changed by ALTER SESSION, NLS_LANGUAGE and NLS_TERRITORY can. However NLS_LANGUAGE and /or NLS_TERRITORY cannot be set as "standalone" parameters in the environment or registry on the client.

    * NLS_SESSION_PARAMETERS is NOT visible for other sessions. If you need to trace this then you have to use a logon trigger to create your own logging table (based on session parameters)

    * The <clients characterset> part of NLS_LANG is NOT shown in any system table or view.

    * On Windows you have two possible options, normally the NLS_LANG is set in the registry, but it can also be set in the environment, however this is not often done and generally not recommended to do so. The value in the environment takes precedence over the value in the registry and is used for ALL Oracle_Homes on the server if defined as a system environment variable.

    * NLS_LANGUAGE in the session parameters also declares the language for the client error messages.

    * You cannot "set" a NLS parameter in an SQL script; you need to use ALTER SESSION.

    Top of the Document

    Instance Parameters

    SELECT * from NLS_INSTANCE_PARAMETERS;

    These are the settings in the init.ora of the database at the moment that the database was started or set through ALTER SYSTEM.

    If the parameter is not explicitly set in the init.ora or defined by ALTER SYSTEM then its value is NOT derived from a "higher" parameter (we are talking about parameters like NLS_SORT that derive a default from NLS_LANGUAGE in NLS_SESSION_PARAMETERS, this is NOT the case for NLS_INSTANCE_PARAMETERS)

    Note:

    * NLS_LANG is not an init.ora parameter; NLS_LANGUAGE and NLS_TERRITORY are so you need to set NLS_LANGUAGE and NLS_TERRITORY separately.

    * You cannot define the <clients characterset> or NLS_LANG in the init.ora

    The client characterset is defined by the NLS_LANG on the client OS (see above).

    * You cannot define the database characterset in the init.ora. The database characterset is defined by the "Create Database" command.

    * These settings take precedence above the NLS_DATABASE_PARAMETERS.

    * These values are used for the NLS_SESSION_PARAMETERS if the client the

    NLS_LANG is NOT set.

    * Oracle strongly recommends that you set the NLS_LANG on the client at least to

    NLS_LANG=.<clients characterset>

    * The NLS_LANGUAGE in the instance parameters also declares the language for the server error messages in alert.log and in trace files.

    Top of the Document

    Database Parameters

    SELECT * from NLS_DATABASE_PARAMETERS;

    Defaults to AMERICAN_AMERICA if there are no parameters explicitly set in the init.ora during database creation time. If there is parameters set in the init.ora during database creation you see them here. There is no way to change these after the database creation. Do NOT attempt to update system tables to bypass these settings! These settings are used to give the database a default if the INSTANCE and SESSION parameters are not set.

    Note:

    * NLS_LANG is not an init.ora parameter, NLS_LANGUAGE and NLS_TERRITORY are.

    So you need to set NLS_LANGUAGE and NLS_TERRITORY separately.

    * These parameters are overridden by NLS_INSTANCE_PARAMETERS and NLS_SESSION_PARAMETERS.

    * You cannot define the <clients character set> or NLS_LANG in the init.ora. The client character set is defined by the NLS_LANG on the client OS.

    * You cannot define the database character set in the init.ora.

    The database (national) character set NLS_(NCHAR)_CHARACTERSET) is defined by the "Create Database" command.

    * The NLS_CHARACTERSET and NLS_NCHAR_CHARACTERSET parameters cannot be overridden by instance or session parameters.

    They are defined by the value specified in the "CREATE DATABASE command and are not intended to be changed afterwards dynamically. Do NOT update system tables to change the character set. This can corrupt your database and potentially make it impossible to open the database again.

    * Setting the NLS_LANG during the creation of the database does not influence the NLS_DATABASE_PARAMETERS.

    * The NLS_LANG set during the database creation has NO impact on the database National Characterset.

    Additional SELECT statements:

    A) SELECT name,value$ from sys.props$ where name like '%NLS%';

    This gives the same info as NLS_DATABASE_PARAMETERS.

    You should use NLS_DATABASE_PARAMETERS instead of props$.

    Note the UPPERCASE '%NLS%'

    B) SELECT * from v$nls_parameters;

    This view shows the current session parameters and the *DATABASE* characterset as seen in the NLS_DATABASE_PARAMETERS view.

    C) SELECT name,value from v$parameter where name like '%NLS%';

    This view gives the same information as NLS_INSTANCE_PARAMETERS.

    Note the LOWERCASE '%NLS%'

    D) SELECT userenv ('language') from dual;

    and

    SELECT sys_context('userenv','language') from dual;

    Both these SELECT statements give the session's <Language>_<territory> and the

    DATABASE character set. The database character set is not the same as the character set of the NLS_LANG that you started this connection with! So don't be fooled, although the output of this query looks like the value of a NLS_LANG variable, it is NOT.

    E) SELECT userenv ('lang') from dual;

    This SELECT gives the short code that Oracle uses for the Language defined by NLS_LANGUAGE setting for this session. If NLS_LANGUAGE is set to French then this will return "F", if NLS_LANGUAGE is set to English then this will return "GB"

    If NLS_LANGUAGE is set to American then this will return "US", and so on...

    F) SHOW parameter NLS%

    This will give the same as the NLS_INSTANCE_PARAMETERS

    Top of the Document

    An example of a wrong NLS_LANG setup

    A database is created on a UNIX system with the US7ASCII character set. A Windows client connecting to the database works with the WE8MSWIN1252 character set (regional settings -> Western Europe /ACP 1252) and the DBA, use the UNIX shell (ROMAN8) to work on the database. The NLS_LANG is set to american_america.US7ASCII on the clients and the server.

    Note:

    This is an INCORRECT setup to explain character set conversion, don't use it in your environment!

    A very important point (as mentioned before):

    When the client NLS_LANG character set is set to the same value as the database character set, Oracle assumes that the data being sent or received are of the same (correct) encoding, so no conversions or validations may occur for performance reasons. The data is just stored as delivered by the client, bit by bit.

     From Windows insert an ‘é’ (LATIN SMALL LETTER E WITH ACUTE) into a table NLS_TEST containing one column ‘TEST’ of the type 'char'.

    As long as you insert into and select from the column on Windows with the WE8MSWIN1252 character set everything runs smoothly. No conversion is done and 8 bits are inserted and read back, even if the character set of the database is defined as 7 bits. This happens because a byte is 8 bits and Oracle is ALWAYS using 8 bits even with a 7 bit character set. In a correct setup the most Significant Bit is just not used and only 7 bits are taken into account.

    For one reason or another you need to insert from the UNIX server. When you SELECT from tables where data is inserted by the Windows clients you get a ‘Ò’ (LATIN CAPITAL LETTER O WITH TILDE) instead of the ‘é’. 

    If you insert ‘é’ on the UNIX server and you SELECT the row at the Windows client you get an ‘Å’ (LATIN CAPITAL LETTER A WITH RING ABOVE) back.

    Bottom line is that you have INCORRECT data in the database. You store the numeric value for ‘é’ of the WE8MSWIN1252 character set in the database but you tell Oracle this is US7ASCII data, so Oracle is NOT converting anything and just stores the numeric value (again: Oracle thinks that the client is giving US7ASCII codes because the NLS_LANG is set to US7ASCII, and the database character set is also US7ASCII -> no conversion done).

     When you SELECT the same column back on the UNIX server, Oracle is again expecting that the value is correct and passes the value to the UNIX terminal without any conversion.

    Now the problem is that in the WE8MSWIN1252 character set the ‘é’ has the hexadecimal value 'E9’and in the Roman8 character set the hexadecimal value for ‘é’ is 'C5'.  Oracle just passes the value stored in the database ('E9') to the UNIX terminal, and the UNIX terminal thinks this is the letter ‘?’ because in its (Roman8) character set the hexadecimal value 'E9' is representing the letter ‘Ò’.  So instead of the ‘é’ you get ‘Ò’ on the UNIX terminal screen.

     The inverse (the insert on the UNIX and the SELECT on the Windows client) is the same story, but you get other results.

     The solution is creating the database with a character set that contains ‘é’

    (WE8MSWIN1252, WE8ISO89859P1, UTF-8, etc.) and setting the NLS_LANG on the client to WE8MSWIN1252 and on the server to WE8ROMAN8. If you then insert an ‘é’ on both sides, you will get an ‘é’ back regardless of where you SELECT them. Oracle knows then that a hexadecimal value of 'C5’ inserted by the UNIX and an 'E9’ from a WE8MSWIN1252 client are both ‘é’ and inserts ‘é’ into the database (the code in the database depends on the character set you have chosen). 

     You don't have to switch between UNIX, Windows or other OS clients to run into this kind of problem.  The same problem appears if you add Windows clients that are using another character set and have an incorrect NLS_LANG set.

     

    Top of the Document

    How to setup the NLS_LANG Properly for UNIX

    To specify the locale behavior of your client Oracle software, you have to set your NLS_LANG parameter. It sets the language, territory and also the character set of your client. You need to check the locale environment settings to set your NLS_LANG 3rd field (character set) in accordance with it. To do this, use the "locale" command like this:

    $ locale

    Example of output:

    LANG=fr_FR
    LC_CTYPE="fr_FR.iso885915@euro"
    LC_COLLATE="fr_FR.iso885915@euro"
    LC_MONETARY="fr_FR.iso885915@euro"
    LC_NUMERIC="fr_FR.iso885915@euro"
    LC_TIME="fr_FR.iso885915@euro"
    LC_MESSAGES="fr_FR.iso885915@euro"
    LC_ALL=fr_FR.iso885915@euro


    The output of this command is not exactly the same on all the Unix environments. On some platforms, it can be useful to use the following syntax to have more details about the codepage really used:

    $ locale LC_CTYPE | head

    Example of output in a HP-UX environment:
    ""

      
      
     
    ""

      
      
     
    "iso885915"

      
      
     
    ""

      
      
     
    Example of output in a Linux environment:

      
      
     
    upper;lower;alpha;digit;xdigit;space;print;graph;blank;cntrl;
    punct;alnum;

    combining;combining_level3
    toupper;tolower;totitle
    16
    1
    ISO-8859-15
    70
    84
    1
    0
    1

    In these cases, the NLS_LANG 3rd field should be set to WE8ISO8859P15. On Solaris, AIX, TRU64, this syntax doesn't give interesting complementary information. To find more details about these settings:
    On Solaris, look in /usr/lib/locale
    On AIX, look in /usr/lib/nls/README
    On TRU64, look in /usr/lib/nls
    On HP-UX, look in /usr/lib/nls/config
    On Linux, look in /usr/share/locale/locale.alias

    To set a chosen value for these "locale" settings, it's needed to know which values are available. To know that, use the following syntax:

    $ locale -a

    Then, when you have chosen a value, for example UTF-8 on Linux, you can set it like this:

    $ export LC_ALL=UTF-8

    or

    % setenv LC_ALL UTF-8

    Example of output after the setenv:

    $ locale

    LANG=fr_FR
    LC_CTYPE="UTF-8"
    LC_NUMERIC="UTF-8"
    LC_TIME="UTF-8"
    LC_COLLATE="UTF-8"
    LC_MONETARY="UTF-8"
    LC_MESSAGES="UTF-8"
    LC_PAPER="UTF-8"
    LC_NAME="UTF-8"
    LC_ADDRESS="UTF-8"
    LC_TELEPHONE="UTF-8"
    LC_MEASUREMENT="UTF-8"
    LC_IDENTIFICATION="UTF-8"
    LC_ALL=UTF-8

    $ locale LC_CTYPE | head
    upper;lower;alpha;digit;xdigit;space;print;

    graph;blank;cntrl;punct;alnum;combining;combining_level3
    toupper;tolower;totitle
    16
    6
    UTF-8
    70
    84
    1
    0
    1

    In this case, the 3rd field (character set) of NLS_LANG should be set to UTF8.

    % setenv NLS_LANG American_America.UTF8

    Top of the Document

    How to setup the NLS_LANG Properly for Windows and DOS Code Pages

    On Windows systems, the encoding scheme (character set) is specified by a code page. Code pages are defined to support specific languages or groups of languages, which share common writing systems. From Oracle point of view the terms code page and character set mean the same. Note that in non Chinese-Japanese-Korean environments, the Windows GUI and DOS command prompt do not use the same code page.

    As a result Windows uses 2 different character sets for the ANSI (sqlplusw.exe) and the OEM (dos box - sqlplus.exe) environments.

    Where to set the NLS_LANG in Windows

    In the Registry:

    On Windows systems, you should make sure that you have set an NLS_LANG registry subkey for each of your Oracle Homes:

    You can easily modify this subkey with the Windows Registry Editor:

    Start -> Run...

    Type "regedit", and click "ok"

    Edit the following registry entry:

    For Oracle version 7:

    HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE

    For Oracle Database versions 8, 8i and 9i:

    HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMEx\

    where "x" is the unique number identifying the Oracle home.

    HOME0 is the first installation

    For Oracle Database 10g:

    HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_<oracle_home_name>

    There you have an entry with name NLS_LANG

    When starting an Oracle tools, like SQL*Plusw, it will read the content of the oracle.key file located in the same directory to determine which registry tree will be used, therefore which NLS_LANG subkey will be used.

    Note:

    Some people are confused by finding a NLS_LANG set to "NA" in HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE when no version 7 was installed. This is used for backwards compatibility, and can be ignored.

    As a System or User Environment Variable, in System properties:

    Although the Registry is the primary repository for settings on Windows, it is not the only place where parameters can be set. Even if not at all recommended, you can set the NLS_LANG as a System or User Environment Variable in the System properties.

    This setting will be used for ALL Oracle homes.

    To check and modify them:

    Right-click the 'My Computericon -> 'Properties'

    Select the 'Advanced Tab -> Click on 'Environment Variables'

    The 'User Variables list contains the settings for the specific OS user currently logged on and the 'System variables system-wide variables for all users.

    Since these environment variables take precedence over the parameters already set in your Registry, you should not set Oracle parameters at this location unless you have a very good reason.

    As an Environment variable defined in the command prompt:

    Before using an Oracle command line tool you need to MANUALLY SET the NLS_LANG parameter. In an MS-DOS command prompt, use the set command, for example:

    C:\> set NLS_LANG=american_america.WE8PC850

    Top of the Document

    Determine your Windows ANSI code page

    Now that you know what the NLS_LANG is currently set to you can check to see if it properly agrees with the current ANSI code page. The ACP (ANSI Code Page) is defined by the "default locale" setting of Windows, so if you have a UK Windows 2000 client and you want to input Cyrillic (Russian) you need to change the ACP (by changing the "default locale") in order to be able to input Russian.

    You'll find its value in the registry:

    Start -> Run...

    Type "regedit", and click "ok"

    Browse the following registry entry:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NLS\CodePage\

    There you have (all the way down) an entry with as name ACP. The value of ACP is your current GUI Codepage, for the mapping to the Oracle name. Since there are many registry entries with very similar names, please make sure that you are looking at the right place in the registry.

    Additionally, the following URL provides a list of the default code pages for all Windows versions:

    http://www.microsoft.com/globaldev/reference/ (under the REFERENCE tab on the left of the page)

    OEM = the command line codepage, ANSI = the GUI codepage

    Note that the Honk Kong HKSCS is listed here: http://www.microsoft.com/hk/hkscs/

    Find the correspondent Oracle client character set:

    Find the Oracle client character set in the table below based on the ACP you found above. Note that there is only ONE CORRECT value for a given ACP.

    ANSI CodePage (ACP)

    Oracle Client character set (3rd part of NLS_LANG)

    1250

    EE8MSWIN1250

    1251

    CL8MSWIN1251

    1252

    WE8MSWIN1252

    1253

    EL8MSWIN1253

    1254

    TR8MSWIN1254

    1255

    IW8MSWIN1255

    1256

    AR8MSWIN1256

    1257

    BLT8MSWIN1257

    1258

    VN8MSWIN1258

    874

    TH8TISASCII

    932

    JA16SJIS

    936

    ZHS16GBK

    949

    KO16MSWIN949

    950

    ZHT16MSWIN950 - except for Hong Kong (see below)

    This is the character set used by the GUI SQL*Plus (sqlplusW.exe/ plus80W.exe / plus33W.exe ) that you start through the Windows start menu. Please note the difference between the GUI SQL*Plus and the "DOS mode" SQL*Plus.

    You can use UTF8 as Oracle client character set (=NLS_LANG) on Windows NT, 2000 and XP but you will be limited to use only client programs that explicitly support this configuration. This is because the user interface of Win32 is not UTF8, therefore the client program have to perform explicit conversions between UTF8 (used on Oracle side) and UTF16 (used on Win32 side).

    Set it in your Registry:

    Use the Windows Registry Editor to set up the NLS_LANG in your Oracle Home with the value you have just found above.

    Top of the Document

    The correct NLS_LANG for Windows Command Line Operations

    MS-DOS mode uses, with a few exceptions like CJK, (Japanese, Korean, Simplified Chinese, and Traditional Chinese) a different code page (called OEM code page) than Windows GUI (ANSI code page). Meaning that before using an Oracle command line tool such as SQL*Plus (sqlplus.exe/ plus80.exe / plus33.exe ) en svrmgrl in a command prompt then you need to MANUALLY SET the NLS_LANG parameter as an environment variable with the set DOS command BEFORE using the tool.

    For Japanese, Korean, Simplified Chinese, and Traditional Chinese, the MS-DOS OEM code page (CJK) is identical to the ANSI code page meaning that, in this particular case, there is no need to set the NLS_LANG parameter in MS-DOS mode.

    In all other cases, you need to set it in order to overwrite the NLS_LANG registry key already matching the ANSI code page. The new "MS-DOS dedicated" NLS_LANG needs to match the MS-DOS OEM code page that could be retrieved by typing chcp in a Command Prompt:

    C:\> chcp

    Active code page: 437

    C:\> set NLS_LANG=american_america.US8PC437

    If the NLS_LANG parameter for the MS-DOS mode session is not set appropriately, error messages and data can be corrupted due to incorrect character set conversion.

    Use the following list to find the Oracle character set that fits to your MS-DOS code page in use on your locale system:

    MS-DOS codepage

    Oracle Client character set (3rd part of NLS_LANG)

    437

    US8PC437

    737

    EL8PC737

    850

    WE8PC850

    852

    EE8PC852

    857

    TR8PC857

    858

    WE8PC858

    861

    IS8PC861

    862

    IW8PC1507

    865

    N8PC865

    866

    RU8PC866

    Top of the Document

    List of common NLS_LANG settings used in the Windows Registry:

    Note: this is the correct setting for the GUI SQL*Plus version, (sqlplusW.exe/ plus80W.exe / plus33W.exe )

    if you are testing with "special" characters please DO use the GUI and not the "DOS box" sqlplus.exe !

    Operating System Locale

    NLS_LANG Value

    Arabic (U.A.E.)

    ARABIC_UNITED ARAB EMIRATES.AR8MSWIN1256

    Bulgarian

    BULGARIAN_BULGARIA.CL8MSWIN1251

    Catalan

    CATALAN_CATALONIA.WE8MSWIN1252

    Chinese (PRC)

    SIMPLIFIED CHINESE_CHINA.ZHS16GBK

    Chinese (Taiwan)

    TRADITIONAL CHINESE_TAIWAN.ZHT16MSWIN950

    Chinese (Hong Kong HKCS)

    TRADITIONAL CHINESE_HONG KONG.ZHT16HKSCS

    Chinese (Hong Kong HKCS2001)

    TRADITIONAL CHINESE_HONG KONG.ZHT16HKSCS2001 (new in 10gR1)

    Croatian

    CROATIAN_CROATIA.EE8MSWIN1250

    Czech

    CZECH_CZECH REPUBLIC.EE8MSWIN1250

    Danish

    DANISH_DENMARK.WE8MSWIN1252

    Dutch (Netherlands)

    DUTCH_THE NETHERLANDS.WE8MSWIN1252

    Dutch (Belgium)

    DUTCH_BELGIUM.WE8MSWIN1252

    English (United Kingdom)

    ENGLISH_UNITED KINGDOM.WE8MSWIN1252

    English (United States)

    AMERICAN_AMERICA.WE8MSWIN1252

    Estonian

    ESTONIAN_ESTONIA.BLT8MSWIN1257

    Finnish

    FINNISH_FINLAND.WE8MSWIN1252

    French (Canada)

    CANADIAN FRENCH_CANADA.WE8MSWIN1252

    French (France)

    FRENCH_FRANCE.WE8MSWIN1252

    German (Germany)

    GERMAN_GERMANY.WE8MSWIN1252

    Greek

    GREEK_GREECE.EL8MSWIN1253

    Hebrew

    HEBREW_ISRAEL.IW8MSWIN1255

    Hungarian

    HUNGARIAN_HUNGARY.EE8MSWIN1250

    Icelandic

    ICELANDIC_ICELAND.WE8MSWIN1252

    Indonesian

    INDONESIAN_INDONESIA.WE8MSWIN1252

    Italian (Italy)

    ITALIAN_ITALY.WE8MSWIN1252

    Japanese

    JAPANESE_JAPAN.JA16SJIS

    Korean

    KOREAN_KOREA.KO16MSWIN949

    Latvian

    LATVIAN_LATVIA.BLT8MSWIN1257

    Lithuanian

    LITHUANIAN_LITHUANIA.BLT8MSWIN1257

    Norwegian

    NORWEGIAN_NORWAY.WE8MSWIN1252

    Polish

    POLISH_POLAND.EE8MSWIN1250

    Portuguese (Brazil)

    BRAZILIAN PORTUGUESE_BRAZIL.WE8MSWIN1252

    Portuguese (Portugal)

    PORTUGUESE_PORTUGAL.WE8MSWIN1252

    Romanian

    ROMANIAN_ROMANIA.EE8MSWIN1250

    Russian

    RUSSIAN_CIS.CL8MSWIN1251

    Slovak

    SLOVAK_SLOVAKIA.EE8MSWIN1250

    Spanish (Spain)

    SPANISH_SPAIN.WE8MSWIN1252

    Swedish

    SWEDISH_SWEDEN.WE8MSWIN1252

    Thai

    THAI_THAILAND.TH8TISASCII

    Spanish (Mexico)

    MEXICAN SPANISH_MEXICO.WE8MSWIN1252

    Spanish (Venezuela)

    LATIN AMERICAN SPANISH_VENEZUELA.WE8MSWIN1252

    Turkish

    TURKISH_TURKEY.TR8MSWIN1254

    Ukrainian

    UKRAINIAN_UKRAINE.CL8MSWIN1251

    Vietnamese

    VIETNAMESE_VIETNAM.VN8MSWIN1258

    Top of the Document

    List of common NLS_LANG settings used in the Command Prompt (DOS box)

    Note: this is the correct setting for the DOS BOX SQL*Plus version, (sqlplus.exe/ plus80.exe / plus33.exe )

    Operating System Locale

    Oracle Client character set (3rd part of NLS_LANG)

    Arabic

    AR8ASMO8X

    Catalan

    WE8PC850

    Chinese (PRC)

    ZHS16GBK

    Chinese (Taiwan)

    ZHT16MSWIN950

    Czech

    EE8PC852

    Danish

    WE8PC850

    Dutch

    WE8PC850

    English (United Kingdom)

    WE8PC850

    English (United States)

    US8PC437

    Finnish

    WE8PC850

    French

    WE8PC850

    German

    WE8PC850

    Greek

    EL8PC737

    Hebrew

    IW8PC1507

    Hungarian

    EE8PC852

    Italian

    WE8PC850

    Japanese

    JA16SJIS

    Korean

    KO16MSWIN949

    Norwegian

    WE8PC850

    Polish

    EE8PC852

    Portuguese

    WE8PC850

    Romanian

    EE8PC852

    Russian

    RU8PC866

    Slovak

    EE8PC852

    Slovenian

    EE8PC852

    Spanish

    WE8PC850

    Swedish

    WE8PC850

    Turkish

    TR8PC857

    Top of the Document


     

    Other Frequently asked questions regarding NLS_LANG

    What does the LANGUAGE component of the NLS_LANG parameter control?

    The language component of the NLS_LANG parameter controls the operation of a subset of globalization support features. It specifies conventions such as the language used for Oracle messages, sorting, day names, and month names. Each supported language has a unique name; for example, AMERICAN, FRENCH, or GERMAN. The language argument specifies default values for the territory and character set arguments. If the language is not specified, then the value defaults to AMERICAN.

    What does the TERRITORY component of the NLS_LANG parameter control?

    The territory component of the NLS_LANG parameter controls the operation of a subset of globalization support features. It specifies conventions such as the default date, monetary, and numeric formats. Each supported territory has a unique name; for example, AMERICA, FRANCE, or CANADA. If the territory is not specified, then the value is derived from the language value.

    Top of the Document

    How to see what's really stored in the database?

    To find the real numeric value for a character stored in the database use the dump command:

    The syntax of the function call is:

    DUMP( <value> [, <format> [, <offset> [, <length> ] ] ] )

    where:

    value - is the value to be displayed

    format - is a number which describes the format in which bytes of the value are to be displayed: 8 - means octal, 10 - means decimal, 16 - means hexadecimal; other values between 0 and 16 mean decimal; values greater then 16 are a little confusing and mean: print bytes as ASCII characters if they correspond to printable ASCII codes, print them as "^x" if they correspond to ASCII control codes and print them in hexadecimal otherwise; adding 1000 to the format number will add character set information for the character data type values to the return value offset - is the offset of the first byte of the value to display; negative values mean counting from the end length - is the number of bytes to display. So for example,

    SQL> SELECT DUMP(col,1016)FROM table;

    Typ=1 Len=39 CharacterSet=UTF8: 227,131,143,227,131,170

    returns the value of a column consisting of 3 Japanese characters in UTF8 encoding . For example the 1st char is 227(*255)+131. You will probably need to convert this to UCS2 to verify the codepoint value with the Unicode Standard codepage.

    Where is the Character Conversion Done?

    Normally conversion is done at client side for performance reasons. This is true from Version 8.0.4 onwards. If the database is using a character set not known by the client then the conversion is done at server side. This is true from Version 8.1.6 onwards.

    Windows SQL*Plus is not showing all my extended characters?

    You see black squares instead of the characters you probably don’t have the right font defined for your codepage. A font is a collection of glyphs (from "hieroglyphs") that share common appearance (typeface, character size). A font is used by the operating system to convert a numeric value into a graphical representation on screen. A font does not necessarily contain a graphical representation for all numeric values defined in the code page you are using. That's why you sometimes get black squares on the screen if you change fonts and the new font has no representation for a certain symbol.

    The Windows "Character Set Map" utility can be used to see which glyphs are parts of a certain font.

    On Windows 2000 and XP:

    Start -> Run...

    Type "charmap", and click "ok".

    I get a question mark or inverted question mark when selecting back just inserted characters?

    When characters are converted between the client and the database character set, or vice versa, the character should exist in both. If it does not exist in the character set being converted to (the destination) then a replacement character is used. Some character sets have specific replacement characters defined when translating from other specific character sets but where this is not done a default replacement character, such as a ?, is used. Conversion from a replacement character back to the original character is not possible.

    Is iSQL*Plus the only UTF8/Unicode enabled client we support?

    On Windows OS, yes, On Unix OS's, no. All the database utilties, including Import, Export, SQL*Loader, SQL*Plus, can act as a UTF-8 client if the OS locale is UTF-8 (e.g., en_US.UTF-8 on Linux) and NLS_LANG character set is set to UTF8 or AL32UTF8.

    How to check the code points managed by a UNIX Operating System?
    To know which code point is generated for a character in a Unix Environment, you can use the "od" command:

    $ echo "" | od -xc

    You can also check the character corresponding to a code point using the "echo" command like this:

    for Solaris, AIX, HP-UX, TRU64:

    $echo '\0351'


    for Linux:

    $echo -e '\0351'


    You can use Locale Builder or a printed code page (see links below) to verify that your native code page and NLS_LANG setting properly correspond.   If there is any ambiguity then use the command above to get the values for more than one character. For printed code page:

    http://www.unicode.org
    http://www.iso.org
    http://czyborra.com/charsets/iso8859.html

    Top of the Document

    What about command line tools like SQL*Loader, Import, Export, utilities?

    Typically the NLS_LANG needs to match the MS-DOS OEM code page that could be retrieved by typing chcp in a Command Prompt:

    C:\> chcp

    Active code page: 437

    C:\> set NLS_LANG=american_america.US8PC437

    For tools like SQL*Loader you can temporarily change the NLS_LANG to the character set of the FILE you are loading. An alternative to changing NLS_LANG is to specify the character set of the data in the datafile using the characterset keyword in the .ctl file. In that case, SQL*Loader will interpret the data in the datafile as that character set regardless of the client character set setting of NLS_LANG. Here is an example .ctl file for utf16. This example ships in the demo area:

    -- Copyright (c) 2001 by Oracle Corporation
    --   NAME
    --     ulcase11.ctl - Load Data in the Unicode Character Set UTF-16
    --   DESCRIPTION
    --     Loads data in the Unicode character set UTF-16. The data is in little
    --     Endean byte order. This means that depending on whether SQL*Loader is
    --     running on a little Endean or a big Endean system, it will have to
    --     byte swap the UTF-16 character data as necessary. This load uses
    --     character length semantics, the default for the character set UTF-16.
    --
    --     This case study is modeled after case study 3 (ulcase3), which loads
    --     variable length delimited (terminated and enclosed) data.
    --
    --   RETURNS
    --
    --   NOTES
    --     None
    --   MODIFIED   (MM/DD/YY)
    --    rpfau     02/06/01  - Merged rpfau_sqlldr_add_case_study_11
    --    rpfau     01/30/01 -  Creation
    --

    LOAD DATA
    CHARACTERSET utf16
    BYTEORDER little
    INFILE ulcase11.dat
    REPLACE

    INTO TABLE EMP
    FIELDS TERMINATED BY X'002c' OPTIONALLY ENCLOSED BY X'0022'
    (empno integer external (5), ename, job, mgr,
     hiredate DATE(20) "DD-Month-YYYY",
     sal, comm,
     deptno   CHAR(5) TERMINATED BY ":",
     projno,
     loadseq  SEQUENCE(MAX,1) )

    In Oracle9i the Export utility always exports user data, including Unicode data, in the character set of the database. The Import utility automatically converts the data to the character set of the target database.

    In Oracle8i the Export utility exports user data converting them from the database character set to the character set of the NLS_LANG of the Export session. The Import utility first converts the data to the character set of the NLS_LANG of the Import session and then converts them to the character set of the target database. Care must be taken that the character set of the NLS_LANG for Export and Import sessions contain all characters to be migrated. This character set is usually chosen to be either the source database or the target database character set and it is usually the same for both Export and Import sessions. This choice is recommended especially with multibyte character sets, which pose some restrictions on export files. The

    Oracle8i conversions to and from the NLS_LANG character set happen in Oracle9i for DDL statements contained in the Export file.

    Top of the Document

    What about database links?

    The NLS_LANG on the server (or client) has no influence on character set conversion through a database link. Oracle will do the conversion from the character set of the source database to the character set of the target database (or reverse).

    What about Multiple Homes on Windows?

    There is nothing special with NLS_LANG and the multiple homes on Windows. The parameter taken into account is the one specified in the ORACLE_HOME registry key used by the executable. If the NLS_LANG is set in the environment, it takes precedence over the value in the registry and is used for ALL Oracle_Homes on the server/client.

    The NLS_LANG can be found in these registry keys:

    HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE

    or

    HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMEx

    Is there an Oracle Unicode Client on Windows?

    On Windows there are two kinds of tools / applications:

    1) A fully Unicode enabled applications which accepts Unicode codepoints and which can render them. It's the application that needs to deal with the Unicode. Windows provides the Unicode API but the GUI system itself is NOT Unicode "by nature".

    A fully Unicode application can only show one glyph for a given Unicode code point. So there is NO confusion possible here, this application will need to use a full Unicode font. If you have a full Unicode application, then you need to set the NLS_LANG to UTF8.

    Note that there are currently not many applications like this and if not explicitly stated by the vendor it's most likely an ANSI application. So don’t set the NLS_LANG to UTF8 if you are not sure!

    The only Unicode capable client that is included in the Oracle database is iSQL*Plus.

    2) Standard ANSI application (like sqlplusw.exe) cannot use Unicode code points. So the Unicode code point stored in the database needs to be CONVERTED to an ANSI code point based on the correct setting of the NLS_LANG. This allows Oracle to map the Unicode code point to the character set of the client. If the Unicode code point does not have a mapping to the character set of the client then a replacement character is used.

    What is a Character set or Code Page?

    A character set is just an agreement on what numeric value a symbol has. A computer does not know ‘A’ or ‘B ', it only knows the (binary) numeric value for that symbol, defined in the character set used by its Operating System (OS) or in hardware (firmware) for terminals. A computer can only manipulate numbers, which is why there is a need for character sets. An example is 'ASCII', an old 7 bit character set, 'ROMAN8’ a 8 bit character set on UNIX or 'UTF8’ a multibyte character set.

    A code page is the name for the Windows/DOS encoding schemes, for Oracle NLS you can consider it the same as a character set. You also have to distinguish between a FONT and a character set/codepage. A font is used by the OS to convert a numeric value into a graphical 'print’ on screen.  The Wingdings Font on Windows is the best example of a font where an ‘A’ is NOT shown as an ‘A’ on screen, but for the OS the numeric value represents an ‘A‘. So you don't SEE it as an ‘A’, but for Windows it's an ‘A’ and will be saved (or used) as an ‘A’.

    To better understand the explanation above, just open MS Word, choose the Wingdings Font, type your name (you will see symbols) and save this as html, if you open the html file with Notepad you will see that in the <style> section the fonts are declared and lower in the <body> section you will find your name in plain text but with style='font-family: Wingdings’ attribute. If you open it in Internet Explorer or Netscape, you will again see the Wingdings symbols. It's the presentation that changes, not the data itself.

     It's also possible that you don't see with a particular font, all the symbols defined in the codepage you are using, just because the creator of the FONT did not include a graphical representation for all the symbols in that font. That's why you sometimes get black squares on the screen if you change fonts. On Windows you can use the 'Character Map’ tool to see all the symbols defined in a font.

     

    Why Are There Different Character sets?

    Two main reasons:

    Historically vendors have defined different 'character sets’ for their hardware and software, mainly because there were no official standards.

    New character sets have been defined to support new languages. With an 8 bit character set, you are limited in the number of symbols you can support so there are different character sets for different written languages.

    What is the difference between 7 bit, 8 bit and Unicode Character sets?

    A 7 bit character set only knows 128 symbols (2^7)

    An 8 bit character set knows 256 symbols (2^8)

    Unicode (UTF-8) is a multibyte character set. Unicode has the capability to define over a million characters. For more information on Unicode see the white paper Oracle Unicode Database Support.

    How to choose the right database character set?

    A basic consideration for choosing a character set is to make sure it can handle any language that needs to be supported immediately and in the indeterminate future. Another overlooked consideration is to think about what applications and technologies you may want to utilize or interact with the database. Use locale builder (from Oracle Database 9i onwards) to view what characters are defined for a particular Oracle character set.

    Choosing Unicode as the database character set ensures a strong foundation for whatever is built into and on top of the database.Oracle recommends using Unicode for all new system deployment. Migrating legacy systems to Unicode is also recommended. Deploying your systems today in Unicode offers many advantages in usability, compatibility, and extensibility. Oracle's comprehensive support allows you to deploy high-performing systems faster and more easily while leveraging the true power of Unicode. Even if you don't need to support multilingual data today or have any requirement for Unicode, it is still likely to be the best choice for a new system in the long run and will ultimately save you time and money and give you competitive advantages.

    Posted Sep 17 2009, 09:24 AM by wicky with no comments
    Filed under:
  • 『娱乐八卦』[八卦江湖]陈鲁豫死去活来的瞬间(转载)

    Posted Sep 15 2009, 10:37 AM by wicky with no comments
    Filed under:
  • RIA项目失败的教训

    http://www.infoq.com/cn/news/2009/07/Lessons-to-Fail-RIA-Project

    EffectiveUI公司主席Anthony Franco最近做了一次名为“RIA项目失败的十种方式”的演讲,为想要RIA项目失败的人提供了十条建议。SAP AG的Gerd Waloszek则总结了“糟糕用户界面的18黄金法则”。

    以下是Franco提供的十条逆向建议,并解释了为何要避免它们,而应该如何去做:

    1. 如果你想失败,那就不要理解最终用户——70%的IT项目失败都是由于用户可接受性出了问题。
    2. 如果你想失败,那就相信开发人员能够正确的做出设计决定。开发人员被逼迫着做出糟糕的设计,因为他们的工作量是由其所完成的功能数量决定的。当一个项目将要接近截止日期时,开发人员就会关注于删除功能而不是从最终用户的角度思考。
    3. 如果你想失败,那就期望一个银弹式的设计。好主意是值得肯定的,但一个伟大的功能建议不应该取代优秀健康的UI设计。
    4. 如果你想失败,那就满足所有人的需求。“如果一个公司试图为所有人创造一个产品,那么最后不会适用于任何人”。
    5. 如果你想失败,那就启动项目然后忘却。在项目启动之后,产品需要更多的迭代以不断完善。
    6. 如果你想失败,那就不要定义成功。不定义成功意味着不知道目标是什么。
    7. 如果你想失败,那就避免冲突。冲突未必是坏事,因为“没有冲突就没有进步”。当屋子里的所有人都赞同某种看法时,那么就要提高警惕了。
    8. 如果你想失败,那就相信不需要推销自己的想法。利益相关者应该努力在组织内部推销自己的想法,但不要期望仅仅因为来源于你就会被接受。这需要准备回答类似下面的问题:投资回报率如何?优点是什么?为什么要现在做?如果不做会怎么样?
    9. 如果你想失败,那就追求完美。不应该一开始就把所有都计划好,并期望现实会按照计划行事,因为变化无处不在。
    10. 如果你想失败,那就重视过程甚于产品。这条建议可以改写为:“如果你想失败,那就不要冒险”。我们可以非常重视开发过程,但是“按时生产一个糟糕的产品毫无意义”,通过迭代的方法构建满意的产品更轻松一些。

    以下是Waloszek总结的糟糕用户界面18黄金法则,提供了负面的例子:

    1. 让客户忙于那些不必要的工作——让用户在某些控件填写数据,随后又提示他们不能在那里输入数据(比如,一个应用让你在假期或周末填写数据,随后又提示说你不能在那些天工作)。
    2. 不遵守标准——不把菜单条目放置在通常的类别和位置上(比如,在“编辑”菜单中放置“保存”按钮)。
    3. 让软件运行缓慢——有无数的可能性导致软件运行缓慢。比如,你可以在每个用户输入之后包含长时间的验证或者切换。或者你可以强制用户浏览一连串的对话框。
    4. 尽可能地使用缩写,特别是在有足够空间显示完整单词的情况下——使用“dat.”而不是“date”,“Tolky”而不是“Tolerance Key”,“NxOb”而不是“Next Object”,等等还有很多......
    5. 使用技术型语言指导用户——使用UTF-8格式发送URL(需要重启,在MS IE的高级设置里)
    6. 隐藏在用户看来重要和常用的功能——把其藏在用户永远找不到的菜单里。
    7. 让你的应用只支持鼠标——绝不提供任何键盘快捷键
    8. 使用你的应用成为一项挑战——即使用户操作会导致严重的后果也不加以提示。
    9. 脱离最终用户——许多用户有许多的选择,你只提供一个。这倒是可以更快更简单的实现。
    10. 宣扬糟糕的示例——只需要听从本页的其他黄金法则就可以实现。
    11. 花费大量精力设置糟糕的缺省参数:与用户的期望背道而驰,缺省配置极其糟糕、令人厌恶、无用——反正由你决定——在web表单上做缺省设置使用户收到不想要的新闻或者广告,散布他们的地址等等。
    12. 在每次系统重新恢复之后都破坏工作上下文——在系统重启之后取消之前选择的屏幕元素。
    13. 忽略让用户更方便的功能——让他们很辛苦——当用户需要在列表中添加条目时,只允许他们在列表末端插入条目,然后再让用户把条目移动到正确的位置。换句话说,没有提供额外的功能用于直接将条目插入到目标位置。为了增加点情趣,当用户直接把条目移动到目标位置时,应用提示一些伪造的错误,然后把条目插入到末尾。
    14. 不让用户中断消耗时间和/或消耗资源的进程——偷偷启动一个备份或者索引进程,让用户难以取消,也就是说,无视用户的鼠标点击和键盘操作。
    15. 应用不合逻辑——添加一个准备某操作的按钮使用户确认可以做该操作了。这里有一个真实例子:在许多电子邮件应用中,“转发”按钮实际上没有真正执行转发操作,而是做转发之前的准备工作(因为,我们不得不提供收件人地址)。
    16. 时不时的来一次系统崩溃或者让应用僵死——让编辑器或者编辑域在用户事先未预料的情况下僵死,以至于用户还没有来得及保存他们的工作成果,而频繁保存的习惯会浪费宝贵的系统资源。
    17. 尽可能的阻碍用户输入——页面加载也是阻碍用户输入的好机会。在等待的时候,用户可能会与室友聊天、读报或者盯着空屏幕发呆。
    18. 阻碍用户输入,即使没有必要——阻碍用户在图片浏览器更新缩略图的时候输入就是一个很好的例子——没有任何理由阻止用户滚动、选择图片或者发起操作。

    是否还有其他失败RIA项目的“优秀”建议,值得不惜一切代价避免呢?

    查看英文原文:“Good” Lessons on How To Fail a RIA Project

    Posted Aug 26 2009, 09:23 AM by wicky with no comments
    Filed under:
More Posts Next page »
Copyright SDT, 2006-2009. All rights reserved.