728x90

안녕하세요. CURSOR Service Distribution의 2021년 1분기 뉴스레터에서 꽤 유용한 정보를 발견해서 정리해보려고 합니다. 참고로 CURSOR Service Distribution은 독일에서 Informix와 Db2에 대한 서비스를 제공하는 회사입니다.

 

인포믹스에서 테이블을 정의할 때 Smart Blob (데이터 유형 BLOB 또는 CLOB) 컬럼에 대해 스토리지 공간 (SBSpace)을 지정할 수 있습니다. 저장 위치를 ​​지정하지 않으면 $ONCONFIG의 SBSPACE 및 SYSSBSPACE에 설정한 값이 사용되죠.  여러개의 SBSpace를 저장 위치로 지정하면 row별로 SBSpace에 분산되는데, 정확한 저장 위치를 SQL 쿼리로 확인할 수 있다고 합니다.

 

SBSpace 위치를 확인하는 SQL 쿼리를 사용할 때는 Little Endian (Linux, Windows)과 Big Endian (AIX, SPARC Solaris..) 시스템을 구분해서 작성해야 한다네요.

 

Big Endian 시스템에서 SBSpace 번호를 확인하는 방법은 비교적 간단합니다.

("0x" || substr(<sblob_column>::lvarchar,17,8))::INT

Little Endian의 경우 좀 복잡해집니다.

("0x"|| substr(<sblob_column>::lvarchar,23,2)
     || substr(<sblob_column>::lvarchar,21,2)
     || substr(<sblob_column>::lvarchar,19,2)
     || substr(<sblob_column>::lvarchar,17,2))::INT

아래는 리눅스 환경에서의 테스트를 위한 SQL문장입니다. AIX같은 Big Endian에서는 쿼리 내용을 수정해야겠죠.

-- 테이블 생성
create table blob_test (
objekt_nr int,
doc blob
) put doc in (sbdbs,sbdbs2)
;
-- 샘플 데이터 입력
insert into blob_test values (42, filetoblob("/etc/passwd","server"));
insert into blob_test values (43, filetoblob("/etc/hosts","server"));
insert into blob_test values (44, filetoblob("/etc/services","server"));
-- 각 row별 BLOB 데이터가 저장된 SBSpace 확인
select objekt_nr , 
       ("0x"||substr(doc::lvarchar,23,2)
            ||substr(doc::lvarchar,21,2)
            ||substr(doc::lvarchar,19,2)
            ||substr(doc::lvarchar,17,2))::INT as space_nr,
       (select name::char(40)
          from sysmaster:sysdbspaces 
         where dbsnum = ("0x"||substr(doc::lvarchar,23,2)
                             ||substr(doc::lvarchar,21,2)
                             ||substr(doc::lvarchar,19,2)
                             ||substr(doc::lvarchar,17,2))::INT) as spacename
  from blob_test
 where doc is not null;

 

아래는 제가 AIX에서 테스트 해본 결과입니다.

> dbaccess stores_demo -
select objekt_nr , 
       ("0x" || substr(doc::lvarchar,17,8))::INT as space_nr,
       (select name::char(40)
       from sysmaster:sysdbspaces 
       where dbsnum = ("0x" || substr(doc::lvarchar,17,8))::INT) as spacename
  from blob_test
 where doc is not null;
   objekt_nr    space_nr spacename
         42          11 sbspace1
         43          15 sbspace2
         44          11 sbspace1
3 row(s) retrieved.

 

이 쿼리는 공식적으로 문서화되지 않았기 때문에 향후에 변경될 가능성이 있다고 합니다.

제가 테스트한 버전은 12.1과 14.1입니다. SQL 사용전에 맞는 정보가 표시되는지 테스트는 해보시기 바랍니다.

 

 

www.cursor-distribution.de/de/ibm-software/informix-fuer-administratoren/informix-newsletter-ibm/send/434-informix-newsletter/6364-informix-nl-2021q1

 

 

728x90
728x90

Troubleshooting


Problem

Informix creates temporary files for BLOB and CLOB data types. When accessing these temporary files, Informix may fail with an SQLException caused by Java™ 2 Security or unexpected changes to the directory structure containing these files.

Symptom

Informix may create temporary files in the profiles directory of the Application Server environment having format IfxTmpFile_xxxx or Ifxb_xxxx, where xxxx is a numerical value. In the event Informix cannot find or open these temporary files, the following exception will appear in the WebSphere Application Server logs:

java.sql.SQLException: Blob not found
at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:373)
at com.informix.jdbc.IfxResultSet.blobCheck(IfxResultSet.java:1713)
at com.informix.jdbc.IfxResultSet.a(IfxResultSet.java:686)
at com.informix.jdbc.IfxResultSet.b(IfxResultSet.java:626)
at com.informix.jdbc.IfxResultSet.getBlob(IfxResultSet.java:3301)
...
Caused by: java.sql.SQLException: System or internal error
java.security.PrivilegedActionException: java.io.IOException: Permission denied
at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:492)
at com.informix.jdbc.IfxTmpFile.<init>(IfxTmpFile.java:96)
at com.informix.jdbc.IfxSqli.executeFetchBlob(IfxSqli.java:4894)
at com.informix.jdbc.IfxResultSet.blobCheck(IfxResultSet.java:1706)
... 4 more
Caused by: java.security.PrivilegedActionException: java.io.IOException:
Permission denied
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessController.doPrivileged(Native Method)
at com.informix.jdbc.IfxTmpFile.<init>(IfxTmpFile.java:80)
... 6 more
Caused by: java.io.IOException: Permission denied
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.checkAndCreate(File.java:1314)
at java.io.File.createTempFile(File.java:1402)

The nested exception (For example; the exception indicated after "Caused by:") can vary based on JDK version, whether the directory containing the temporary files exists, or whether Java 2 Security is enabled, for example:

Caused by: java.sql.SQLException: System or internal error java.lang.SecurityException: Unable to create temporary file

Caused by: java.security.PrivilegedActionException: java.io.IOException: No such file or directory

Caused by: java.sql.SQLException: System or internal error java.security.PrivilegedActionException: java.io.IOException: Permission denied

Cause

Informix creates IfxTmpFile_xxxxx and Ifxb_xxxx files as temporary storage for CLOB and BLOB data types. These files, by default, are placed in the <InstallRoot>/profiles directory by Informix. Informix may fail with the exceptions above when accessing these temporary files in the default directory due to restrictive Java 2 Security file access permission or changes to either the Informix temporary files or the <InstallRoot>/profiles directory (where <InstallRoot> is the directory where you installed WebSphere Application Server).

Resolving The Problem

Specify a specific directory for Informix's temporary files by opening the data source on the WebSphere Administrative Console; then open the link for the data source custom properties; create a new custom property called ifxJDBCTEMP for your Informix data source. The value for the ifxJDBCTEMP property must be set to an absolute path name (For example; c:\temp or \opt\temp).

For more information on how to configure or change a data source, see the WebSphere Information Center section, WebSphere Application Server data source properties.

For more information on custom properties, see the WebSphere Information Center section Custom property collection



https://www.ibm.com/support/pages/informix-fails-exception-javasqlsqlexception-blob-not-found

https://www.databaseadm.com/article/11187195/temporary+files+are+not+getting+deleted

728x90
728x90

안녕하세요. 인포믹스 LOB(Large Object) 타입의 데이터 크기를 계산하는 방법을 테스트해봤습니다.

LOB 타입 데이터를 처리할 수 있는 함수가 없는 것으로 알고 있어서, 아래와 같이 blademgr의 번들된 모듈을 설치해서 사용했습니다.


1. 먼저 테스트용 데이터베이스 stores_demo를 아래와 같이 만듭니다.

$ dbaccessdemo -log -dbspace datadbs1


2. blademgr에서 LOB 타입 데이터를 처리하기 위한 모듈을 아래와 같이 설치합니다.

$ blademgr

ol_informix1210_1>show databases

Databases on server:

        stores_demo

        sysadmin

        sysuser


ol_informix1210_1>list stores_demo

DataBlade modules registered in database stores_demo:

         TimeSeries.6.00.FC7          ifxrltree.2.00

            spatial.8.22.FC2


ol_informix1210_1>show modules

16 DataBlade modules installed on server ol_informix1210_1:

                LLD.1.20.FC2                Node.2.0 c

           TSAFuncs.1.00.FC1       TSPIndex.1.00.FC1

           TSPMatch.2.00.FC1     TimeSeries.6.00.FC7

               binaryudt.1.0                bts.3.10

                excompat.1.0         ifxbuiltins.1.1

               ifxregex.1.00          ifxrltree.2.00

                 mqblade.2.0        spatial.8.22.FC2

                sts.2.00.FC1            wfs.1.00.FC1

A 'c' indicates DataBlade module has client files.

If a module does not show up, check the prepare log.

ol_informix1210_1>register excompat.1.0 stores_demo

Register module excompat.1.0 into database stores_demo? [Y/n]y

Registering DataBlade module... (may take a while).

DataBlade excompat.1.0 was successfully registered in database stores_demo.


3. 위와 같은 절차로 설치하고 나면 dbms 관련 함수와 프로시저가 생성된 것을 확인할 수 있습니다.

$ dbschema -d stores_demo -f all | egrep 'create function.*dbms_|create procedure.*dbms'

create function "informix".dbms_lob_getlength (blob)

create function "informix".dbms_lob_getlength (clob)

create function "informix".dbms_lob_compare (blob,blob,integer default 2147483647,integer default 1,integer default 1)

create function "informix".dbms_lob_substr (clob,integer default 32767,integer default 1)

create function "informix".dbms_lob_instr (clob,lvarchar,integer default 1,integer default 1)

create function "informix".dbms_lob_new_clob (lvarchar)

create function "informix".dbms_lob_compare (clob,clob,integer default 2147483647,integer default 1,integer default 1)

create function "informix".dbms_random_jrand48 (inout bigint)

create procedure "informix".dbms_output_enable (integer default 20000)

create procedure "informix".dbms_output_disable ()

create procedure "informix".dbms_output_put (lvarchar)

...


4. 인포믹스 데모 프로그램의 샘플 이미지 파일을 입력하기전에 사이즈를 확인합니다.

$ ls -l demo/esqlc/cn*.gif

-rw-r--r--    1 informix informix      15736 Apr 19 18:08 demo/esqlc/cn_10001.gif

-rw-r--r--    1 informix informix      21454 Apr 19 18:08 demo/esqlc/cn_10027.gif

-rw-r--r--    1 informix informix      11751 Apr 19 18:08 demo/esqlc/cn_10031.gif

-rw-r--r--    1 informix informix      25610 Apr 19 18:08 demo/esqlc/cn_10046.gif

-rw-r--r--    1 informix informix       7937 Apr 19 18:08 demo/esqlc/cn_10049.gif


5. 입력할 테이블을 만들고 LOB 데이터 크기를 계산합니다.

$ dbaccess stores_demo -

> create table test (filename varchar(30), img blob);

> insert into test values ('cn_10001.gif', filetoblob('./demo/esqlc/cn_10001.gif','client'));

> insert into test values ('cn_10027.gif', filetoblob('./demo/esqlc/cn_10027.gif','client'));

> insert into test values ('cn_10031.gif', filetoblob('./demo/esqlc/cn_10031.gif','client'));

> insert into test values ('cn_10046.gif', filetoblob('./demo/esqlc/cn_10046.gif','client'));

> insert into test values ('cn_10049.gif', filetoblob('./demo/esqlc/cn_10049.gif','client'));

> select filename, dbms_lob_getlength (img) from test;



filename                       (expression)


cn_10001.gif                          15736

cn_10027.gif                          21454

cn_10031.gif                          11751

cn_10046.gif                          25610

cn_10049.gif                           7937


5 row(s) retrieved.



Knowledge Center를 보면 DBMS_LOB_LENGTH라고 문서화가 되어있지 않아 혼동이 있을 것 같네요.

참고가 되시기를 바랍니다.




** 참고

http://www-01.ibm.com/support/docview.wss?uid=swg21670983

https://www.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.dbext.doc/ids_r0055123.htm

728x90
728x90

4KB가 넘는 이미지 데이터가 hex string으로 존재하고 이를 이미지 형태로 ORACLE 테이블에 입력하는 예제입니다.

먼저 아래와 같은 함수를 만듭니다. 함수는 stack overflow의 글에서 참조했습니다.

기본적인 기능만 있어 예외처리가 필요할 수 있습니다.


create or replace function hextoblob(data in clob) return blob

is

    v_blob    blob;

    v_start  pls_integer := 1;

    v_buffer pls_integer := 4000;

begin


    dbms_lob.createtemporary(v_blob, true);


    for i in 1..ceil(dbms_lob.getlength(data) / v_buffer)

    loop

        dbms_lob.append(v_blob, hextoraw(DBMS_LOB.SUBSTR(data, v_buffer, v_start)));

        v_start := v_start + v_buffer;

    end loop; 


    return v_blob;

end;


위의 예제는 NULL값 처리는 제외된 내용입니다. 관련 내용은 아래 링크를 참고해주세요.


작업 전에 hex string 데이터를 CLOB 필드에 입력합니다. 

$ sqlplus scott/tiger

 

SQL> create table img (img clob);

 

Table created.

 

$ cat img.ctl     << SQL*Loader control file

 

load data

infile '/work2/INFORMIX/1150FC9W3/HDR_PRI/unload/img.unl'

append

into table img

( IMG CHAR(1000000) )

 

$  sqlldr userid=scott/tiger control='./img.ctl'

 

SQL*Loader: Release 11.2.0.1.0 - Production on Tue Nov 22 10:51:25 2016

 

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

 

Commit point reached - logical record count 1

 

그리고 입력된 hex string 을 4000바이트씩 자른 후, hextoraw 함수로 변환하는 것입니다.

hextoraw 함수는 CHAR, VARCHAR2, NCHAR, NVARCHAR2 타입만 지원하므로 잘라서 처리해야 합니다.

SQL> create table test_lob (img blob);

 

Table created.

 

insert into test_lob select hextoblob(img) from img;

 

1 row created.

 


참조 사이트:

http://stackoverflow.com/questions/8549138/oracle-rawtohex-function-what-happens-if-return-value-exceeds-varchar2-limit

728x90
728x90

환경

MySQL : 5.0.89, AIX 6.1

Informix : 11.50.FC9, AIX 6.1


MySQL의 BLOB데이터를 Informix로 마이그레이션 해보았습니다.


샘플 테이블 및 데이터 생성 (MySQL)

echo "create table blotest(a int, b blob)" | mysql -u root -p1nfra test

echo "insert into blobtest values (2,load_file('/home/mysql/logo.gif'))" | mysql -u user -ppasswd test


처음에는 mysqldump의 --hex-blob, --tab 옵션으로 데이터를 추출하였으나 구분자가 있는 형태로 추출했을 때 hex형태로 추출되지 않아

아래와 같이 OUTFILE문으로 추출했습니다.

echo "SELECT a,hex(b) INTO OUTFILE '/home/mysql/blobtest.txt'  FIELDS TERMINATED BY '|'      LINES TERMINATED BY '|\n'     FROM blobtest;" | mysql -u user -ppasswd test


위와 같이 MySQL에서 OUTFILE로 데이터를 추출하면 NULL값은 \N으로 추출되기 때문에 이에대한 처리가 필요합니다.

그리고 인포믹스의 구분자 파일에는 레코드 끝에 구분자가 있으므로 LINES TERMINTAED BY를 '|\n' 으로 했습니다.

MySQL에서는 hex값의 알파벳이 대문자로 추출되는 반면 인포믹스는 소문자로 추출되는데, 로드할 때 문제는 없었습니다.



인포믹스에 BLOB 데이터를 입력할 테이블 생성 (Informix)

echo "create table blobtest (a byte)" | dbaccess stores_demo

echo "create table blobtest1 (a blob)" | dbaccess stores_demo


인포믹스에 BLOB 타입에 입력할때는 구분자 파일과 BLOB파일이 별도로 존재하므로 우선 BYTE 타입에 먼저 입력후 BLOB으로 변환하여

다시 입력하는 순서로 진행했습니다.


echo "load from /home/mysql/blobtest.txt insert into blobtest" | dbaccess stores_Demo

echo "insert into blobtest1 select b::blob from blobtest" | dbaccess stores_demo


GUI 툴로 확인한 결과 이미지가 잘 입력되었음을 확인할 수 있었습니다.




How to migrate large blob table from mysql to postgresql?

http://dba.stackexchange.com/questions/4211/how-to-migrate-large-blob-table-from-mysql-to-postgresql


Migrate a database from MySQL to IBM Informix Innovator-C Edition, Part 1: Comparing MySQL to IBM Informix Innovator-C Edition

http://www.ibm.com/developerworks/data/library/techarticle/dm-1102mysqltoinnovatorc/


Migrate a database from MySQL to IBM Informix Innovator-C Edition, Part 2: Step-by-step walk-through of the migration process

http://www.ibm.com/developerworks/data/tutorials/dm-1102mysqltoinnovatorc2/index.html





728x90

+ Recent posts