你好:这个死锁没办法完全避免,尽量的话在做事物提交的时候,提交完成后在进行其余的同一个表的操作,再就是insert、update等操作尽量能减少就减少。其实正常情况下是很少出现死锁的。
网站设计制作、做网站的关注点不是能为您做些什么网站,而是怎么做网站,有没有做好网站,给成都创新互联公司一个展示的机会来证明自己,这并不会花费您太多时间,或许会给您带来新的灵感和惊喜。面向用户友好,注重用户体验,一切以用户为中心。
关于硬件故障管理
现代数据中心管理灵活且不断发展。它的任务是推动业务目标并保证任务关键型负载可用,包括各种硬件和软件解决方案,这些方案可能过于复杂,难以有效管理。为了控制风险和满足苛刻的服务级别承诺,各种硬件和软件特性应运而生,从而可以帮助系统管理员监视系统运行状况、及早发现问题。
这些特性被称作故障管理,由多种解决方案和标准构成,旨在提供能够监视、管理、识别和解决那些困扰系统管理员的问题的工具。与数据中心最佳实践(如冗余和高可用性)相结合时,硬件故障管理特性提供强大的工具,可以提升效率、提高认识、降低风险并支持数据中心系统所担负的苛刻目标。
使用 IPMI 和 ipmitool
IPMI 是一个规范,最早于 1998 年由 Intel、Dell、HP 和 NEC 共同制定。其主要目的是提供一个访问系统信息的通用命令接口。它原本是设计成与管理软件无关的;但后来却常与系统特性结合使用。
IPMI 独立于操作系统运行,这意味着您可以“带外”方式或是在操作系统启动之前访问系统。这在操作系统或系统出现故障的情况下非常有用,因为您可以使用它提供的工具在传统系统管理功能不可用时收集关键信息。
IPMI 中有一些预定义的命令和接口可用于读取温度、电压、风扇速度、电源和网络设置。而且 IPMI 规范被设计成可扩展的。因此,厂商可以自定义和创建其他的命令和传感器。例如,Oracle Integrated Lights Out Manager (Oracle ILOM) 符合 IPMI 1.5 版和 2.0 版。HP 的 Integrated Lights-Out (iLO) 和 Dell 的 DRAC (Dell Remote Access Controller) 就是集成了 IPMI 或符合 IPMI 的方案。每个解决方案都提供了一组带外支持特性。这正是本规范的设计意图:提供通用的、跨平台的支持,同时让厂商能够定制自己的个性化解决方案的方法。
在 Oracle Linux 中,使用 ipmitool 实用程序管理和配置支持 IPMI 规范的设备。从 2.4 版开始,IPMI 支持已成为 Linux 内核的一部分。ipmitool 实用程序提供管理现场可更换部件 (FRU)、LAN 配置、传感器读取和远程机箱电源控制的功能。下一节将讨论使用 ipmitool中特性的安装和使用场景。
安装
第一步是在系统中安装 ipmitool。支持 IPMI 规范的系统中含有 IPMI 特性。这些系统都含有一个基板管理控制器 (BMC),它是 IPMI 架构的智能核心。使用 OpenIPMI 和 ipmitool,您可以与 BMC 直接连接并与 IPMI 规范实现的特性交互。
为了访问服务器的 IPMI 特性,本地工作站或管理计算机需要位于能访问具有 BMC 的系统的网络,且必须安装了 OpenIPMI 和 ipmitool工具。要安装这些工具,请转至服务器控制台并键入以下命令:
yum install ipmitool.x86_64 OpenIPMI.x86_64
然后,使用以下命令配置 ipmitool 以便在系统上使用并启动服务。启动服务后,它会加载 IPMI 内核并创建一个 /dev/ipmi0 设备。
chkconfig ipmi on
service ipmi start
还可以在其他含有 BMC 的 IPMI 系统上安装 ipmitool 和 OpenIPMI 软件包,这两个软件包提供配置 IPMI 设置的选项,我们在以下示例中将看到。
安装、配置并运行这些工具后,我们就可以与控制和监视系统的特性进行交互。我们来看看下面这些利用 ipmitool 和 Oracle Linux 的 IPMI 用例。
远程系统访问
IPMI 的一个特性是能够通过网络直接与系统相连。这个动作独立于目标系统上安装的任何操作系统,提供了一个非常有用的管理选项。它为您提供了与服务器 IPMI 接口的直接连接,让您可以远程执行 IPMI 命令。实际上,您可以使用该选项编写脚本,从而能够在一台管理计算机上控制无数台服务器。
要启用此特性,必须先完成几个步骤,比如设置口令以及为 BMC 所在服务器的 IPMI 接口添加 IP 地址。需要注意的是,许多服务器都有一个单独的远程管理以太网端口。查看您的硬件文档,了解有关具体服务器远程管理的更多信息。
通过网络访问 IPMI 的第一步是要为 BMC 所在的系统配置有效的 IP 地址。以下示例演示了如何使用 ipmitool 完成这一配置。(注:该示例使用 Oracle Sun Fire X4170 M2 服务器。)要使用 ipmitool 配置 IP 地址,请在服务器控制台使用以下命令:
ipmitool lan set 1 ipaddr 192.168.1.120
ipmitool lan set 1 netmask 255.255.255.0
ipmitool lan set 1 defgw ipaddr 192.168.1.1
设置完 IPMI 接口的 IP 地址之后,需要一个方法进行身份验证。在以下示例中,我们将口令改成 root 用户,从而允许使用 PASSW0rd 口令登录。
注意:我们不推荐使用该方法,此处仅用来举例。我们强烈推荐使用安全口令。
首先,我们需要列出用户以获得 ID 号,然后将使用该 ID 号更改口令。
[root@test1 ~]# ipmitool user list 1
ID Name Callin Link Auth IPMI Msg Channel Priv Limit
1 false false true NO ACCESS
2 root false false true ADMINISTRATOR
[root@test1 ~]# ipmitool user set password 2 PASSW0rd
一旦完成这些配置步骤后,您就可以通过向服务器远程发送 chassis status IPMI 请求来测试配置结果。系统将提示您输入所连接帐户的口令。如果一切配置正确无误,机箱状态将显示在本地命令行上。在您的管理系统命令行上,键入清单 1 所示的命令:
[root@mgmt-vm ~]# ipmitool -I lan -H 192.168.1.120 -U root -a chassis status
Password:
System Power : on
Power Overload : false
Power Interlock : inactive
Main Power Fault : true
Power Control Fault : false
Power Restore Policy : always-on
Last Power Event :
Chassis Intrusion : inactive
Front-Panel Lockout : inactive
Drive Fault : false
Cooling/Fan Fault : false
Oracle数据库无响应故障处理方式
Oracle数据库无响应故障,简单地讲就是数据库实例不能响应客户端发起的请求,客户端提交一个SQL后,就一直处于等待数据库实例返回结果的状态。更严重的现象是客户端根本不能连接到数据库,发起一个连接请求后,一直处于等待状态。Oracle数据库无响应故障怎么处理呢?下面跟我一起来学习Oracle数据库无响应故障的处理方法吧!
无响应的故障现象一般有以下几种:
1.Oracle的进程在等待某个资源或事件
这种现象一般可以从V$SESSION_WAT、V$LATCH、V$LATCHHOLDER等动态视图中检查进程正在等待的资源或事件,而被等待的资源或事件,一直都不能被获取,甚至是很长时间都不可获得。如果这个正在等待的进程持有了其他的资源,则会引起其他的进程等待,这样就很可能引起实例中大范围的会话发生等待。由于进程在等待资源或事件时,通常都处于SLEEP状态,消耗的CPU资源非常少(在等待latch时要稍微多消耗一些CPU资源),所以从OS来看,CPU的消耗并不高,甚至是非常低。
这种因为等待而引起的个别进程Hang,相对比较容易处理。
2. OracleProcess Spins
所谓Spin,就是指Oracle进程中的代码在执行某个过程时,陷入了循环。在V$SESSION视图中,往往可以看到Hang住的会话,一直处于“ACTIVE”状态。对于这样的会话,用“alter system kill session ‘sid,serial#’”命令也不能完全断开会话,会话只能被标记为“killed”,会话会继续消耗大量的CPU。进程Spins由于是在做循环,CPU的消耗非常大,从OS上明显可以看到这样的进程,通常会消耗整个CPU的资源。
而对于这样的Hang住的会话,处理起来相对比较复杂,并且为了从根本上解决问题,需要超过DBA日常维护所需要的技能。
从故障范围来看,无响应故障可以分为以下几种情况:
1. 单个或部分会话(进程)Hang住
这种情况属于小范围的故障,业务影响相对较小,一般来说只会影响业务系统的个别模块。在一个多应用系统的数据库上面,如果Hang住的会话比较多,则影响的可能是其中的一个应用系统。这里有一个例外,如果Hang住的进程是系统后台进程,如pmon、smon等,则影响的范围就非常大了,最终甚至会影响整个数据库及所有应用系统。还有值得注意的是,即使是少部分会话Hang住,也要及时处理,否则极有可能会扩散到整个系统。
2. 单个数据库实例Hang住
这种情况造成的影响非常大。在这个实例上的所有应用系统均受到严重影响,并且在找到根源并最终解决问题之前,数据库实例往往须要重启。
3. OPS或RAC中的多个实例或所有实例都Hang住
在这种情况下,即使是OPS或RAC,都已经没办法提供高可用特性了。使用这个数据库的所有应用系统将不能继续提供服务,这种情况往往须要重启。
无响应故障成因分析
Oracle数据库无响应,一般主要由以下几种原因引起:
1. 数据库主机负载过高,严重超过主机承受能力
比如应用设计不当,数据库性能低下,活动会话数的大量增加,导致数据库主机的负载迅速增加,数据库不能正常操作,并最终Hang住;主机物理内存严重不足,引起大量的换页,特别是在SGA中的内存被大量换出到虚拟内存时,数据库实例往往就会Hang住。
2. 日常维护不当、不正确的操作引起数据库Hang住
比如归档日志的存储空间满,导致数据库不能归档,引起数据库Hang住;在一个大并发的繁忙的系
统上,对DML操作比较多的大表进行move、增加外键约束等操作也可能使系统在短时间内负载大幅升高,并引起数据库系统Hang住;不正确的资源计划(Resource Plan)配置,使进程得不到足够的CPU等。
3. Oracle数据库的Bug
几乎每个版本都存在着会导致数据库系统Hang住的Bug,这些Bug会在一些特定的条件下触发,特别是在RAC数据库中,引起数据库Hang住的Bug比较多。
4. 其他方面的一些原因
比如在RAC数据库中,如果一个节点退出或加入到RAC的过程中,当进行Resource Reconfiguration时,会使系统冻结一段时间,也有可能使系统Hang住。
以上所描述的几种常见的会导致Oracle数据库实例Hang住的原因中,大部分的情况是可以避免的,只要维护得当,一般不会出现这种故障。对于Oracle数据库Bug所导致的数据库无响应故障,由于是在特定的情况下才会触发,所以如果能够尽量对数据库打上最新版本的补丁,并且熟悉当前版本中会导致系统Hang住的Bug以及触发条件,就能够最大限度地避免这种故障的发生,提高系统的可用性。
那么,在数据库Hang住的情况下,如何去分析并发现导致问题的根源?一方面,由于系统Hang住会导致业务系统不可用,为了能够尽快地恢复业务,须快速地判断问题所在,然后Kill掉引起故障的会话和进程,或者数据库实例不得不重启以迅速恢复业务;但另一方面,如果只是重启数据库或Kill会话和进程来解决问题,在很多情况下是治标不治本的办法,在以后故障随时可能会出现。如何在二者之间进行抉择呢?对于数据库Hang故障的处理,首先是尽可能地收集到系统Hang住时的状态数据,然后尽快地恢复业务,恢复业务后分析收集到的数据,找到数据库系统Hang住的真正原因,然后再进行相应的处理。下一节将详细描述数据库系统Hang住后的处理流程。
无响应故障处理流程
对于Oracle无响应故障的处理,我们可以按下图所示的流程进行。
值得注意的是,上图并不是一个完整的Oracle数据库故障处理流程图,只是处理Oralce数据库无响应这一类特定的故障的流程,只列出了针对这一特定类型故障处理时的关键处理点。不过既然是故障,所以这类故障的处理流程与其他故障的处理流程,有着非常相似的地方。
下面是整个流程的详细说明:
1. 在出现数据库无响应故障后,首先确认系统的影响范围,如上节所描述的',是部分业务系统或模块还是所有的业务系统都受影响,是不是整个实例或多个实例都无响应。同时应询问系统维护和开发人员,受影响的系统在出现故障前是否有过变动,包括主机硬件、操作系统、网络、数据库以及应用等。有时一个细小的变动就可能导致出现数据库Hang住这样严重的故障。曾经遇到一个库,应用只是修改了一个SELECT语句就导致了数据库Hang住。
2. 为了避免由于网络、数据库监听或客户端因素影响分析,建议都登录到主机上进行操作。
3. 如果主机不能登录(为了避免干扰流程主线,这里不讨论如网络问题这样也会导致不能连接的故障),尝试关闭出现问题的业务系统,甚至是所有的业务系统。如果关闭了所有的业务系统之后,仍然不能连接,则只有考虑重新启动数据库主机。在数据库主机重新启动后,使用操作系统工具或OSW等长期监控操作系统的资源使用,同时监控Oracle数据库的性能和等待等。
4. 登录上主机后,先用top、topas等命令简单观察一下系统。看看系统的CPU使用、物理内存和虚拟内存的使用、IO使用等情况。
5. 使用SQLPLUS连接数据库,如果不能连接,则只能从操作系统上观察系统中是否有异常的现象,比如占用CPU过高的进程。使用gdb、dbx等debugger工具对数据库进行system state dump;使用strace、truss等工具检查异常进程的系统调用;使用pstack、procstack等工具察看异常进程的call stack等。
6. 使用SQLPLUS连接上数据库后,进行hanganalyze、system state dump等操作;或检查等待事件、异常会话等正在执行的SQL等待。
7. 找到故障产生的原因,如果暂时找不到原因,尽量收集数据。
8.确良如果应用急须恢复,可通过Kill会话、重启数据库实例等方式,先恢复应用。
9. 根据最终诊断结果,对数据库升级打补丁,或者修改应用等方式从根本上解决问题。
怎样避免数据库出现无响应故障
作为Oracle数据库DBA,除了处理故障之外,更重要的是如何预防故障的发生。根据前面对数据库无响应故障的成因分析,在日常的维护工作中,须做到以下几点:
1. 进行正确的维护操作
很多的数据库无响应故障都是由于不正确的维护操作引起的。应避免在业务高峰期做大的维护操作,比如像move、加主外键约束等会长时间锁表的操作。如果的确需要,尽量使用正确的操作方法。比如用ONLINE方式重建索引;建主键、唯一键约束时先建索引,然后在建约束时指定新建的索引,等等。也就是保证系统的并发性、可伸缩性,避免系统串行操作的出现。
2. 优化应用设计,优化数据库性能
为避免性能问题导致在业务高峰期数据库不能及时有效处理来自业务的请求,甚至于完全Hang住。对于数据库中存在串行访问的部分进行优化,比如latch、enqueue,还包括不合理的sequence设计等。特别是在RAC数据库中,严重串行访问等待往往更容易引起严重的性能问题。优化应用设计,使数据库具有更好的可伸缩性和并行处理能力,能够有效地避免性能问题引起的数据库Hang住。
3. 利用监控系统随时监控系统负载
遇到系统负载过高,内存不足,OS中虚拟内存换页很频繁等情况时,及时采取措施;监控Oracle数据库的核心进程,如pmon、smon等,看是否有异常,如过高的CPU消耗。出现异常应立即处理;监控归档空间和日志切换;监控数据库中的等待事件,比如是否有大量的enqueue、log file switch (archiving needed)、resmgr:become active等待事件等。
4. 为数据库打上补丁
很多的无响应故障是由于Oracle的Bug引起的,数据库DBA应关注当前版本中有哪些Bug会导致数据库Hang住,尽量为数据库打上解决这些Bug的补丁。
;
一、使用工具:Oracle Solaris 、SUNW.HAStoragePlus。
二、配置方法及步骤:
1、注册 SUNW.HAStoragePlus (HASP) 资源类型。
phys-schost-1# /usr/cluster/bin/clrt register SUNW.HAStoragePlus
2、创建故障切换资源组。
phys-schost-1# /usr/cluster/bin/clrg create sol-kz-fz1-rg
3、创建一个 HAStoragePlus 资源来监视用作内核区域的引导或挂起设备的磁盘。
root@phys-schost-1:~# clrs create -t SUNW.HAStoragePlus -g sol-kz-fz1-rg \
-p GlobalDevicePaths=dsk/d7,dsk/d8 sol-kz-fz1-hasp-rs
root@phys-schost-1:~# /usr/cluster/bin/clrg online -emM -n phys-schost-1 \ sol-kz-fz1-rg
4、在 phys-schost-1 上创建并配置区域。必须确保引导和挂起设备位于共享磁盘上。为了配置双节点集群,在
phys-schost-1 上执行以下命令,然后将区域配置复制到
phys-schost-2。
root@phys-schost-1:~# zonecfg -z sol-kz-fz1 'create -b; set brand=solaris-kz;
add capped-memory;
set physical=2G; end; add device;
set storage=dev:did/dsk/d7; set bootpri=1; end; add suspend; set
storage=dev:did/dsk/d8; end; add anet; set lower-link=auto; end; set autoboot=false; add attr;
set name=osc-ha-zone; set type=boolean; set value=true; end;'
5、验证区域已配置。
phys-schost-1# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
- sol-kz-fz1 configured - solaris-kz excl
6、使用 zoneadm 安装区域,然后引导区域。
root@phys-schost-1:~# zoneadm -z sol-kz-fz1 install
Progress being logged to /var/log/zones/zoneadm.20140829T212403Z.sol-kz-fz1.install
pkg cache: Using /var/pkg/publisher.
Install Log: /system/volatile/install.4811/install_log
AI Manifest: /tmp/zoneadm4203.ZLaaYi/devel-ai-manifest.xml
SC Profile: /usr/share/auto_install/sc_profiles/enable_sci.xml
Installation: Starting ...
Creating IPS image
Installing packages from:
solaris
origin:
ha-cluster
origin:
The following licenses have been accepted and not displayed.
Please review the licenses for the following packages post-install:
consolidation/osnet/osnet-incorporation
Package licenses may be viewed using the command:
pkg info --license pkg_fmri
DOWNLOAD PKGS FILES XFER (MB) SPEED
Completed 482/482 64261482/482 64261/64261 544.1/544.1 1.9M/s
PHASE ITEMS
Installing new actions 87569/87569
Updating package state database Done
Updating package cache 0/0
Updating image state Done
Creating fast lookup database Done
Installation: Succeeded
Done: Installation completed in 609.014 seconds.
7、验证区域是否已成功安装并引导。
phys-schost-1# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
- sol-kz-fz1 installed - solaris-kz excl
8、在另一个窗口中,登录区域控制台并引导区域。按照各系统配置交互屏幕上的提示配置区域。
phys-schost-1# zlogin -C sol-kz-fz1
phys-schost-1# zoneadm -z sol-kz-fz1 boot
9、关闭区域并将资源组切换到资源组节点列表中的另一个节点。
phys-schost-1# zoneadm -z sol-kz-fz1 shutdown
phys-schost-1# zoneadm -z sol-kz-fz1 detach -F
phys-schost-1# /usr/cluster/bin/clrg switch -n phys-schost-2 sol-kz-fz1-rg
phys-schost-1# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / solaris shared
- sol-kz-fz1 configured - solaris-kz excl
10、将区域配置复制到第二个节点,使用配置文件在第二个节点上创建内核区域。
root@phys-schost-1:~# zonecfg -z sol-kz-fz1 export -f \
/var/cluster/run/sol-kz-fz1.cfg
root@phys-schost-1:~# scp /var/cluster/run/sol-kz-fz1.cfg phys-schost- \
2:/var/cluster/run/
root@phys-schost-1:~# rm /var/cluster/run/sol-kz-fz1.cfg
root@phys-schost-2:~# zonecfg -z sol-kz-fz1 -f /var/cluster/run/sol-kz-\
fz1.cfg
root@phys-schost-2:~# rm /var/cluster/run/sol-kz-fz1.cfg
11、附加区域并验证区域是否可以在第二个节点上引导。从另一个会话登录,确保区域正常引导。
root@phys-schost-2:~# zoneadm -z sol-kz-fz1 attach -x force-takeover
root@phys-schost-2:~# zoneadm -z sol-kz-fz1 boot
root@phys-schost-2:~# zlogin -C sol-kz-fz1
12、关闭并分离区域。
root@phys-schost-2:~# zoneadm -z sol-kz-fz1 shutdown
root@phys-schost-2:~# zoneadm -z sol-kz-fz1 detach -F
13、安装故障切换区域代理(如果尚未安装)。
root@phys-schost-1# pkg install ha-cluster/data-service/ha-zones
root@phys-schost-2# pkg install ha-cluster/data-service/ha-zones
14、要从任何一个节点创建资源,请编辑 sczbt_config 文件并设置参数,如下所示。
root@phys-schost-2:~# clrt register SUNW.gds
root@phys-schost-2:~# cd /opt/SUNWsczone/sczbt/util
root@phys-schost-2:~# cp -p sczbt_config sczbt_config.sol-kz-fz1-rs
root@phys-schost-2:~# vi sczbt_config.sol-kz-fz1-rs
RS=sol-kz-fz1-rs
RG=sol-kz-fz1-rg
PARAMETERDIR=
SC_NETWORK=false
SC_LH=
FAILOVER=true
HAS_RS=RS=sol-kz-fz1-hasp-rs
RG=sol-kz-fz1-rg
Zonename="sol-kz-fz1"
Zonebrand="solaris-kz"
Zonebootopt=""
Milestone="svc:/milestone/multi-user-server"
LXrunlevel="3"
SLrunlevel="3"
Mounts=""
Migrationtype="warm"
15、要配置区域引导资源,请在区域引导配置文件中设置参数。
root@phys-schost-2:~# ./sczbt_register -f ./sczbt_config.kz
sourcing ./sczbt_config.kz
Registration of resource kz-rs succeeded.
root@phys-schost-2:~# /usr/cluster/bin/clrs enable sol-kz-fz1-rs
16、检查资源组和资源的状态。
root@phys-schost-2:~# /usr/cluster/bin/clrs status -g sol-kz-fz1-rg
=== Cluster Resources ===
Resource Name Node Name State Status Message
------------------- ------------- ----- -------------------
sol-kz-fz1-rs phys-schost-1 Online Online - Service is online.
phys-schost-2 Offline Offline
sol-kz-fz1-hasp-rs phys-schost-1 Online Online
phys-schost-2 Offline Offline
root@phys-schost-2:~#
17、使用 zlogin -C sol-kz-fz1
命令登录,验证该区域是否成功引导,然后切换到另一个节点以测试故障切换。
root@phys-schost-2:~# /usr/cluster/bin/clrg switch -n phys-schost-1 sol-kz-fz1-rg
root@phys-schost-2:~# /usr/cluster/bin/clrs status -g sol-kz-fz1-rg
=== Cluster Resources ===
Resource Name Node Name State Status Message
------------------- ---------- ----- -------------------
sol-kz-fz1-rs phys-schost-1 Online Online
phys-schost-2 Offline Offline
ha-zones-hasp-rs phys-schost-1 Online Online
phys-schost-2 Offline Offline
root@phys-schost-2:~#
三、注意事项:在故障区域配置中,区域的 zonepath 必须位于高可用文件系统上。
如何配置才能使客户端连到数据库:
要使一个客户端机器能连接oracle数据库,需要在客户端机器上安装oracle的客户端软件,唯一的例外就是java连接数据库的时候,可以用
jdbc
thin模式,不用装oracle的客户端软件。加入你在机器上装了oracle数据库,就不需要在单独在该机器上安装oracle客户端了,因为装
oracle数据库的时候会自动安装oracle客户端。
用过sql
server数据库然后又用oracle的新手可能会有这样的疑问:问什么我用sql server的时候不用装sql
server的客户端呢?原因很简单,sql server也是microsoft的,它在操作系统中集成了sql
server客户端,如果microsoft与oracle有协议,将oracle客户端也集成到操作系统中,那我们也就不用在客户端机器装oracle
客户端软机就可访问数据库了,不过,这好像是不可能实现的事情。
也有的人会问:为什么在sql
server中没有侦听端口一说,而在oracle中要配置侦听端口?其实sql
server中也有侦听端口,只不过microsoft将侦听端口固定为1433,不允许你随便改动,这样给你一个错觉感觉sql
server中没有侦听端口,咳,microsoft把太多的东西都封装到黑盒子里,方便使用的同时也带来的需要副作用。而oracle中的侦听端口直接
在配置文件中,允许随便改动,只不过无论怎样改动,要与oracle服务器端设置的侦听端口一致。
好,言归正传,我们如何做才能使客户端机器连接到oracle数据库呢?
A. 安装相关软件
B. 进行适当的配置
A.在适当的位置安装适当的软件:
在客户端机器:
1.在客户端机器上安装ORACLE的Oracle Net通讯软件,它包含在oracle的客户端软件中。
2.正确配置了sqlnet.ora文件:
NAMES.DIRECTORY_PATH = (TNSNAMES, ….)
NAMES.DEFAULT_DOMAIN=DB_DOMAIN
一般情况下我们不用NAMES.DEFAULT_DOMAIN参数。如果想不用该参数用#注释掉或将该参数删除即可,对于NAMES.DIRECTORY_PATH参数采用缺省值即可,对于NAMES.DEFAULT_DOMAIN参数有时需要注释掉,在下面有详细解释。
3.正确配置了tnsname.ora文件
在服务器端机器:
1.保证listener已经启动
2.保证数据库已经启动。
如果数据库没有启动,用:
Oracle 9i:
dossqlplus “/ as sysdba”
sqlplus startup
Oracle 8i:
dossvrmgrl
svrmgrlconnect internal
svrmgrlstartup
命令启动数据库
如果listener没有启动,用:
lsnrctl start [listener name]
lsnrctl status [listener name]
命令启动listener
B.进行适当的配置
如何正确配置tnsname.ora文件:
可
以在客户端机器上使用oracle Net Configuration Assistant或oracle Net
Manager图形配置工具对客户端进行配置,该配置工具实际上修改tnsnames.ora文件。所以我们可以直接修改tnsnames.ora文件,
下面以直接修改tnsnames.ora文件为例:
该文件的位置为: …\network\admin\tnsnames.ora (for windows)
…/network/admin/tnsnames.ora (for unix)
此处,假设服务器名为testserver,服务名为orcl.testserver.com,使用的侦听端口为1521,则tnsnams.ora文件中的一个test网络服务名(数据库别名)为:
test =
(DESCRIPTION=
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST=testserver)(PORT=1521))
)
(CONNECT_DATA=(SERVICE_NAME=orcl.testserver.com)
)
)
此处的笑脸为)。
红色的内容为需要根据实际情况修改的内容,现解释如下:
PROTOCOL:客户端与服务器端通讯的协议,一般为TCP,该内容一般不用改。
HOST:数据库侦听所在的机器的机器名或IP地址,数据库侦听一般与数据库在同一个机器上,所以当我说数据库侦听所在的机器一般也是指数据库所在的机
器。在UNIX或WINDOWS下,可以通过在数据库侦听所在的机器的命令提示符下使用hostname命令得到机器名,或通过ipconfig(for
WINDOWS) or ifconfig(for
UNIX)命令得到IP地址。需要注意的是,不管用机器名或IP地址,在客户端一定要用ping命令ping通数据库侦听所在的机器的机器名,否则需要在
hosts文件中加入数据库侦听所在的机器的机器名的解析。
PORT:数据库侦听正在侦听的端口,可以察看服务器端的listener.ora文件或在数据库侦听所在的机器的命令提示符下通过lnsrctl status [listener name]命令察看。此处Port的值一定要与数据库侦听正在侦听的端口一样。
SERVICE_NAME:在服务器端,用system用户登陆后,sqlplus show parameter service_name命令察看。
如何利用配置的网络服务名连接到数据库:
用sqlplus程序通过test网络服务名进行测试,如sqlplus system/manager@test。
如果不能连接到数据库,则在tnsname.ora文件中的test网络服务名(net
service)后面加上sqlnet.ora文件中NAMES.DEFAULT_DOMAIN参数的值,此处我的参数值为
testserver.com,将其加到网络服务名后面,修改后的tnsname.ora中关于该网络服务名的内容为:
什么情况下会引起oracle自动设置NAMES.DEFAULT_DOMAIN参数?
出现这种情况的典型环境为windows的客户端的‘我得电脑à属性à计算机名à更改à其它…à此计算机的主DNS后缀’中设置了‘primary
dns
suffix’,因为在这种情况下安装客户端时,会在sqlnet.ora文件中自动设置NAMES.DEFAULT_DOMAIN参数,或许当把计算机
加入域中安装oracle客户端时也会出现这种情况,有条件的话大家可以试一下。
我在设置oracle的客户端时一般手工修改tnsnames.ora文件,但是还有许多人喜欢用图形工具配置,该图形工具最终还是修改tnsnames.ora文件,但是它有时会引起其它的问题:
在用oracle的图形配置软件'net assistant'或‘Net Configuration
Assistant’配置网络服务名时,假如已经设置了‘primary dns
suffix’,但是在图形配置软件中写的网络服务名的名字中没有‘primary dns
suffix’,如只是写了test,则图形配置软件会自动在后面加上‘primary dns
suffix’,使之变为test.testserver.com,并存在tnsnames.ora中,而不管你的sqlnet.ora文件中是否有
NAMES.DEFAULT_DOMAIN参数。此时,用图形工具进行测试连接是通过的,但是假如此时sqlnet.ora文件中没有
NAMES.DEFAULT_DOMAIN参数,则你在使用网络服务名时应该使用在tnsnames.ora中的
test.testserver.com,而不是你在图形配置软件中键入的test。解决的办法为:
1可以在sqlnet.ora文件中设置NAMES.DEFAULT_DOMAIN= testserver.com,这时你可以用test或test.testserver.com连接数据库
2在sqlnet.ora文件中不设置NAMES.DEFAULT_DOMAIN参数,在tnsnames.ora文件中将test.testserver.com中的.testserver.com去掉,这时你可以用test连接数据库。
关于为什们在网络服务名后面加db_domain参数,需要了解sql*plus连接数据库的原理,我在后面解决12154常见故障中给出了详细的说明。
如果上面的招数还不奏效的话,只好用一下乾坤大挪移了。
将客户端的网络服务名部分
test.testserver.com =
(DESCRIPTION=
(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver)(PORT=1521))
)
(CONNECT_DATA=(SERVICE_NAME=orcl.testserver.com)
)
)
此处的笑脸为)。
拷贝到服务器的tnsnames.ora文件中。然后再服务器端用sqlplus system/manager@test.testserver.com连接到数据库。
如果能连接成功,说明你的客户端与服务器端的网络有问题。
如果连接不成功,用前面的部分检查网络服务名部分部分是否正确,如果确信网络服务名部分正确而且所有的客户端都连不上数据库则可能为系统TCP/IP或Oracle系统有问题,建议重新安装数据库。
该错误表示用于连接的网络服务名在tnsnames.ora文件中不存在,如上面的tnsnames.ora中的网络服务名只有test,假如用户在连接时用sqlplus system/manager@test1则就会给出TNS-12154错误。
要注意的是,有时即使在tnsnames.ora文件中有相应的网络服务名,可是用该网络服务名连接时还会出错,出现这种情况的典型配置如下(在客户端的机器上):
sqlnet.ora文件:
NAMES.DIRECTORY_PATH = (TNSNAMES, ….)
NAMES.DEFAULT_DOMAIN = server.com
tnsnames.ora文件:
test =
(DESCRIPTION=
(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=testserver)(PORT=1521))
)
(CONNECT_DATA=(SERVICE_NAME=orcl.testserver.com)
)
)
此处的笑脸为)。
sql*plus运行基本机理:
在用户输入sqlplus system/manager@test后,sqlplus程序会自动到sqlnet.ora文件中找NAMES.DEFAULT_DOMAIN参数,假 如该参数存在,则将该参数中的值取出,加到网络服务名的后面,
即此例中你的输入由sqlplus system/manager@test自动变为sqlplus system/manager@test.server.com
,然后再到tnsnames.ora文件中找test.server.com网络服务名,这当然找不到了,因为该文件中只有test网络服务名,所以报
错。解决的办法就是将sqlnet.ora文件中的NAMES.DEFAULT_DOMAIN参数注释掉即可,如
#NAMES.DEFAULT_DOMAIN =
server.com。假如NAMES.DEFAULT_DOMAIN参数不存在,则sqlplus程序会直接到tnsnames.ora文件中找
test网络服务名,然后取出其中的host,port,tcp,service_name,利用这些信息将连接请求发送到正确的数据库服务器上。
另外原则上tnsnames.ora中的配置不区分大小写,但是我的确遇到区分大小写的情况,所以最好将使用的网络服务与tnsnames.ora中配置的完全一样。
ORA-12514: TNS:listener could not resolve SERVICE_NAME given in connect Descriptor.
该错误表示能在tnsnames.ora中找到网络服务名,但是在tnsnames.ora中指定的SERVICE_NAME与服务器端的SERVICE_NAME不一致。解决的办法是修改tnsnames.ora中的SERVICE_NAME。
易混淆术语介绍:
Db_name:对一个数据库(Oracle database)的唯一标识,该数据库为第一章讲到的Oracle
database。这种表示对于单个数据库是足够的,但是随着由多个数据库构成的分布式数据库的普及,这种命令数据库的方法给数据库的管理造成一定的负
担,因为各个数据库的名字可能一样,造成管理上的混乱。为了解决这种情况,引入了Db_domain参数,这样在数据库的标识是由Db_name和
Db_domain两个参数共同决定的,避免了因为数据库重名而造成管理上的混乱。这类似于互连网上的机器名的管理。我们将Db_name和
Db_domain两个参数用’.’连接起来,表示一个数据库,并将该数据库的名称称为Global_name,即它扩展了Db_name。
Db_name参数只能由字母、数字、’_’、’#’、’$’组成,而且最多8个字符。
Db_domain:定义一个数据库所在的域,该域的命名同互联网的’域’没有任何关系,只是数据库管理员为了更好的管理分布式数据库而根据实际情况决定的。当然为了管理方便,可以将其等于互联网的域。
Global_name:对一个数据库(Oracle
database)的唯一标识,oracle建议用此种方法命令数据库。该值是在创建数据库是决定的,缺省值为Db_name.
Db_domain。在以后对参数文件中Db_name与Db_domain参数的任何修改不影响Global_name的值,如果要修改
Global_name,只能用ALTER DATABASE RENAME GLOBAL_NAME TO
db_name.db_domain命令进行修改,然后修改相应参数。
Service_name:该参数是oracle8i新引进的。在8i以前,我们用SID来表示标识数据库的一个实例,但是在Oracle的并行环境中,
一个数据库对应多个实例,这样就需要多个网络服务名,设置繁琐。为了方便并行环境中的设置,引进了Service_name参数,该参数对应一个数据库,
而不是一个实例,而且该参数有许多其它的好处。该参数的缺省值为Db_name.
Db_domain,即等于Global_name。一个数据库可以对应多个Service_name,以便实现更灵活的配置。该参数与SID没有直接关
系,即不必Service name 必须与SID一样。
Net service name:网络服务名,又可以称为数据库别名(database alias)。是客户端程序访问数据库时所需要,屏蔽了客户端如何连接到服务器端的细节,实现了数据库的位置透明的特性。
在故障发生时,尝试用下面的语句抓取数据库引起故障的点。
/*********************************************************************************************/
在oracle中监控死锁
/*********************************************************************************************/
SELECT sn.username,
m.SID,
sn.SERIAL#,
m.TYPE,
DECODE(m.lmode,
0,
'None',
1,
'Null',
2,
'Row Share',
3,
'Row Excl.',
4,
'Share',
5,
'S/Row Excl.',
6,
'Exclusive',
lmode,
LTRIM(TO_CHAR(lmode, '990'))) lmode,
DECODE(m.request,
0,
'None',
1,
'Null',
2,
'Row Share',
3,
'Row Excl.',
4,
'Share',
5,
'S/Row Excl.',
6,
'Exclusive',
request,
LTRIM(TO_CHAR(m.request, '990'))) request,
m.id1,
m.id2
FROM v$session sn, v$lock m
WHERE (sn.SID = m.SID AND m.request != 0) --存在锁请求,即被阻塞
OR (sn.SID = m.SID --不存在锁请求,但是锁定的对象被其他会话请求锁定
AND m.request = 0 AND lmode != 4 AND
(id1, id2) IN (SELECT s.id1, s.id2
FROM v$lock s
WHERE request != 0
AND s.id1 = m.id1
AND s.id2 = m.id2))
ORDER BY id1, id2, m.request;
/*********************************************************************************************/
定位引起oracle死锁的sql
/*********************************************************************************************/
select sql_text from v$sql where hash_value in
(select sql_hash_value from v$session where sid in
(select session_id from v$locked_object))
/*********************************************************************************************/
下面的SQL查询可以用于确定锁住数据库对象的锁:
/*********************************************************************************************/
select
c.owner,
c.object_name,
c.object_type,
b.sid,
b.serial#,
b.status,
b.osuser,
b.machine
from
v$locked_object a ,
v$session b,
dba_objects c
where
b.sid = a.session_id
and
a.object_id = c.object_id;
/*********************************************************************************************/
显示哪些会话被锁住
/*********************************************************************************************/
/* showlock.sql */
COLUMN o_name format a10
COLUMN lock_type format a20
COLUMN object_name format a15
SELECT RPAD (oracle_username, 10) o_name, session_id SID,
DECODE (locked_mode,
0, 'None',
1, 'Null',
2, 'Row share',
3, 'Row Execlusive',
4, 'Share',
5, 'Share Row Exclusive',
6, 'Exclusive'
) lock_type,
object_name, xidusn, xidslot, xidsqn
FROM v$locked_object, all_objects
WHERE v$locked_object.object_id = all_objects.object_id;
/*********************************************************************************************/
显示所有的TM和TX锁
/*********************************************************************************************/
/* showalllock.sql */
SELECT SID, TYPE, id1, id2,
DECODE (lmode,
0, 'None',
1, 'Null',
2, 'Row share',
3, 'Row Exclusive',
4, 'Share',
5, 'Share Row Exclusive',
6, 'Exclusive'
) lock_type,
request, ctime, BLOCK
FROM v$lock
WHERE TYPE IN ('TX', 'TM');
/*********************************************************************************************/
在Oracle数据库中,可以通过kill session的方式来终止一个进程,其基本语法结构为:
被kill掉的session,状态会被标记为killed,Oracle会在该用户下一次touch时清除该进程.
我们发现当一个session被kill掉以后,该session的paddr被修改,如果有多个session被kill,那么多个session
的paddr都被更改为相同的进程地址:
/*********************************************************************************************/
alter system kill session 'sid,serial#' ;
/*********************************************************************************************/
在oracle中kill掉的进程有时还需要等待pmon回滚数据库已经占有的资源
有时候我们需要使用下面的脚本找出那些已经在oracle中kill掉的进程,在操作系统中在kill一次
/*********************************************************************************************/
select p.addr from v$process p where pid 1
minus
select s.paddr from v$session s;
$ kill -9 paddr