返回首页

gbase数据、南大通用产品文档:GBase8s数据库日志记录状态

更新日期:2024年09月11日

您必须对数据库使用事务日志记录以利用需要日志记录的数据库服务器进程中所列的所有
功能。
数据库服务器管理的每个数据库均有日志记录状态。日志记录状态指示数据库是否使用事
务日志记录以及(如果使用)数据库运用哪一种日志缓冲机制。要查明数据库的事务日志
记录状态,请按监视数据库的日志记录方式中的说明,使用数据库服务器实用程序。数据
库日志记录状态将指示下列日志记录类型中的任意一种:
 未缓冲的事务日志记录
 已缓冲的事务日志记录
 符合 ANSI 的事务日志记录
 无日志记录
所有逻辑日志记录在数据库服务器将其写入磁盘上的逻辑日志之前,均经过共享内存中的
逻辑日志缓冲区。但是,数据库服务器清仓逻辑日志缓冲区的时刻对于已缓冲的事务日志
记录和未缓冲的事务日志记录是不同的。

GBase 8s 管理员指南
南大通用数据技术股份有限公司
- 281 -
未缓冲的事务日志记录
如果事务是对使用未缓冲日志记录的数据库进行的,那么逻辑日志缓冲区中的记录可保证
在落实处理期间写入磁盘。当应用程序在 COMMIT 语句之后(对于分布式事务,在
PREPARE 语句之前)重获控制权时,逻辑日志记录在磁盘上。一旦落实缓冲区中的任何
事务(即,将落实记录写入逻辑日志缓冲区),数据库服务器就立即清仓记录。
当数据库服务器清仓缓冲区时,仅将已使用的页写入磁盘。已使用的页包含那些仅部分已
满的页,但这样就浪费了一些空间。由于这个原因,相比在同一数据库服务器上的所有数
据库均使用已缓冲的日志记录这种情况而言,磁盘上的逻辑日志文件会更快地填满。
未缓冲的日志记录对于大多数数据库而言是最好的选择,因为它保证所有已落实的事务可
得以恢复。在发生故障的情况下,仅丢失在发生故障时未落实的事务。但是,有了未缓冲
的日志记录,数据库服务器会更频繁地将逻辑日志缓冲区清仓到磁盘,而缓冲区将包含更
多部分已满的页,因此它比已缓冲的日志记录会更快地填充逻辑日志。

已缓冲的事务日志记录
如果事务是对使用已缓冲日志记录的数据库进行的,那么记录尽可能久地保留(已缓冲)
在逻辑日志缓冲区中。直至发生以下情况之一,这些记录才会从共享内存中的逻辑日志缓
冲区刷新到磁盘上的逻辑日志:
 缓冲区已满。
 具有未缓冲日志记录的数据库上的落实清空了缓冲区。
 出现检查点。
 连接关闭。
如果您使用已缓冲日志记录并且发生了故障,那么不能期望数据库服务器恢复那些在发生
故障时位于逻辑日志缓冲区中的事务。因此,可能会丢失一些已落实的事务。作为对该风
险的补偿,变更期间的性能会稍有提高。只要您在发生故障的情况下可重新创建更新,那
么已缓冲日志记录最适合用于频繁更新的数据库(这时更新速度很重要)。您可调整逻辑
日志缓冲区的大小以便为您的系统在性能和因系统故障而丢失事务的风险之间找到可接受
的平衡。

符合 ANSI 的事务日志记录
符合 ANSI 标准的数据库日志记录状态表明数据库所有者使用 MODE ANSI 关键字。符
合 ANSI 标准的数据库对事务处理强制执行 ANSI 规则,始终使用未缓冲的事务日志记
录。您无法更改符合 ANSI 标准的数据库的缓冲状态。

无数据库日志记录
如果您关闭了数据库的日志记录,那么将不记录事务,但会记录其他操作。有关更多信息,
请参阅 始终记录的活动。通常,当您要装入数据或仅运行查询时,将关闭数据库的日志记
录。

GBase 8s 管理员指南
南大通用数据技术股份有限公司
- 282 -
如果您对恢复源感到满意,可以决定不对数据库使用事务日志记录,从而减少数据库服务
器处理量。例如,如果要将许多行从可恢复的源(如磁带或 ASCII 文件)装入数据库,那
么可能不需要事务日志记录,并且在不使用事务日志记录的情况下装入会进行得更快。但
是,如果其他用户在数据库中是活动的,那么您直到重新启动日志记录(这必须等待 0 级
备份)后才会拥有其事务的逻辑日志记录。

具有不同日志缓冲状态的数据库
数据库服务器上的所有数据库使用相同的逻辑日志和相同的逻辑日志缓冲区。因此,对具
有不同逻辑缓冲状态的各数据库的事务可写入相同的逻辑日志缓冲区。在这种情况下,如
果事务是对具有已缓冲日志记录的数据库和对具有未缓冲日志记录的数据库而存在的,那
么数据库服务器在缓冲区已满时或在具有未缓冲日志记录的数据库的事务完成时清空缓冲
区。

X/Open DTP 环境中的数据库日志记录
X/Open 分布式事务处理 (DTP) 环境中的数据库必须使用未缓冲日志记录。未缓冲日志记
录确保数据库服务器逻辑日志始终处于一致状态,并且可与事务管理器同步。如果在
X/Open DTP 环境中打开用已缓冲日志记录创建的数据库,数据库状态会自动更改为未缓
冲日志记录。
数据库服务器支持符合 ANSI 标准和不符合 ANSI 标准的数据库。
有关更多
信息,请参阅事务管理器。

使用 FLUSH 语句来将 PUT 语句缓冲的行强制写到数据库。
语法

元素
描述
限制
语法
cursor_id
游标名称
必须已经声明
标识符
cursor_id_var
保留 cursor_id 值
的主变量
必须为字符数据类型 特定于语言
用法
随同 GBase 8s ESQL/C 使用此语句,这是对 SQL 的 ANSI/ISO 标准的扩展。
PUT 语句添加行到缓冲区,在缓冲区变满时,将缓冲区的内容写到数据库。在缓
冲区未满时,使用 FLUSH 语句来强制插入。
如果程序终止而未关闭该游标,则缓冲区保持为未刷新。从上一次刷新丢失起,
将行放入缓冲区内。不要预期程序结束会自动地关闭游标并刷新缓冲区。下列示
例展示操作名为 icurs 的游标的 FLUSH 语句:
FLUSH icurs

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 632
示例
下列示例假设名为 next_cust 的函数返回有关新客户的信息,或返回空数据表示
输入结束:
EXEC SQL BEGIN WORK;
EXEC SQL OPEN new_custs;

while(SQLCODE == 0)
{

next_cust();

if(the_company == NULL)


break;


EXEC SQL PUT new_custs;
}

if(SQLCODE == 0)
/* if no problem with PUT */
{

EXEC SQL FLUSH new_custs;

/* write any rows left */



if(SQLCODE == 0)
/* if no problem with FLUSH */


EXEC SQL COMMIT WORK; /* commit changes */
}
else

EXEC SQL ROLLBACK WORK; /* else undo changes */
此示例中的代码重复地调用 next_cust。在返回非空数据时,PUT 语句将返回值
发送到行缓冲区。在缓冲区填满时,自动地将缓冲区包含的那些行发送到数据库
服务器。在 next_cust 不再有数据返回时,循环正常结束。
检查 FLUSH 语句时出错
SQL 通信区域(sqlca)结构包含关于每一 FLUSH 语句的成功信息以及成功地插
入的行数。每一 FLUSH 语句的结果在 sqlca 的这些字段描述:sqlca.sqlcode、
SQLCODE 和 sqlca.sqlerrd[2]。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 633
在您以插入游标使用数据缓冲时,直到刷新该缓冲区才会发现错误。例如,仅在
刷新缓冲区时,才能发现与列的预定数据类型不兼容的输入值。在发现错误时,
缓冲区中位于错误之后的任何行都不会插入;它们从内存中丢失。
如果未发生错误,则 SQLCODE 域或设置为错误代码或设置为零(0)。SQLERRD
数组的第三个元素设置为成功地插入到数据库内的行数:

如果一个行块成功地插入到数据库内,则 SQLCODE 设置为零(0),
SQLERRD 设置为行数。

如果在 FLUSH 语句插入一个行块时发生错误,则 SQLCODE 显示是哪
个错误,SQLERRD 包含成功地插入的行数。(从缓冲区废弃未插入的
行。)
提示: 在您遇到 SQLCODE 错误时,还存在相应的 SQLSTATE 错误。 GBase 8s
的客户机/服务器通信协议,诸如 SQLI 和 DRDA®,支持 SQLSTATE 代码值。要
获取这些代码的列表,以及关于如何取得消息文本的信息,请参阅 使用
SQLSTATE 错误状态代码。
要对实际插入到数据库内的行数以及尚未插入的行数计数
.准备两个整数变量,例如,total 和 pending。
1. 在游标打开时,设置两个变量为 0。
2. 每次执行 PUT 语句时,增大 total 和 pending。
3. 只要执行 FLUSH 语句时,或关闭游标时,从 pending 抽取 SQLERRD
数组的第三个字段。

您可在 SPL 例程中使用任何 SQL 表达式,除了聚集表达式以外。GBase 8s SQL 指南:
语法 提供 SQL 表达式的完整语法与描述。
下列示例包含 SQL 表达式:
var1
var1 + var2 + 5
read_address('Miller')
read_address(lastname = 'Miller')
get_duedate(acct_num) + 10 UNITS DAY
fname[1,5] || ''|| lname '(415)' || get_phonenum(cust_name)