2010-10-9

利用MSCS创建高可用性的DB2集群服

利用MSCS创建高可用性的DB2集群服务
2010-03-10 11:25作者:天极网开发频道出处:天极网软件频道责任编辑:郑重
  【天极网开发频道 技术文档】周末加班,事先得知是帮人建一个Windows的故障转移集群。虽说现在主要精力是在中间件上,但Windows毕竟还是深入学习过一年的嘛,更何况在WebSphere和WebLogic上都做过MSCS的集群,所以以为不过是小菜一碟,最后想不到从6点搞到了凌晨1点。

  我们首先是采用Oracle在Windows下的套路:两台主机上都启用数据库实例,数据库则存放在共享存储上,通过在集群资源中添加DB2的通用服务,从而达到数据库服务的故障转移。

  应该说思路没什么问题,但是实行起来有个问题,就是在有用户连接的情况下,停止db2服务会失败,第二次再去停止才能够停下来,这样手动转移集群就会有点问题。于是我们就想着法子怎么再数据库服务停止前执行一下中断所有数据库链接的命令……苦思冥想、多次尝试,弄的焦头烂额。

  最后上IBM developerworks找文档,才知道原来根本不用这么麻烦,实例只需一份,而且DB2早就给你准备好了db2msce工具,只要写一份db2mscs.cfg的配置文件:

  DB2_INSTANCE=DB2 //指定需要转换的实例名称

  DB2_LOGON_USERNAME=dbdomain/db2admin //指定登录实例的域用户账号

  DB2_LOGON_PASSWORD=0000 //指定登录实例域用户账号的密码

  CLUSTER_NAME=MYCLUSTER //指定群集的名称

  GROUP_NAME=DB2 Group A //指定用于该实例的组名称

  DB2NODE=0 //指定该组资源对应的 DB2 节点号

  IP_NAME= MscsA //指定用于该实例的 IP 地址资源的名称

  IP_ADDRESS=192.168.192.31 //指定 IP 地址资源的IP地址属性

  IP_SUBNET=255.255.255.0 //指定 IP 地址资源的子网掩码

  IP_NETWORK=Public Network //指定 IP 地址资源绑定的网络连接

  NETNAME_NAME = MscsAName //指定网络名资源的名称

  NETNAME_VALUE = DataCenter //指定网络名资源的机器名属性

  NETNAME_DEPENDENCY = MscsA //指定该网络资源名对应的 IP 地址资源的名称

  DISK_NAME=DISK E: //指定该节点需要使用的磁盘资源

  INSTPROF_DISK=E:
//指定该节点目录所在的磁盘资源上述配置文件中的NAME选项都可以随便填写,以简单明了为主,IP_ADDRESS是DB2服务的浮动IP,IP_NETWORK应该写提供集群外网服务的那块网卡名称,NETNAME的那三个选项可以不填,不影响使用(因为都是用IP连接的)。

  然后运行db2mscs -f:db2mscs.cfg命令(注意F不是指盘符,将db2mscs.cfg放于db2mscs同一个目录下),你就会看到集群服务中自动添加了一个资源组:DB2
Group A,添加了一个名为DB2的DB2类型服务,而这个服务类型之前是没有的。

--
we drink green tea

sqlserver 建立热备

集群是一种技术解决方案,它将硬件和软件结合起来,为Web、Email以及数据库等服务提供高可用性和高伸缩性的架构。本文将分析集群的类型,然后将重点放在如何建立一个基于Microsoft的集群解决方案。

集群的类型

集群分为两种类型:负载平衡和失效转移(Failover)。负载平衡集群将负载分散到集群内的各个资源,这要涉及跨越多个前端服务器的分布式网络传输。负载平衡集群令每个可用的服务器都拥有较为平均的负载量,以提高系统整体的性能和伸缩能力。这类集群一般用于Web和COM+程序,集群内部支持两个以上的节点。

Failover集群主要针对硬件和软件故障时的系统可用性。它监视系统资源,以确定何时启动失效转移。当系统发生故障时,集群会将资源从故障服务器转移到集群中的其他服务器,以恢复资源的可访问性。

一个具有容错能力的failover集群需要大量的硬件和专用软件,确定应用状态,它可以在硬件和软件发生故障时进行实时故障恢复,包括恢复到当前的应用状态。一个高可用性的集群必定是一个具有容错能力的集群,但它不一定能提供和failover集群同样的错误恢复能力。

Microsoft的Cluster Service
(MSCS)是一种比容错集群更好的高可用性集群。它和专用的容错集群相比,所需硬件更少,但可以操作更多种类的应用。同时,它也可以对硬件和软件的故障进行恢复,但发生故障时无法正常恢复到应用状态则。高可用性的MSCS可以在一个集群内支持两个服务器节点。

基本的软硬件组件

集群中的服务器节点都采用各自独立的硬件设备,相互间协同工作。每个服务器有自己的操作系统,并独立连接在网络上。服务器间采用外部硬盘和专用网络连接。共享硬盘通过硬盘控制器与各个节点相连,这种硬盘控制器一般采用外置SCSI设备或存储局域网(SAN)作为共享硬盘,不同于包含操作系统的硬盘控制器。

MSCS解决方案可以采用主动/被动模式工作。在同一时间集群中只有一个节点是主动的,主动服务器存储着集群内的全部资源,并不断将数据写入共享硬盘,这就是所谓的quorum驱动器。它可以在故障恢复时,将共享状态信息从一个节点转移到另一个节点。定时的发送信号会通过服务器间的专用网传递,当处于被动模式的服务器没有受到这个信号,就认为主动服务器已经失效。此时,它便开始接管集群资源,并从quorum分区上读取状态信息。

在集群中安装 SQL Server

为了在集群上安装 SQL Server ,你必须首先按以下步骤建立一个可操作的集群:

1. 在每个服务器上安装支持MSCS的Windows Server操作系统。

2. 为每个服务器建立一个"公开的"网络连接。这个连接用来接收外部查询请求。

3. 在集群的两个节点间建立一个专用网络,用来传输节点状态信号。

4. 在域中建立一个用户,用来操作集群。在每个服务器上将该用户添加到管理员组。

5. 将两个服务器关闭。连接到共享驱动器上,并建立磁盘资源。开启集群中的一号节点(主动模式)。建立并初始化逻辑磁盘空间用来设置quorum驱动器,并建立其它的逻辑分区。

6. 通过控制面板的添加/删除程序中的Windows组件添加并配置Microsoft Cluster
Service。其中包括设置集群的虚拟名称、IP地址,以及共享磁盘资源。

7. 开启二号节点(被动模式)。当二号节点在线时,回到一号节点,通过集群管理程序添加二号节点。在集群中添加二号节点非常容易,只要通过在一号节点进行简单配置就可以完成。

集群建立好后,就按照以下步骤安装SQL Server了:

1. 插入SQL Server企业版的安装光盘。如果没有启动自动安装程序,就在光盘上点击setup.exe。

2. 在确认计算机名界面,选择虚拟服务器并输入一个虚拟名称。

3. 建立一个运行SQL Server的服务账号。将集群中每个节点的管理权限赋给这个账号。

4. 填写IP地址、服务账号,以及共享磁盘资源等内容。

安装程序会在集群中的每个节点上安装SQL Server的复本,并在集群中建立虚拟设置。之后用户就可以通过集群管理器对SQL Server进行控制了。

--
we drink green tea

关于sqlserver集群的几点考虑

由二台或更多物理上独立的服务器共同组成的"虚拟"服务器称之为集群服务器。一项称做MicroSoft集群服务(MSCS)的微软服务可对集群服务器进行管理。一个SQL
Server集群是由二台或更多运行SQL
Server的服务器(节点)组成的虚拟服务器。如果集群中的一个节点发生故障,集群中的另一个节点就承担这个故障节点的责任。

认为一个SQL Server集群能够给集群中的两个节点带来负载平衡,这是一种常见的误解。虽然这似乎很有用,但却是不正确的。这也意味着集束SQL
Server不能真正提高性能。集束SQL
Server只能提供故障转移功能。故障转移就是当系统中的一台机器发生故障失去其功能时,另一台机器将接手运行它的SQL
Server实例。这种功能失效可能是由于硬件故障、服务故障、人工故障或各种其它原因。

为何要集束SQL Server环境?

在实用性方面,集群SQL Server环境令人满意。在进行故障转移时,将数据库实例由一台服务器转移到另一台服务器的时间非常短暂,一般只需要3至7秒钟。虽然需要重建连接,但对数据库的终端用户而言,故障转移处理通常是透明的。低廉的故障转移成本还可帮助你对集群中的节点进行维护,而不会造成服务器完全无法访问。

SQL Server集群类型

一共有两种类型的SQL Server集群:主动/被动集群和主动/主动集群。下面分别对它们进行说明(说明以两个节点的SQL Server集群为基础)。

主动/被动集群

在这种类型的集群中,一次只有一个节点控制SQL
Server资源。另一个节点一直处于备用模式,等待故障发生。进行故障转移时,备用的节点即取得SQL Server资源的控制权。

优点:由于服务器上只有一个实例在运行,所以在进行故障转移时,不需要另外的服务器来接管两个SQL Server实例,性能也不会因此降低。

缺点:由于虚拟服务器上只有一个SQL Server实例在运行,另一台服务器总是处理备用模式与空闲状态。这意味着你并没有充分利用你购买的硬件。

主动/主动集群

在这种类型的集群中,集群中的每个节点运行一个独立且主动的SQL Server实例。发生节点故障时,另一个节点能够控制发生故障节点的SQL
Server实例。然后这个正常的节点将运行两个SQL Server实例――它自己的实例和发生故障的实例。

优点:通过这种配置,你能够充分利用你的硬件。在这样的系统中,两个服务器都在运行,而不是只有一台服务器运行,而另一台处于等待故障发生的备用模式,因此你能够充分利用你购买的机器。

缺点:如果进行故障转移,一台服务器运行两个SQL
Server实例,性能就会受到不利影响。然而,性能降低总比虚拟服务器完全失灵要强得多。这种配置的另一故障在于它要求购买的许可要比主动/被动集群多一些。因为集群在运行两个主动SQL
Server实例,这要求你购买两个单独的服务器许可。在某些情况下,这也可能对你形成阻碍。

集群考虑

在高实用性方面,集群SQL Server环境有一定的优势。然而,高实用性也确实伴随某种折衷。

首先,建立一个集群SQL Server环境非常昂贵。这是因为集群中的节点必须遵照集群节点的兼容性列表。而且,还需要建立一个复杂的网络,机器的配置必须几乎相同,同时需要实现数据库文件磁盘子系统共享。存储区网络(SAN)是建立这种子系统的不错选择,但SAN并非必要,而且十分昂贵。另外,如果你正在运行一个主动/主动集群,你需要为集群中运行SQL
Server实例的每台机器的处理器购买一个许可。

因为当地集群主要局限于同一地理区域,自然灾难可能会使集群完全失灵。在那种情况下,你需要转移到灾难恢复站点进行继续操作。你也可以建立地理分散的SQL
Server集群,但这样的系统更加复杂与昂贵。

--
we drink green tea

淘宝构建分布式数据库

在淘宝,有一个业务系统,在一年半以前,这个业务系统很小,访问量很低,相关的表跟核心数据库放在一起,后来由于产品升级,新产品的许多功能很受会员的喜爱,会员大量使用,很快就对核心数据库造成了相当程度的IOPS冲击与威胁,也迅速消耗着核心存储的空间,为了不影响淘宝的核心业务,我们将此业务相关的表迁移出了核心库,创建了一个独立的ORACLE数据库,这种拆分数据库的方式,就是大家常说的垂直拆分。

这种拆分方式,对上层业务应用程序变动很小,只是需要改一下数据库连接而已。尽管数据库独立了,但从本质上来讲,并没有优化这个业务的数据库。在新的数据库里,此产品仍然在高速发展,每天都制造着大量的数据,表和索引越来越大,存储空间达到了T级。由于此业务访问的离散性,对存储IOPS消耗极高,占用了大量的宝贵的存储资源。为了减少这种消耗,我们首先在业务层面进行了优化,拿掉了一些不必要的产品功能,并加入了一些限制,控制了一部份不正常的数据增长;在数据库层面,通过观察SQL,发现了应用程序中可以改进的业务逻辑以及进行必要有索引调整;还有对有些业务点加上适当的前端的Cache策略。通过以上的改进,在一定程度上缓解了整个系统的压力。
对整个系统的根本性改造,我们一直在探索。对于技术出身的我们来说,一个小小的xx业务系统,占用了这么多的昂贵的存储硬件资源与ORACLE软件资源,心里总有一些不平静,要去改造它。而且这个业务系统仍然在不断的膨胀,好几个表的数据都超过了十亿级,进行索引调整的难度越来越大,对于前端业务的不断变化,这种调整又是必须的。采用集中式的ORACLE数据库方式,在前期,会在相当程度上减少前端应用程序的复杂性,但到了一定的规模过后,你会发现你要付出的代价也会呈指数级的增长,可维护性在逐渐降低。而且在这种高IOPS,高并发的情况下,数据库也会很容易出问题。
从去年开始,taobao开始在一些小系统上采用MySQL数据库,但使用的方式跟ORACLE并没有什么不同。搭建master-slave主从复制结构,应用程序访问master,slave只起到接管的作用。为了改造这个业务系统,采用这么简单的结构是不行的。我们确立了几点目标,第一搭建一个分布式集群;第二集群采用廉价的PC;第三实现读写分离,slave也要承担一定的业务读;第四是用内存来支撑IOPS,不是硬盘。对于此项目业务的数据库,根据什么规则做sharding,又是摆在我们面前一个问题?在做这个架构设计的时候,我们sharding的原则,是要保证大量的访问都是在单库上完成的,不需要跨库merge与sort。我们确立了基本方案过后,联合开发与架构,细化了设计方案,在几个月前,开始了这场攻坚。

因为是要对大表做数据的水平拆分,将数据拆分到多个数据库上,有几个重要的问题需要思考:
1.怎么把在ORACLE中几十亿的数据按规则迁到mysql集群中;
2.如何产生主键唯一值;
3.大表根据规则拆成小表,具体拆分粒度是多少?每个库多少表?
4.如何解决这么多库这么多表的路由问题;
5.如何解决跨库的merge与sort;
6.如何对连接进行管理;
7.如何做数据订正;
8.我们需要开发哪些集群管理工具,比如说建表工具;
9.集群遇到停电怎么办?
10.如何对集群中的数据进行历史迁移?
11.尽管集群采用廉价的PC,但具体采用何种PC,差别还是挺大的,如何平衡集群的规模与可管理性方面的问题?
12.集群对机房电力的消耗与机柜占用问题?
在项目进行期间,DBA团队先后进行了几次数据迁移测试,在数据仓库与SA团队的帮助下,尽管经历了一些困难与挑战,但最终这些问题,大都一一解决。这个项目先后进行了三次程序发布,发布期间平滑迁移数据32亿条左右,感谢负责此项目的DBA同事们与可敬可爱的开发工程师们。这个项目,也使得我们的分布式中间件有了进一步的发展与完善,大大减化了上层业务系统开发的复杂度,不必关心下层业务数据的存放逻辑,感谢架构团队的精益求精。

项目发布后,经过观察,各库不管是master与slave,负载基本相同,但集群中各库负载基本上都在6以上,稍微有点偏高。进行了一些SQL调化,主要是索引调整后,负载降到2以下。说起索引调整,这也是第一次对这么大的mysql集群做DDL,做一次大概需要好几个小时。这个时间消耗,超过了自己的预期。
项目一期已经完成,二期很快又会启动,如果你想不断挑战自我,实现自我价值,加入淘宝DBA团队,这里有一流的环境,成为一名优秀的mysql DBA指日可待。

--
we drink green tea

mysql 支持分布式事务么????

mysql从5.0开始支持XA DataSource。Connector/J 版本要使用5.0版本,5.0以下的不支持。

--
we drink green tea

MySQL+amoeba,轻量级的分布式数据库实现

MySQL+amoeba,轻量级的分布式数据库实现

  最近因为一个大作业,我需要建立一个分布式数据库系统。Oracle和DB2固然强大,但巨大的资源占用以及软件授权的限制让我放弃选择它们。我的目标是寻找轻量级的、免费(最好是开源)的解决方案,最终目标锁定在国产的amoeba上。
  amoeba是一个以MySQL为底层数据存储,并对应用提供MySQL协议接口的proxy。它集中地响应应用的请求,依据用户事先设置的规则,将SQL请求发送到特定的数据库上执行。基于此可以实现负载均衡、读写分离、高可用性等需求。与MySQL官方的MySQL
Proxy相比,作者强调的是amoeba配置的方便(基于XML的配置文件,用SQLJEP语法书写规则,比基于lua脚本的MySQL
Proxy简单)。有关amoeba的更多信息可以参考其文档或作者blog。google出来的相关信息并不多,不过作者的这个帖子(含回复)倒是值得一看。
  下面说说我的理解:
  1、amoeba相当于一个SQL请求的路由器,目的是为负载均衡、读写分离、高可用性提供机制,而不是完全实现它们。用户需要结合使用MySQL的Replication等机制来实现副本同步等功能。amoeba对底层数据库连接管理和路由实现也采用了可插拨的机制,第三方可以开发更高级的策略类来替代作者的实现。这个程序总体上比较符合KISS的思想。
  2、由上一条,建议使用MySQL的Replication机制建立Master-Slave来做副本。我一开始理解有误,使用了amoeba的virtual
DB(负载均衡pool)做writePool,结果使得本应插入同一个表中的数据被拆分地写入了不同的物理数据库中。这样自然与副本的语义不符了。
  3、amoeba已经实现了数据的垂直切分与水平切分。水平切分方面,粒度是行。使用SQLJEP语句可以设计出复杂的切分规则,个人认为是比较强大的。垂直切分的粒度是表,可以把针对不同表的请求发送到不同的节点上执行,但不能以列作为分片粒度。从作者的说法看,amoeba不做SQL解析和重写。在目前的机制下似乎是难以实现同一个表不同的列在不同节点上的分布。不过对开发人员来说,设计良好的表结构应该可以实现简单的基于关系属性的负载均衡的。
  要说这个项目最大的不足,我想可能是文档方面的:
  1、软件的文档(0.31版)主要在讲解配置文件怎么修改,却没有说怎么运行amoeba。我以前没有MySQL
Proxy以及Java工程方面的经验,下载解压amoeba之后,第一感觉这是一个数据库中间件,要通过Java
API编程使用,所以我还纳闷文档中为什么没有API的说明。仔细一看才发现bin目录下有启动脚本。回到文档,发现只在最后的"amoeba性能调优"一节才提到了"amoeba启动脚本"。希望作者改进下一版的文档,让新手不要再疑惑。
  2、文档的"amoeba for aladdin"一节说"(amoeba for aladdin)其性能比MySQL
Proxy也好,但比amoeba for mysql微微差了点",看起来性能优劣是"amoeba for mysql>amoeba for
aladdin>MySQL Proxy";但在这个帖子的回复中,作者又说"(amoeba for mysql)比官方的MySQL
Proxy性能大致低10%~20%左右",两处似乎有矛盾。继续翻这个帖子,才发现原来在0.27版本以后,amoeba的性能逐渐超过了MySQL
Proxy。所以,希望作者可以完善一下文档,并在官方网站或blog的显著位置说明最新版本的特性,以免引起误会。
  3、amoeba是一项优秀的工作,有必要提供完整的英文文档,以便国际推广。

--
we drink green tea

2010-10-8

/创建Statement对象 Statement stmt = conn.createStatement();//只读的结果集 //Statement stmt2 = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);//可更新的结果集 //执行操作(增删改查) ResultSet rs = stmt.executeQuery("select * from stt"); //处理

/创建Statement对象
Statement stmt = conn.createStatement();//只读的结果集
//Statement stmt2 = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);//可更新的结果集

//执行操作(增删改查)
ResultSet rs = stmt.executeQuery("select * from stt");

//处理结果
while(rs.next()){
        System.out.println(rs.getString("1"));
}

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

//创建prepareStatement对象

perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();



--
we drink green tea

Java Statement 和 PrepareStatement 使用方法

String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE ′Colombian′"; 
stmt.executeUpdate(updateString); 

Code Fragment 2: 


PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? "); 
updateSales.setInt(1, 75); 
updateSales.setString(2, "Colombian"); 
updateSales.executeUpdate(); 

 
 


          片段2和片断1的区别在于:后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需要更改其中变量的值,便可重新执行SQL语句。选择PreParedStatement对象与否,在于相同的句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量不同,如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出她预编译的优越性。


--
we drink green tea

jdbc注意事项

使用jdbc四年了,还是犯一些低级错误,提醒自己要注意

1.get数据前,必须执行next()

2.得到记录数,最好不要last再用getrow,因为jdbc驱动可能迭代一次所有记录(可能不使用数据库的存储过程,sqlserver就是如此),应该使用count函数

3.一般要使用预处理,对于数据库的查询,为了防止用户输入的字符串中带有',必须使用预处理,注意使用预处理时,就打开了服务器的游标。

4.使用预处理,数据库生成一个数据集的镜像,它没有参数类型,必须自己转换。

5。生成预处理的sql,必须保证数据库生成一个数据集的镜像,表名使用?代替不可以的,select top ?from tablename ,也不可以用.

6.处理长文本的时候,例如sqlserver 和mysql,读取时不要用getString,应该使用输入流,512字节读一次,这样的效率高一些


--
we drink green tea

how java connect database by jdbc

Java基础:常用的JDBC连接数据库方法大全

时间:2009-08-06 13:05:00来源:网络 作者:未知 点击:296
常用JDBC连接数据库方法总结如下:
一、DB2
Class.forName("Com.ibm.db2.jdbc.net.DB2Driver");
String url="jdbc:db2://dburl:port/DBname"
cn = DriverManager.getConnection( url, userName, password );
二、Microsoft

常用JDBC连接数据库方法总结如下:

一、DB2

Class.forName("Com.ibm.db2.jdbc.net.DB2Driver");

String url="jdbc:db2://dburl:port/DBname"

cn = DriverManager.getConnection( url, userName, password );

二、Microsoft SQLServer(microsoft)

Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" );

cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://DBServerIP:1433;databaseName=master", userName, password );

三、Sybase(jconn2.jar)

Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" );

cn = DriverManager.getConnection( "jdbc:sybase:Tds:DBServerIP:2638", userName, password);

四、MySQL(mm.mysql-3.0.2-bin.jar)

Class.forName( "org.gjt.mm.mysql.Driver" );

cn = DriverManager.getConnection( "jdbc:mysql://DBServerIP:3306/myDatabaseName", userName, password );

五、PostgreSQL(pgjdbc2.jar)

Class.forName( "org.postgresql.Driver" );

cn = DriverManager.getConnection( "jdbc:postgresql://DBServerIP/myDatabaseName", userName, password );

六、Oracle(classes12.jar)

Class.forName( "oracle.jdbc.driver.OracleDriver" );

cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", userName, password );

七、ODBC

Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );

Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, userName, password );



--
we drink green tea

java jdbc 注意事项

JDBC的陷阱

    1、conn一定要在finally语句块进行关闭。

    2、Statement、ResultSet尽可能缩小其变量作用域。

    3、Statement可以使用多次,定义多个。一个Statement对象只和一个ResultSet对象关联,并且是最后一次查询。

    4、ResultSet在Connection、ResultSet关闭后自动关闭。


--
we drink green tea