关于PHP连接ORACLE问题(06年自己写…

来源:互联网 发布:销售月数据分析表格 编辑:程序博客网 时间:2024/04/28 22:09
 关于PHP连接ORACLE问题
  网络上有关PHP连接ORACLE的文章很多,但往往不够全面。一般只能解决部分问题, 本人结合实践,将全部过程写下来供各位参考
  OS:bluepoint2.0
  Java: jre118_v3-glibc-2.1.3.tar
  Oracle: oracle8161.tar
  这个网站可以下载多个版本的oracle http://219.139.108.138/UnixSoft/Oracle/
  至于JDK可以在这里下:
  http://mirrors.ibiblio.org/pub/mirrors/blackdown/
  bluepoint2.0就比较不好找了,我有ISO景象文件,不知那位可以提供FTP空间,不过其他的版本的linux问题也应该不大。
  一、ORACLE的安装
  网上关于ORACLE的安装的文章很多,如果在redhat7.1(类似内核的发行版)或以上的版本要安装ORACLE8i要解决glibc 兼容问题。bluepoint2.0与oracle816的Glibc库也不兼容但只需直接安装以下几个包就可以了:glib-1.2.6-3.i386.rpm glib10-1.0.6-6.i386.rpm
  glibc-2.1.3-15.i386.rpm glibc-devel-2.1.3-15.i386.rpm
  glibc-profile-2.1.3-15.i386.rpm glib-devel-1.2.6-3.i386.rpm。
  (这些包可以在redhat6.2的光盘中获得),不必安装glibc-2.1.3-stubs.tar.gz补丁,也无须改变gcc,ld等接连。具体的安装过程就不在这里讲了,只贴出我的环境,这个在下面的叙述中有用:
  #------------------------------------------------------------------------
  
  # Setup ORACLE environment 
  
  #------------------------------------------------------------------------
  ORACLE_HOME=/home/oracle/OraHome1 export ORACLE_HOME 
  ORACLE_SID=orcl export ORACLE_SID 
  ORACLE_TERM=xterm export ORACLE_TERM
  ORACLE_OWNER=oracle8 export ORACLE_OWNER 
  TNS_ADMIN=/home/oracle/config/8.1.6 export TNS_ADMIN
  CLASSPATH=$ORACLE_HOME/jdbc/lib/classes111.zip:$CLASSPATH export CLASSPATH 
  LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH
  NLS_LANG="SIMPLIFIED CHINESE"_CHINA.ZHS16GBK export NLS_LANG 
  # Set up the search paths:
  PATH=$PATH:/usr/local/jre/bin:bin:/sbin:/usr/sbin:$ORACLE_HOME/bin
  PATH=$PATH:/usr/local/sbin:/usr/bin/X11:. export PATH 
  HOSTNAME =.Cs163,这个在tnsnames.ora等文件配置中也有用。
  在建库中名字选为ORACLE8,还有个问题,就是字符集选 ZHS16GBK,如果选择默认的US7ASCII,在windows客户端就会有中文显示问题,选了ZHS16GBK那就要在bash_profile设置NLS_LANG="SIMPLIFIED CHINESE"_CHINA.ZHS16GBK export NLS_LANG 环境变量,这样在linux服务器端就可以正确中文显示问题了ZHS16GBK,当然前提是你得搞定linux中文问题。
  如果建库时用了US7ASCII,在服务端中文没问题,但windows客户端就麻烦了,注册表改为和服务端一致即(Hkey_Local_machine\Software\Oracle\Home0\NLS_Lang American.America.US7ASCII)甚至无法登陆,解决办法就是用ALTER DATABASE改变数据库的字符集,当然这么做是有风险的,一般不提倡,不过我就是这么干过滴,以下是我的做法:
  修改server端字符集(不建议使用) 
    在oracle 8之前,可以用直接修改数据字典表props$来改变数据库的字符集。但oracle8之后,至少有三张系统表记录了数据库字符集的信息,只改props$表并不完全,可能引起严重的后果。正确的修改方法如下: 
  $sqlplus /nolog 
    SQL>conn as sysdba; 
    若此时数据库服务器已启动,则先执行SHUTDOWN IMMEDIATE命令关闭数据库服务器,然后执行以下命令: 
    SQL>STARTUP MOUNT; 
    SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION; 
    SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0; 
    SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0; 
    SQL>ALTER DATABASE OPEN; 
    SQL>ALTER DATABASE CHARACTER SET ZHS16GBK; 
    SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK; 
    SQL>SHUTDOWN IMMEDIATE; 
  SQL>STARTUP
  感觉有点离题,浪我们言归正传吧
  二、apache和PHP的安装
  以root用户登录,#mkdir /www(这只是我的做法,你也可以mkdir /dog /pig之类)。#cd /www
  从网络下载apache和php的源代码,并把他们考到/www,
  apache官方网站http://archive.apache.org/dist/httpd/
  php官方网站:http://www.php.net/releases.php
  我用的是apache_1.3.36,php-4.1.2
  #tar xvzf apache_1.3.36.tar.gz
  #tar xvzf php-4.1.2.tar
   #cd /www/apache_1.3.36
   #./configure --prefix=/www 
   #cd /www/php-4.1.2
   #configure --with-apache=../apache_1.3.36 
  --with-oracle=/home/oracle/OraHome1
  --with-oci8=/home/oracle/ OraHome1
  --with-mysql =/usr
  --enable-url-includes
  --enable-sockets
  --enable-track-vars 
  --disable-debug 
  注意这里要根据各自的安装目录来配置
   #make 
   #make install 
   #cp ./php.ini-dist /usr/local/lib/php.ini
   这样就完成了对php的配置和安装,下面继续安装apache 
  #cd /www/apache_1.3.33
  #./configure --prefix=/www --enable-module=all 
   --activate-module=src/modules/php4/libphp4.a 
  有文章里写成--activate-module=./src/modules/php4/libphp4.a
  以我自己的经历,这样做configure会失败。
  #make 
  #make install 
   这样就完成了apache的安装,此时需要编辑/www/conf/httpd.conf文件,加上php4的支持。 由于我们在 编译PHP时已经静态支持PHP4模块,因此无须加LoadModule php4_module lib/apache/libphp4.so 
  之类的模块装入语句,加了http反而不能正确启动。但必须加上
  AddType application/x-httpd-php .php .phtml 
  AddType application/x-httpd-php-source .phps
  否则apache无法正确识别PHP后缀。
  /www/conf/httpd.conf很重要,下面解决ORACLE连接也要设置该文件。
  下面就可以先测试一下了:
  先启动http服务:/www/bin/apachectl start
  在windows客户端打开IE,在地址栏输入http://you_ip_address/
  可以看到Apache Web Server 已經安裝成功的一个欢迎页面,
  在测试php:以root登陆,#vi /www/htdocs/phpinfo.php 
  输入以下内容:
   <?php 
   phpinfo(); 
  ?>
  :wq退出。
  在IE地址栏输入http://you_ip_address/ phpinfo.php,可以看到一系列的表格,是关于我们安装的PHP的信息,说明PHP没问题。
  测试php和oracle的连接:
  同样在/www/htdocs/目录下创建ora1.php, 内容如下:
   <?php 
   $conn=OCILogon("scott","tiger","localdb"); 
   if($conn) 
   echo "Oracle connect successfully!";
    
  else echo "Oracle connect failed!"; 
    
  ?> 
  在IE地址栏输入http://you_ip_address/ phpinfo.php
  如果你能看到Oracle connect successfully,那恭喜你成功了,也就不必再看我下面的这些废话了。通常你不可能有这么好的运气,一般会出现:
  Warning: _oci_open_server: ORA-12541: TNS:no listener in /www/htdocs/ora1.php on line 2
  Oracle connect failed!
  Warning: _oci_open_server: Connection Failed: Error while trying to retrieve text for error ORA-12546
   Warning: _oci_open_server: TNS-12154 (ORA-12154):TNS:could not resolve service name 
  之类的出错信息。要解决这个问题就比较复杂了,要从unix/linux访问控制,TSN连接等方面入手去分析。有人认为这和环境变量有关,加了一大堆putenv之类的,其实没什么大用。
  我们再来次试验将$conn=OCILogon("scott","tiger","localdb");
  改为conn=OCILogon("scott","tiger");然后打开文件
  /www/conf/httpd.conf ,将其中的User nobody,Group nobody,改为User Oracle,Group dba。再来试试看,应该就能成功,当然你首先是要启动http及数据库实例。
  启动数据库有多种做法,这里用SVRMGR工具:
  以oracle用户登陆linux
  oracle$svrmgrl
  SVRMGR>connect internal
  SVRMGR>startup
  不过这样做好象不是很好(安全性是不是会有问题,我也不太知道),而且我们还不知道这样做会成功的道理。所以本文还是要继续写下去。
  三、Oracle访问和TNS配置
  要真正明白这个问题估计要写本书了,这里只提及对本问题最重要的一些内容:
  支持网络连接的服务类型有dedicated方式,MTS方式。Dedicated是专用方式,MTS是共享方式,可用select server from v$session;来确定你的服务类型,不过这个和我们没有大的关系,只在配置tnsnames.ora用到一点。
  下面要澄清一个比较重要的事情:
  用户连接到Oracle 服务有两种情形:
  1. Oracle本地用户连接数据库
  这种情况无须启用listener进程,也用不到listener.ora、sqlnet.ora, tnsnames.ora等配置文件,连接的格式为:
  sqlplus scott/tiger。
  非oracle用户要连接成功的话,还需要设置好oracle环境和确定对$ORACLE_HOME有访问权限。
  2. 远程用户连接数据库服务器(TNS连接)
  这种情况须启用listener进程,在用lsnrctl start启用listener进程前还需要在服务器配置好listener.ora文件.
  连接的格式为:
  sqlplus scott/tiger@localdb
  当然要连接成功在客户机端还要做很多事情:在客户端机器上安装ORACLE的Oracle Net通讯软件,正确配置sqlnet.ora, tnsnames.ora文件。
  如果本地用户一定要以TNS连接的方式,也不是不可以,但需要在服务器端同时配置listener.ora、sqlnet.ora、 tnsnames.ora。listener.ora给listener进程用,后两个给本地用户连接时查询服务名用,这里的localdb是我在tnsnames.ora中配的服务名。(不过有个问题很奇怪现在还不明白:在sqlnet.ora、 tnsnames.ora 不配置情况下, svrmgrl中用connect internal无须输入密码,但配了以后却要求输入orcle用户的linux帐户密码)
  
  为了说明这三个文件的配置方法,先说明以下的概念:
  主机识别:在/etc/hosts中
  数据库识别:在/etc/oratab中
  服务识别:$ORACLE_HOME/network/admin/tnsnames.ora
  默认的情况其他两个配置也放在这里,当然你可以用环境变量TNS_ADMIN来设置新的路径,即便你设置了TNS_ADMIN,但$ORACLE_HOME/network/admin这个路径也还是能被识别。
  下面边贴我的这三个配置文件边来分析其意义:
  1.listener.ora
  LISTENER =
   (DESCRIPTION =
   (ADDRESS (PROTOCOL TCP)(HOST .cs163)(PORT 1521))
   )
  
  SID_LIST_LISTENER =
   (SID_LIST =
   (SID_DESC =
   (GLOBAL_DBNAME Oracle8)
   (ORACLE_HOME /home/oracle/OraHome1)
   (SID_NAME ORCL)
   )
   )
  (PROTOCOL TCP)(HOST .cs163)(PORT 1521),分别是协议,主机名在/etc/hosts中描述,oracle服务侦听的端口号。
  GLOBAL_DBNAME oracle8 为创建数据库时的数据库名
  ORACLE_HOME就不讲了
  SID_NAME为实例名
  如果用户想要监听多个服务,只需在SID_LIST_LISTENER中的SID_LIST(监听列表)下再增加一个要监听的SID_DESC条目 ,这样监听器就可以监听指定的ORACLE_SID服务了(即oracle的实例)
  2.sqlnet.ora
  SQLNET.AUTHENTICATION_SERVICES= (NTS)
  NAMES.DIRECTORY_PATH= (TNSNAMES,HOSTNAME) 
  这个配置和tnsnames.ora配合使用,当用户输入sqlplus system/manager@localdb后,sqlplus程序会自动到sqlnet.ora文件中找NAMES.DEFAULT_DOMAIN参数,假如该参数存在,则将该参数中的值取出,加到网络服务名的后面,
  这里的配置没有NAMES.DEFAULT_DOMAIN参数,如果客户端输入sqlplus sys/oracle@localdb,那么客户端就会首先在tnsnames.ora文件中找localdb的记录(服务名).如果没有相应的记录则尝试把localdb当作一个主机名,通过网络的途径去解析它的ip地址然后去连接这个ip上的GLOBAL_DBNAME=orcl这个实例;如果NAMES.DIRECTORY_PATH= (TNSNAMES)那么客户端就只会从tnsnames.ora查找,找不到就报错。TNS-12154 (ORA-12154):TNS:could not resolve service name
  3.tnsnames.ora
  localdb= 
   (DESCRIPTION 
   (ADDRESS_LIST 
   (ADDRESS (PROTOCOL TCP)(HOST 192.168.1.29)(PORT 1521))
    
  
    (
   CONNECT_DATA =(SERVICE_NAME oracle8) (SERVER DEDICATED)
  
    )
   ) 
  (PROTOCOL TCP)(HOST 192.168.1.29)(PORT 1521))这些前面已经讲过了,(SERVER DEDICATED)这个也讲过了,一般默认是DEDICATED,MTS方式需要专门的配置,可以用select server from v$session核实,(SERVICE_NAME oracle8)参数是oracle8i新引进的在8i以前,我们用SID来表示标识数据库的一个实例,但是在Oracle的并行环境中,一个数据库对应多个实例,这样就需要多个网络服务名,设置繁琐。为了方便并行环境中的设置,引进了Service_name参数,该参数对应一个数据库,而不是一个实例,而且该参数有许多其它的好处。,参数的缺省值为数据库名,可以用show parameter service_name 来确定其值。
  TNS的配置就讲这些了,仅仅是其中的皮毛,但对分析我们的问题也就差不多了。更加多的内容可参考:《在Oracle网络结构中解决连接问题》一文:
  http://fanqiang.chinaunix.net/db/oracle/2006-06-29/4714.shtml
  
  四、Oracle和PHP连接错误的分析
  先声明以下分析都是基于数据库实例已经启动的情况
  第一次测试用$conn=OCILogon("scott","tiger","localdb");来连接Oracle。实际上就是
  sqlplus scott/tiger@localdb
  这明显就是一个TNS连接请求,但listener.ora没被正确配置或
  listener进程没启用,显然会产生错误,Warning: _oci_open_server: ORA-12154: TNS:could not resolve service name in /www/htdocs/ora1.php on line 2
  Oracle connect failed!
  上面是典型的出错信息。但如果确定以上步骤都没问题的情况下,就一定没问题吗?我们用$conn=OCILogon("scott","tiger");来代替$conn=OCILogon("scott","tiger","localdb");进一不来测试
  结果还是产生如下错误:
  Warning: _oci_open_server: Error while trying to retrieve text for error ORA-12546 in /www/htdocs/ora1.php on line 2
  Oracle connect failed!
  这时就要考虑另外一个重要问题了,那就是连接的用户要对$ORACLE_HOME有访问权限,在检查访问权限中我看到/home/oracle的权限是drwx-------,问题找到了,/www/conf/httpd.conf 中的User nobody,Group nobody显然没有权限。
  解决办法:用root登陆到系统,#chmod /home/oracle
  #chmod /home/oracle在来测试,不管是
  $conn=OCILogon("scott","tiger","localdb")
  还是$conn=OCILogon("scott","tiger")都成功了。
  当然在listener没启动的情况,
  $conn=OCILogon("scott","tiger","localdb")还是不行
  我们在来看看,最初的第二次测试成功的情况:
  www/conf/httpd.conf 中的User nobody,Group nobody改成了oracle.dba显然访问权限没问题$conn=OCILogon("scott","tiger")用本地连接的方式,故也不存在TNS问题。如果当初用$conn=OCILogon("scott","tiger","localdb")或
  $conn=OCILogon("scott","tiger","XXXXXX")什么的,就算www/conf/httpd.conf 中已经改为了oracle.dba,在TNS没有被正确配置前也是不可能成功的。
0 0
原创粉丝点击