1 Prerrequisites
The installation of Informix service requires Java 1.8.0.
And the libncurses and libaio library as well:
dnf install ncurses-compat-libs libaio
2 Check and fix 'in-place alters'
Informix uses in-place alters to speed up database schema changes whenever possible.
New rows adopt the new schema definition, old rows do not change, therefore conversion is faster.
Recommend resolving in-place alters before an upgrade.
Run 'oncheck -pt' command to identify which tables were altered in the current version. Qualifying tables must have tblspace flag 0x800000 set. For example:
# oncheck -pt tdb:tab1
TBLspace Report for tdb:dmitriyr.tab1
Table fragment partition par1 in DBspace dbs1
Physical Address 2:5
Creation date 06/25/2012 11:58:16
TBLspace Flags 800802 Row Locking
TBLspace use 4 bit bit-maps
...
As an alternative to 'oncheck -pt' you may run the following query against the Informix sysmaster database to find all qualifying tables:
SELECT ta.dbsname, ta.tabname, pt.partnum, HEX(pt.flags) flag FROM sysmaster:systabnames ta, sysmaster:sysptnhdr pt WHERE ta.partnum = pt.partnum AND BIT_AND(HEX(pt.flags),'00800000'::BINARYVAR) = '00800000';
dbsname tdb
tabname tab1
partnum 2097154
flag 0x00800802
In above examples tblspace flag value is 0x800802. It is clear that value 0x800000 is set here.
Run oncheck against those tables identified in p.1 to find which tables have outstanding in-place alters. You must look at "Home Data Page Version Summary" section. For example:
# oncheck -pT [database]:[table]
...
Home Data Page Version Summary
Version Count
0 (oldest) 25
1 (current) 15
...
In the above example there are 25 pages to be altered to a new version. That means that a dummy update is required to be executed against that table. For example, to create a dummy update, specify:
UPDATE tab1 SET col1=col1 WHERE 1=1;
Update a numeric data type
You must ensure that the column selected is a numeric data type (for example, INTEGER of SMALLINT) and not a character data type.
Dummy UPDATE statements force any outstanding in-place alters to complete by updating the rows in the affected tables. To generate a dummy UPDATE statement, create an UPDATE statement in which a column in the table is set to its own value. This forces the row to be updated to the latest schema without actually changing column values. Because the database server always alters rows to the latest schema, a single pass through the table that updates all rows completes all outstanding in-place alters.
The steps to perform a dummy update is explained in detail within the migration guide.
2.1 Get all pending IPAs
The next function returns a list with tables of all databases in the instance that has rows with an old schema. Compile this funcion in any database and then execute it.
CREATE FUNCTION get_pending_ipa() RETURNING VARCHAR(128) as database, VARCHAR(128) as table, VARCHAR(128) as partition, VARCHAR(9) as obj_type, INTEGER as partnum, INTEGER as lockid, SMALLINT as version, INTEGER as npages -- For version 7.x use this header instead: --CREATE PROCEDURE get_pending_ipa() RETURNING VARCHAR(128), VARCHAR(128), VARCHAR(128), VARCHAR(9), INTEGER, INTEGER, SMALLINT, INTEGER; -- Name: $RCSfile: get_pending_ipa.sql,v $ -- CVS file: $Source: /usr/local/cvs/stable/informix/queries/get_pending_ipa.sql,v $ -- CVS id: $Header: /usr/local/cvs/stable/informix/queries/get_pending_ipa.sql,v 1.5 2011/09/09 20:57:31 fnunes Exp $ -- Revision: $Revision: 1.5 $ -- Revised on: $Date: 2011/09/09 20:57:31 $ -- Revised by: $Author: fnunes $ -- Support: Fernando Nunes - domusonline@gmail.com -- Licence: This script is licensed as GPL ( http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html ) -- Variables holding the database,tabnames and partnum DEFINE v_dbsname, v_old_dbsname LIKE sysmaster:systabnames.dbsname; DEFINE v_tabname, v_partname, v_old_tabname LIKE sysmaster:systabnames.tabname; DEFINE v_partnum, v_old_partnum LIKE sysmaster:syspaghdr.pg_partnum; DEFINE v_lockid, v_old_lockid LIKE sysmaster:sysptnhdr.lockid; DEFINE v_pg_next INTEGER; DEFINE v_pg_partnum INTEGER; DEFINE v_obj_type VARCHAR(9); -- Variables holding the various table versions and respective number of pages pending to migrate DEFINE v_version SMALLINT; DEFINE v_pages INTEGER; -- Hexadecimal representation of version and pending number of pages DEFINE v_char_version CHAR(6); DEFINE v_char_pages CHAR(10); DEFINE v_aux_char CHAR(8); -- Hexadecimal representation of the slot 6 data. Each 16 bytes will appear as a record that needs to be concatenated DEFINE v_hexdata VARCHAR(128); -- Variable to hold the sysmaster:syssltdat hexadecimal representation of each 16 bytes of the slot data DEFINE v_slot_hexdata CHAR(40); DEFINE v_aux VARCHAR(128); DEFINE v_endian CHAR(6); DEFINE v_offset SMALLINT; DEFINE v_slotoff SMALLINT; DEFINE v_dummy INTEGER; -- In case we need to trace the function... Uncomment the following two lines --SET DEBUG FILE TO "/tmp/get_pending_ipa.dbg"; --TRACE ON; -- Now lets find out the Endianess ( http://en.wikipedia.org/wiki/Endianness ) of this platform -- The data in sysmaster:syssltdat will be different because of possible byte swap -- Read the first slot of the rootdbs TBLSpace tblspace (0x00100001) -- The first 4 bytes hold the partition number (0x00100001) SELECT s.hexdata[1,8] INTO v_hexdata FROM sysmaster:syssltdat s WHERE s.partnum = '0x100001' AND s.pagenum = 1 AND s.slotnum = 1 AND s.slotoff = 0; IF v_hexdata = '01001000' THEN -- Byte swap order, so we're little Endian (Intel, Tru64....) LET v_endian = 'LITTLE'; ELSE IF v_hexdata = '00100001' THEN -- Just as we write it (no byte swap), so we're big Endian (Sparc, Power, Itanium...) LET v_endian = 'BIG'; ELSE -- Just in case something weird (like a bug(!) or physical modification) happened RAISE EXCEPTION -746, 0, 'Invalid Endianess calculation... Check procedure code!!!'; END IF END IF -- Flags to mark the beginning LET v_hexdata = "-"; LET v_old_dbsname = "-"; LET v_old_tabname = "-"; -- The information we want for each version description will occupy this number of characters -- in the sysmaster:syssltdat.hexdata notation (after removing spaces). The size depends on the engine version. LET v_offset=DBINFO('version','major'); IF v_offset >= 10 THEN LET v_offset = 48; ELSE LET v_offset = 40; END IF LET v_old_lockid = -1; FOREACH -- This query will browse through all the instance partitions, excluding sysmaster database, and will look for -- any extended partition header (where partition header "next" field is not 0) -- the ABS(...) is just a trick to make partnums that are equal to lock id appear at the end SELECT t.dbsname, t.tabname, t1.tabname, t.partnum, p.pg_partnum, p.pg_next, h.lockid, ABS(h.lockid - h.partnum) INTO v_dbsname, v_partname ,v_tabname, v_partnum, v_pg_partnum, v_pg_next, v_lockid, v_dummy FROM sysmaster:systabnames t, sysmaster:syspaghdr p, sysmaster:sysptnhdr h, sysmaster:systabnames t1 WHERE p.pg_partnum = sysmaster:partaddr(sysmaster:partdbsnum(t.partnum),1) AND p.pg_pagenum = sysmaster:partpagenum(t.partnum) AND t.dbsname NOT IN ('sysmaster') AND h.partnum = t.partnum AND t1.partnum = h.lockid AND p.pg_next != 0 ORDER BY t.dbsname, t.tabname, 8 DESC, t.partnum IF v_lockid = v_partnum THEN IF v_lockid = v_old_lockid THEN LET v_obj_type = "Part Main"; ELSE LET v_obj_type = "Table"; END IF ELSE LET v_obj_type = "Part"; END IF LET v_old_lockid = v_lockid; WHILE v_pg_next != 0 -- Find if we're dealing with a fragmented table or not... -- While this extended partition page points to another one... -- Get all the slot 6 data (where the version metadata is stored - version, number of pages, descriptor page etc. FOREACH SELECT REPLACE(s.hexdata, ' '), s.slotoff, p.pg_next INTO v_slot_hexdata, v_slotoff, v_pg_next FROM sysmaster:syspaghdr p, sysmaster:syssltdat s WHERE s.partnum = p.pg_partnum AND s.pagenum = p.pg_pagenum AND s.slotnum = 6 AND p.pg_partnum = v_pg_partnum AND p.pg_pagenum = v_pg_next IF ( v_dbsname != v_old_dbsname OR v_tabname != v_old_tabname OR v_partnum != v_old_partnum) THEN LET v_old_dbsname = v_dbsname; LET v_old_tabname = v_tabname; LET v_old_partnum = v_partnum; -- First iteraction for each table LET v_hexdata = v_slot_hexdata; ELSE -- Next iteractions for each table LET v_hexdata = TRIM(v_hexdata) || v_slot_hexdata; IF LENGTH(v_hexdata) >= v_offset THEN -- We already have enough data for a version within a table -- Note that we probably have part of the next version description in v_hexdata -- So we need to copy part of it, and keep the rest for next iteractions LET v_aux=v_hexdata; LET v_hexdata=SUBSTR(v_aux,v_offset+1,LENGTH(v_aux)-v_offset); -- Split the version and number of pending pages part... LET v_char_version = v_aux[1,4]; LET v_char_pages = v_aux[9,16]; -- Create a usable hex number. Prefix it with '0x' and convert due to little endian if that's the case IF v_endian = "BIG" THEN LET v_char_version = '0x'||v_char_version; LET v_char_pages = '0x'||v_char_pages; ELSE LET v_aux_char = v_char_version; LET v_char_version[5]=v_aux_char[1]; LET v_char_version[6]=v_aux_char[2]; LET v_char_version[4]=v_aux_char[4]; LET v_char_version[3]=v_aux_char[3]; LET v_char_version[2]='x'; LET v_char_version[1]='0'; LET v_aux_char = v_char_pages; LET v_char_pages[9]=v_aux_char[1]; LET v_char_pages[10]=v_aux_char[2]; LET v_char_pages[7]=v_aux_char[3]; LET v_char_pages[8]=v_aux_char[4]; LET v_char_pages[6]=v_aux_char[6]; LET v_char_pages[5]=v_aux_char[5]; LET v_char_pages[3]=v_aux_char[7]; LET v_char_pages[4]=v_aux_char[8]; LET v_char_pages[2]='x'; LET v_char_pages[1]='0'; END IF -- HEX into DEC (integer) LET v_version = TRUNC(v_char_version + 0); LET v_pages = TRUNC(v_char_pages + 0); IF v_pages > 0 THEN -- This version has pending pages so show it... RETURN TRIM(v_dbsname), TRIM(v_tabname), TRIM(v_partname), TRIM(v_obj_type), v_partnum, v_lockid, v_version, v_pages WITH RESUME; END IF END IF END IF END FOREACH IF LENGTH(v_hexdata) >= v_offset THEN -- If we still have data to process... LET v_aux=v_hexdata; LET v_char_version = v_aux[1,4]; LET v_char_pages = v_aux[9,16]; IF v_endian = "BIG" THEN LET v_char_version = '0x'||v_char_version; LET v_char_pages = '0x'||v_char_pages; ELSE LET v_aux_char = v_char_version; LET v_char_version[5]=v_aux_char[1]; LET v_char_version[6]=v_aux_char[2]; LET v_char_version[4]=v_aux_char[4]; LET v_char_version[3]=v_aux_char[3]; LET v_char_version[2]='x'; LET v_char_version[1]='0'; LET v_aux_char = v_char_pages; LET v_char_pages[9]=v_aux_char[1]; LET v_char_pages[10]=v_aux_char[2]; LET v_char_pages[7]=v_aux_char[3]; LET v_char_pages[8]=v_aux_char[4]; LET v_char_pages[6]=v_aux_char[6]; LET v_char_pages[5]=v_aux_char[5]; LET v_char_pages[3]=v_aux_char[7]; LET v_char_pages[4]=v_aux_char[8]; LET v_char_pages[2]='x'; LET v_char_pages[1]='0'; END IF -- HEX into DEC (integer) LET v_version = TRUNC(v_char_version + 0); LET v_pages = TRUNC(v_char_pages + 0); IF v_pages > 0 THEN -- This version has pending pages so show it... RETURN TRIM(v_dbsname), TRIM(v_tabname), TRIM(v_partname), TRIM(v_obj_type), v_partnum, v_lockid, v_version, v_pages WITH RESUME; END IF END IF END WHILE END FOREACH; END FUNCTION; -- For version 7.x use this close statement instead: --END PROCEDURE;
execute function get_pending_ipa();
2.2 Resolve outstanding in-place alter operations
2.2.1 From version 12.10.xC4 or later
If you are reverting from version 12.10.xC4 or later, you can remove in-place alter operations by running the admin( ) or task( ) SQL administration command with the table update_ipa or fragment update_ipa argument. You can include the parallel option to run the operation in parallel. For example, the following statement removes in-place alter operations in parallel from a table that is named "mytable" at database "mydb":
database sysadmin; EXECUTE FUNCTION task('table update_ipa parallel','mytable','mydb');
2.2.2 From an earlier version of 12.10.xC4
If you are reverting from an earlier version of 12.10, you can resolve outstanding in-place alter operations by running dummy UPDATE statements. Dummy UPDATE statements force any outstanding in-place alter operations to complete by updating the rows in the affected tables. To generate a dummy UPDATE statement, create an UPDATE statement in which a column in the table is set to its own value. This forces the row to be updated to the latest schema without changing column values. Because the database server always alters rows to the latest schema, a single pass through the table that updates all rows completes all outstanding in-place alter operations.
The dummy UPDATE statement differs from a standard UPDATE statement because it does not change the data. A standard UPDATE statement usually changes the value of the affected row. For example, to create a dummy update, specify:
UPDATE tab1 SET col1=col1 WHERE 1=1;
You must ensure that the column selected is a numeric data type (for example, INTEGER of SMALLINT) and not a character data type (or failing that, a char(1) or a char as small as possible).
Updating big tables
The direct UPDATE on large tables can be produce a LONG TRANSACTION. In order to avoid it, you can use the following procedure indicating the table and field for each case.
CREATE PROCEDURE "informix".dei_dummyupdate(p_tabname CHAR, p_fieldname CHAR) DEFINE numrow SMALLINT; DEFINE fieldv CHAR; LET numrow = 0; FOREACH sal_cursor WITH HOLD FOR SELECT p_fieldname INTO fieldv FROM p_tabname IF numrow = 0 THEN BEGIN WORK; END IF LET numrow = numrow + 1; UPDATE p_tabname SET p_fieldname = p_fieldname WHERE CURRENT OF sal_cursor; IF numrow = 10000 THEN COMMIT WORK; LET numrow = 0; END IF END FOREACH IF numrow > 0 AND numrow < 10000 THEN COMMIT WORK; END IF END PROCEDURE;
Execute this procedure for each table and field
execute procedure dei_updrows(tabname, fieldname);
3 Ensure the scheduler is enabled
Informix upgrades datablade modules using the scheduler. Ensure the scheduler is not stopped, removing the file if exists:
rm $INFORMIXDIR/etc/sysadmin/stop
And then disable auto statistics tasks.
You can execute the following update to enable the auto statistics tasks:
dbaccess sysadmin; UPDATE ph_task SET tk_enable='t' WHERE tk_name LIKE '%Statistics%';
Review the status of the sysadmin database statistics tasks.
dbaccess sysadmin; SELECT tk_enable FROM ph_task WHERE tk_name LIKE '%Statistics%';
4 Backup of the logical logs
Backup of the logical logs
Ensure the logical logs are backed up.
If the logical logs are not backed up the conversion from previous version will fail.
23:43:20 Initialization of Conversion Session 23:43:20 The restore point ended and related data in directory /home/informix/tmp/0 were removed. 23:43:21 Conversion halted because logs are not backed up. To continue conversion it is necessary to restart prior server and backup logical logs. 23:43:21 Conversion failed. 23:43:21 FAILED 23:43:21 Restart conversion after fixing the problem.
5 Disable the service
To prevent a poosible restart service done from systemd while the version is upgraded, is necessary to disable informix as service:
As root user execute:
systemctl disable informix
6 Shuts down the database server gracefully
If exists "open transaction" the conversion can not be continue:
23:25:19 An open transaction was detected when the database server changed log versions. Start the previous version of the database server in quiescent mode and then shut down the server gracefully, before migrating to this version of the server. 23:25:19 Cannot Rollforward from Checkpoint.
Shutsdowan gracefully to ensure close open transactions
The service must be stopped before do the new installation. Do a checkpoint before and ensure that there is no sessions either transactions open.
onmode -c
onmode -s
Stops the service
onmode -ky
And then starts in quiescent mode:
oninit -s
Stops the service
onmode -ky
7 Preserving previous version
If there is a previous version of Informix installed you must preserve the content:
cp -Rp $INFORMIXDIR ${INFORMIXDIR}_old
8 Installation
Run the Informix development installer to install the 14.10 Informix.
tar xvf INFORMIX_DEV_ED_14.10.FC1_Linux.tar
And install the software as user root. Make sure the $INFORMIXDIR is set to the correct path and ensure that is the same used on the proccess of installation:
su - ./ids_install
The development version has limi of 2GB of memory.
Last installation step
At the last step before confirm the installation ensure that the Informix is not running.
=============================================================================== Ready To Install ---------------- InstallAnywhere is now ready to install IBM Informix Software Bundle onto your system at the following location: /home/informix PRESS <ENTER> TO INSTALL:
onstat -
Shared memory is not initialized
9 Licensing the product
Upon the software is installed run the Informix edition installer to switch the 14.10 Informix installation from one edition to another (sample based on Enterprise Edition). As user informix:.
su - informix unzip INFORMIX_EE_License_Ins_14.10.FC1.zip
Make sure the $INFORMIXDIR is set to the correct path and ensure that is the same used on the proccess of installation:
$HOME_JAVA8/bin/java -jar ee_edition.jar
10 Start informix
Now you can setart informix, and auto-upgraded will be executed
As user informix execute:
oninit -v
11 Enable the service
If the service was disabled, you can enable it again.
As user informix execute
onmode -c onmode -s onmode -ky
As root user execute:
systemctl enable informix systemctl start informix