Connect with Db2, Informix, Netezza, open source, and other data experts to gain value from your data, share insights, and solve problems.
Posted by: Serge RielauDB2 provides a whole set of tools to analyze locks, but what is missing is a way to connect LOCKs easily with actual rows.
CREATE TABLE products(prodid INTEGER NOT NULL PRIMARY KEY, prodname VARCHAR(20), prodline VARCHAR(20)) PARTITION BY RANGE (prodline) (PARTITION A_TO_L STARTING MINVALUE ENDING AT 'L' EXCLUSIVE, PARTITION L_TO_Z STARTING FROM 'L' ENDING AT MAXVALUE); INSERT INTO products(prodid, prodname, prodline) VALUES(1, 'Computer', 'Electronics'),(2, 'Vacuum Cleaner', 'Appliances'),(3, 'Pants', 'Clothing'),(4, 'Washer Fluid', 'Automotive'),(5, 'Pills', 'Drugs'),(6, 'Teddy Bear', 'Toys'),(7, 'Doll', 'Toys');
UPDATE COMMAND OPTIONS USING C OFF;SELECT RID(products) as RID, products.* FROM products WHERE prodid = 6 WITH RS USE AND KEEP UPDATE LOCKS;RID PRODID PRODNAME PRODLINE-------------------- ----------- -------------------- -------------------- 281474976710660 6 Teddy Bear Toys 1 record(s) selected.
db2pd -db test -locks;Database Partition 0 -- Database TEST -- Active -- Up 0 days 08:40:36 -- Date 12/18/2011 18:17:18Locks:Address TranHdl Lockname Type Mode Sts Owner Dur HoldCount Att ReleaseFlg rrIID0x7F58EB80 2 FAFF0080040000000000010052 Row ..U G 2 1 0 0x00000000 0x00000001 00x7F586580 2 4141414141464462081C83B441 Internal P ..S G 2 1 0 0x00000000 0x40000000 00x7F585A80 2 FAFF0080000000000000FFFF54 Table .IX G 2 1 0 0x00002000 0x00000001 00x7F581B80 2 FAFF0080000000000000010054 Partition .IX G 2 1 0 0x00002000 0x00000001 0
SELECT LOCK_NAME, MEMBER FROM TABLE(MON_GET_LOCKS('<application_handle>' || MON_GET_APPLICATION_HANDLE() || '</application_handle>', -2));LOCK_NAME MEMBER-------------------------------- ------FAFF0080040000000000010052 001000000010000000100A04956 04141414141464462081C83B441 0FAFF0080000000000000FFFF54 0FAFF0080000000000000010054 0 5 record(s) selected.
SELECT VARCHAR(name, 30) AS name, VARCHAR(value, 30) AS valueFROM TABLE(MON_FORMAT_LOCK_NAME('FAFF0080040000000000010052'));NAME VALUE------------------------------ ------------------------------LOCK_OBJECT_TYPE ROWROWID 4DATA_PARTITION_ID 1PAGEID 0TABSCHEMA SERGETABNAME PRODUCTS 6 record(s) selected.
DATA_PARTITION_ID * POWER(2,48) + PAGEID * POWER(2,16) + ROWID.
CREATE OR REPLACE FUNCTION TO_RID(DATA_PARTITION_ID INTEGER, PAGEID BIGINT, ROWID INTEGER) RETURNS BIGINT SPECIFIC TO_RID CONTAINS SQL DETERMINISTIC NO EXTERNAL ACTION RETURN DATA_PARTITION_ID * POWER(BIGINT(2),48) + PAGEID * POWER(BIGINT(2),16) + ROWID;VALUES TO_RID(1, 0, 4);1-------------------- 281474976710660 1 record(s) selected.
SELECT * FROM products WHERE RID(products) = 281474976710660;PRODID PRODNAME PRODLINE----------- -------------------- -------------------- 6 Teddy Bear Toys 1 record(s) selected.
--#SET TERMINATOR @CREATE OR REPLACE PROCEDURE LOCKTOROW(IN lock VARCHAR(32), OUT tabschema VARCHAR(128), OUT tabname VARCHAR(128), IN mode VARCHAR(10) DEFAULT ('SHORT'), IN member SMALLINT DEFAULT (0)) SPECIFIC LOCKTOROW READS SQL DATA NOT DETERMINISTIC NO EXTERNAL ACTION DYNAMIC RESULT SETS 1BEGIN DECLARE stmttxt VARCHAR(32000); DECLARE colname VARCHAR(128); DECLARE lock_object_type VARCHAR(255); DECLARE data_partition_id BIGINT; DECLARE rid BIGINT DEFAULT NULL; DECLARE pageid BIGINT; DECLARE stmt STATEMENT; DECLARE res CURSOR WITH RETURN TO CALLER FOR stmt; SET mode = UPPER(mode); IF mode NOT IN ('LONG', 'SHORT') THEN SIGNAL SQLSTATE '78000' SET MESSAGE_TEXT = 'Unknown mode [LONG|SHORT]'; END IF; SELECT MAX(CASE WHEN NAME = 'LOCK_OBJECT_TYPE' THEN VALUE END), MAX(CASE WHEN NAME = 'ROWID' THEN VALUE END), MAX(CASE WHEN NAME = 'TABSCHEMA' THEN VALUE END), MAX(CASE WHEN NAME = 'TABNAME' THEN VALUE END), MAX(CASE WHEN NAME = 'DATA_PARTITION_ID' THEN VALUE END), MAX(CASE WHEN NAME = 'PAGEID' THEN VALUE END) INTO lock_object_type, rid, tabschema, tabname, data_partition_id, pageid FROM TABLE(MON_FORMAT_LOCK_NAME(lock)); IF rid IS NULL THEN SIGNAL SQLSTATE '78000' SET MESSAGE_TEXT = 'Lock not found'; END IF; IF lock_object_type <> 'ROW' THEN SIGNAL SQLSTATE '78000' SET MESSAGE_TEXT = 'Not a ROW lock'; END IF; SET colname = (SELECT colname FROM SYSCAT.COLUMNS WHERE TABNAME = locktorow.tabname AND TABSCHEMA = locktorow.tabschema AND colno = 0); IF mode = 'LONG' THEN SET stmttxt = 'SELECT * FROM "' || tabschema || '"."' || tabname || '" AS T' || ' WHERE RID(T) = ?' || ' AND DBPARTITIONNUM(T."' || colname || '") = ? WITH UR'; ELSE SET stmttxt = 'SELECT '; FOR col AS SELECT COLNAME, TYPESCHEMA, TYPENAME, LENGTH FROM SYSCAT.COLUMNS WHERE TABNAME = locktorow.tabname AND TABSCHEMA = locktorow.tabschema ORDER BY colno DO IF TYPESCHEMA = 'SYSIBM ' AND TYPENAME IN ('VARCHAR', 'VARGRAPHIC', 'CLOB', 'BLOB', 'DBCLOB') AND LENGTH > 30 THEN SET stmttxt = stmttxt || 'SUBSTR("' || colname || '", 1, 30) AS "' || colname || '", '; ELSE SET stmttxt = stmttxt || '"' || colname || '", '; END IF; END FOR; SET stmttxt = SUBSTR(stmttxt, 1, LENGTH(stmttxt) - 2) || ' FROM "' || tabschema || '"."' || tabname || '" AS T' || ' WHERE RID(T) = ?' || ' AND DBPARTITIONNUM(T."' || colname || '") = ? WITH UR'; END IF; PREPARE stmt FROM stmttxt; OPEN res USING data_partition_id * power(bigint(2),48) + pageid * power(bigint(2),16) + rid, member;END@--#SET TERMINATOR ;CALL LOCKTOROW('FAFF0080040000000000010052', ?, ?); Value of output parameters -------------------------- Parameter Name : TABSCHEMA Parameter Value : SERGE Parameter Name : TABNAME Parameter Value : PRODUCTS Result set 1 -------------- PRODID PRODNAME PRODLINE ----------- -------------------- -------------------- 6 Teddy Bear Toys 1 record(s) selected.
CALL LOCKTOROW('FAFF0080040000000000010052', ?, ?, 'LONG', 0); Value of output parameters -------------------------- Parameter Name : TABSCHEMA Parameter Value : SERGE Parameter Name : TABNAME Parameter Value : PRODUCTS Result set 1 -------------- PRODID PRODNAME PRODLINE ----------- -------------------- -------------------- 6 Teddy Bear Toys 1 record(s) selected. Return Status = 0