OracleSQL写入文件后UTL_FILE没有关闭导致数据不一致的原因
Reason for data inconsistency if UTL_FILE is not closed after writing data into the file in Oracle SQL
我正在使用 Oracle SQL 开发人员作为 Oracle 11g 数据库的客户端。这是一个简单的问题。我正在从 table 中获取数据并将数据写入文本文件。这段特定的代码被安排为每月作业,输出文本文件放置在数据库目录路径中。
每个月的记录数不同。文本输出文件具有正确的行数,就像 table 直到上个月的工作。本月,在文本文件中观察到数据不一致。要导出到文本文件的行数假设为 1000。输出文件总共有 950 行左右。数据不匹配。这个问题直到上个月才出现。
在进一步测试时,观察到,使用 UTL_FILE.FCLOSE(M_OUT_SYS) 写入后文件没有关闭。关闭文件后问题已解决,数据现在匹配。
但是为什么直到上个月程序运行没有文件关闭才出现这个问题,为什么这个月突然出现这个问题?
declare
M_OUT_SYS UTL_FILE.FILE_TYPE;
M_DATA VARCHAR2(2000);
M_DIRECTORY_NAME ALL_DIRECTORIES.DIRECTORY_NAME%TYPE;
M_DELIMITER_FILE_NAME VARCHAR2(250);
cursor c1 is
select * from example_table;
begin
M_DIRECTORY_NAME := 'OracleDB_dir_name';
M_DELIMITER_FILE_NAME := 'OutputTextFile.txt';
M_OUT_SYS := UTL_FILE.FOPEN(M_DIRECTORY_NAME,
M_DELIMITER_FILE_NAME,
'W', 8192);
UTL_FILE.PUT_LINE(M_OUT_SYS,'column1|column2|column3');
for i in c1 loop
M_DATA := I.column1 || '|' || I.column2 || '|' || I.column3;
UTL_FILE.PUT_LINE(M_OUT_SYS, M_DATA);
end loop;
end;
请参阅 11.2 https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/u_file.htm 的 utl_file 文档:
UTL_FILE.PUT_LINE 不会(默认情况下)在每次调用后刷新到文件,它只是写入缓冲区。
刷新将在以下任一之后发生:
- 由于达到一定的缓冲区大小(大约 10KB),实例决定刷新
- 使用 utl_file.fflush
手动刷新数据
- 文件句柄已关闭
- 会话断开(类似于3)
当你来取文件时,我的钱会花在你以前的工作上。当您注意到差异时,那是因为会话仍处于打开状态并且它最后一次触发了第 950 行的自动刷新。
我正在使用 Oracle SQL 开发人员作为 Oracle 11g 数据库的客户端。这是一个简单的问题。我正在从 table 中获取数据并将数据写入文本文件。这段特定的代码被安排为每月作业,输出文本文件放置在数据库目录路径中。
每个月的记录数不同。文本输出文件具有正确的行数,就像 table 直到上个月的工作。本月,在文本文件中观察到数据不一致。要导出到文本文件的行数假设为 1000。输出文件总共有 950 行左右。数据不匹配。这个问题直到上个月才出现。 在进一步测试时,观察到,使用 UTL_FILE.FCLOSE(M_OUT_SYS) 写入后文件没有关闭。关闭文件后问题已解决,数据现在匹配。
但是为什么直到上个月程序运行没有文件关闭才出现这个问题,为什么这个月突然出现这个问题?
declare
M_OUT_SYS UTL_FILE.FILE_TYPE;
M_DATA VARCHAR2(2000);
M_DIRECTORY_NAME ALL_DIRECTORIES.DIRECTORY_NAME%TYPE;
M_DELIMITER_FILE_NAME VARCHAR2(250);
cursor c1 is
select * from example_table;
begin
M_DIRECTORY_NAME := 'OracleDB_dir_name';
M_DELIMITER_FILE_NAME := 'OutputTextFile.txt';
M_OUT_SYS := UTL_FILE.FOPEN(M_DIRECTORY_NAME,
M_DELIMITER_FILE_NAME,
'W', 8192);
UTL_FILE.PUT_LINE(M_OUT_SYS,'column1|column2|column3');
for i in c1 loop
M_DATA := I.column1 || '|' || I.column2 || '|' || I.column3;
UTL_FILE.PUT_LINE(M_OUT_SYS, M_DATA);
end loop;
end;
请参阅 11.2 https://docs.oracle.com/cd/E11882_01/appdev.112/e40758/u_file.htm 的 utl_file 文档: UTL_FILE.PUT_LINE 不会(默认情况下)在每次调用后刷新到文件,它只是写入缓冲区。 刷新将在以下任一之后发生:
- 由于达到一定的缓冲区大小(大约 10KB),实例决定刷新
- 使用 utl_file.fflush 手动刷新数据
- 文件句柄已关闭
- 会话断开(类似于3)
当你来取文件时,我的钱会花在你以前的工作上。当您注意到差异时,那是因为会话仍处于打开状态并且它最后一次触发了第 950 行的自动刷新。