Archive for ‘数据库’ Category
我们知道在MS SQL中CHAR(N)或VARCHAR(N)的N是指Bytes,而不是字符的个数,那么在 oracle 中(CHAR或VARCHAR2),这个N到底是字符的个数还是字节长度?
在 oracle 中这个N既可以是Bytes也可以是Characters,那么如何去指定它是哪一种呢?有两种方法:
1.在CHAR或VARCHAR2中明确指定
如:CHAR(10 CHAR),VARCHAR2(20 CHAR),CHAR(10 BYTE),VARCHAR2(20 BYTE)
2.在初始化参数中指定
可以在初始化参数中指定NLS_LENGTH_SEMANTICS=’CHAR’或’BYTE’来确定
默认情况下这个参数是BYTE
那么这两种方式有什么关系和优缺点呢?
做这个项目有一段时间了,决定对数据库设计进行一些总结,大概如下:
1.数据库设计之字符集的选择
2.数据库设计之主键的选择
3.数据库设计之设计合理的表结构
4.数据库设计之建模工具的选择与使用
5.数据库设计之避免丢失更新
6.数据库设计之评估数据库规模
7.数据库设计之命名规范
8.数据库设计之存储规划
9.数据库设计之SQL Tuning
10.数据库设计之初始化参数设定
暂定这么多,呵呵
一. 什么是数据库的坏块
首先我们来大概看一下数据库块的格式和结构:
数据库的数据块有固定的格式和结构,分三层:
Cache layer
Transaction layer
Data layer
在我们对数据块进行读取写入操作的时候,数据库会对要读写的数据块做一致性的检查,其中包括:数据块的类型、数据块的地址信息、数据块的SCN号以及数据块的头部和尾部。如果发现其中有不一致的信息,那数据库就会标记这个数据块为坏块了。数据库的坏块分为两种:逻辑坏块和物理坏块
逻辑坏块(Logically Corrupt):example: the block was corrupted by an oracle internal error but does not appear to be media corrupt
物理坏块(Media Corrupt):incorrect checksum/wrong data block address/impossible block type
一客户在查询数据时报如下错误:
SQL> select count(*) from sa.g_sn_travel;
select count(*) from sa.g_sn_travel
*
ERROR 位于第 1 行:
ORA-08103: object no longer exists
用analyze分析该表,出现如下提示:
SQL> analyze table sa.g_sn_travel validate structure cascade;
analyze table sa.g_sn_travel validate structure cascade
*
ERROR 位于第 1 行:
ORA-01499: table/index cross reference failure - see trace file
查看对应的trace file发现该表的索引和表的数据出现不一致,于是重新创建该Index解决问题。
我们知道在SQL SERVER中有datediff可以返回两个日期之间的时间间隔,但在 oracle 中却不存在这样的函数,那要怎么实现呢?我们分两种情况讨论:
1.只是粗略返回相隔的天数
我们知道在 oracle 中两个日期相减返回的就是相差的天数,当然这个天数未必是整数,它会把两个日期相差的时分秒折算成天数
SQL> SELECT SYSDATE-HIREDATE FROM EMP;
SYSDATE-HIREDATE
—————-
3.12123843
9316.66291
9314.66291
9275.66291
9096.66291
9246.66291
9207.66291
9046.66291
9116.66291
9030.66291
9030.66291
8979.66291
此时我们可以用TRUNC函数去获取我们所要得到的天数:
ORA-1555错误简单的说就是针对一个数据块产生一致读时发生了错误。一致读就是指 oracle 利用回滚段来临时重构一个和事务或查询开始时的块状态相同的快照块的过程。如果一个块改变了多次,可能就会有多个快照块的。
一个事务或查询开始执行时, oracle 会产生一个SCN来记录这个开始时刻点,这个SCN也就叫做SNAPSHOT SCN。 oracle 仅仅看基于SNAPSHOT SCN的快照记录。如果块中有活动的事务或BLOCK SCN> SNAPSHOT SCN时,就产生了一致读。如果是没有活动的事务但没有产生COMMIT SCN的块,先产生DELAY BLOCK CLEANOUT,再比较COMMIT SCN与SNAPSHOT SCN的大小,如果COMMIT SCN小于SNAPSHOT SCN则直接使用该块,否则要产生一致读。
产生ORA-1555的可能情况:
(1) 一个长时间运行的查询,并同时针对查询需要的块有DML处理
当一个长时间的查询开始执行时,查询所需要的一个数据块被修改并递交了,这个块是需要一致读的,但因为该DML事务已递交了,所以保留前映像的回滚段SLOT可以被另外的事务使用,这个查询事务耗时非常长,在这个时间段中,很可能该SLOT被另外的事务使用而把原值给覆盖了,所以当查询执行到该块时,该块的SNAPSHOT SCN时的值已经找不到了,报ORA-1555错误。
我们从一个用户请求开始讲, oracle 的完整的工作机制是怎样的,首先一个用户进程发出一个连接请求,如果使用的是主机命名或者是本地服务命中的主机名使用的是机器名(非IP地址),那么这个请求都会通过DNS服务器或HOST文件的服务名解析然后传送到 oracle 监听进程,监听进程接收到用户请求后会采取两种方式来处理这个用户请求,下面我们分专用服务器和共享服务器分别采用这两种方式时的情况来讲:
专用服务器模式下:一种方式是监听进程接收到用户进程请求后,产生一个新的专用服务器进程,并且将对用户进程的所有控制信息传给此服务器进程,也就是说新建的服务器进程继承了监听进程的信息,然后服务器进程给用户进程发一个RESEND包,通知用户进程可以开始给它发信息了,用户进程给这个新建的服务器进程发一个CONNECT包,服务器进程再以ACCEPT包回应用户进程,致此,用户进程正式与服务器进程确定连接。我们把这种连接叫做HAND-OFF连接,也叫转换连接。另一种方式是监听进程接收到用户进程的请求后产生一个新的专用服务器进程,这个服务器进程选用一个TCP/IP端口来控制与用户进程的交互,然后将此信息回传给监听进程,监听进程再将此信息传给用户进程,用户进程使用这个端口给服务器进程发送一个CONNECT包,服务器进程再给用户进程发送一个ACCEPT包,致此,用户进程可以正式向服务器进程发送信息了。这种方式我们叫做重定向连接。HAND-OFF连接需要系统平台具有进程继承的能力,为了使WINDOWS NT/2000支持HAND-OFF必须在HKEY_LOCAL_MACHINE>SOFTWARE> oracle >HOMEX中设置USE_SHARED_SOCKET。
CREATE procedure ListUserPermission
(@UserName sysname)
AS
set nocount on
BEGIN
if (select object_id(’tempdb..#tt’)) is not null
drop table #tt
create table #tt
(owner sysname,
object sysname,
grantee sysname,
grantor sysname,
protecttype varchar(10),
actionname varchar(20),
columnname sysname
)
insert #tt execute sp_helprotect @username = @UserName
select
rtrim(protecttype) + ‘ ‘ + actionname + ” +
case object when ‘.’ then ” else ‘ on ‘ + ‘['+owner+'].['+object+']‘ +
case when columnname in(’(All+New)’,’(All)’,’(New)’,’.’) then ” [...]
今天同事告诉我 oracle 10g无法启动,我看了一下,启动的时候报如下错误:
ORA-00600: [keltnfy-ldmInit], [46]
大致了解了一下情况,由于办公室调整,服务器变更了位置,IP地址和hostname也变掉了。
在google上查了一下,发现跟xzh2000描述的很类似,于是修改hosts及network文件,将其中hostname的设定改成原来的hostname,然后再启动 oracle ,果然可以开启数据库了:)
这应该是 oracle 的一个bug,所以对于10gR2在Linux下不要随意修改hostname,如果要修改,一定要修改彻底,主要是修改/etc/hosts,/etc/sysconfig/network这两个文件。