我正面临一些锁超时问题,我需要更好的工具来找到根本原因。考虑到IBM堆栈、WebSphere 8.5和DB2 10.5,并给出如下锁信息:
Lock Information:
Lock Name: 000301230000000008C0000252
Lock Type: Basic RECORD lock(DMS/IXM)
Lock Specifics: (obj={4;511}, rid=d(0;2440;6), x0000000002A00001)
Lock Requestor:
...
Requesting Agent ID: 28648
Coordinator Agent ID: 28648
...
Lock Owner (Representative):
...
Requesting Agent ID: 295623
Coordinator Agent ID: 295623
...
并且给定我有两个JDBC事务,一个持有锁,另一个等待锁被释放,我如何以编程方式从JDBC连接(例如Agent ID)获取事务信息,以在我的应用程序中诊断哪个JDBC连接实例持有锁?假设我有一个多线程、多服务器的环境。
关于Oracle, SQLServer和PostgreSQL,我看到了一个类似的问题,在这个链接:如何使用JDBC或Hibernate获得当前数据库事务id ?但是我没有找到任何关于DB2 的信息。要排除锁定原因,我需要找到:
- 锁定表的SQL
- 等待锁释放的SQL
- 上述sql中涉及的绑定参数(数据)
从SYSIBMADM开始。MON_LOCKWAITS观点。
MON_GET_APPL_LOCKWAIT
MON_GET_CONNECTION 如果您需要有关参与应用程序的更多信息,您可以使用此视图直接基于的监视表函数:
SELECT
-- locked table
CASE WHEN L.TBSP_ID > 0 THEN T.TABSCHEMA ELSE S.TABSCHEMA END AS TABSCHEMA
, CASE WHEN L.TBSP_ID > 0 THEN T.TABNAME ELSE S.TABNAME END AS TABNAME
, CASE WHEN L.TBSP_ID > 0 THEN T.DATA_PARTITION_ID ELSE -1 END AS DATA_PARTITION_ID
--, L.* -- lock info
, H.CLIENT_HOSTNAME -- holder connection info
, HC.STMT_TEXT AS HLD_STMT_TEXT_CURR -- holder's currently executing statement
, HL.STMT_TEXT AS HLD_STMT_TEXT_LAST -- holder's last executed statement
, R.CLIENT_HOSTNAME -- requester connection info
, RC.STMT_TEXT AS REQ_STMT_TEXT_CURR -- requester's current statement
FROM TABLE (MON_GET_APPL_LOCKWAIT (NULL, -2)) L
LEFT JOIN TABLE (MON_GET_TABLE (NULL, NULL, L.HLD_MEMBER)) T ON T.TBSP_ID = L.TBSP_ID AND T.TAB_FILE_ID = L.TAB_FILE_ID
LEFT JOIN SYSCAT.TABLES S ON S.TBSPACEID = L.TBSP_ID AND S.TABLEID = L.TAB_FILE_ID
-- Holder's info
LEFT JOIN TABLE (MON_GET_CONNECTION (L.HLD_APPLICATION_HANDLE, L.HLD_MEMBER)) H ON 1=1
LEFT JOIN TABLE (MON_GET_ACTIVITY (L.HLD_APPLICATION_HANDLE, L.HLD_MEMBER)) HC ON 1=1
LEFT JOIN TABLE (MON_GET_UNIT_OF_WORK (L.HLD_APPLICATION_HANDLE, L.HLD_MEMBER)) HU ON 1=1
LEFT JOIN TABLE (MON_GET_PKG_CACHE_STMT (NULL, HU.LAST_EXECUTABLE_ID, NULL, L.HLD_MEMBER)) HL ON 1=1
-- Requester's info
LEFT JOIN TABLE (MON_GET_CONNECTION (L.REQ_APPLICATION_HANDLE, L.REQ_MEMBER)) R ON 1=1
LEFT JOIN TABLE (MON_GET_PKG_CACHE_STMT (NULL, L.REQ_EXECUTABLE_ID, NULL, L.REQ_MEMBER)) RC ON 1=1
指出:
- 您无法获得放置锁的语句,请求者正在等待该语句。锁和在Db2中放置该锁的语句之间没有显式绑定。你可以得到一个当前的对账单(如果有的话)和上次完成的对账单为上述持有人。
- 你不能通过上面的查询获得所有返回语句的参数值。
要获得关于锁等待/超时事件的更多信息,您可以创建一个用于锁定的事件监视器——某种"记录器";对于lockwait、locktimeout、死锁事件。相应的信息被写入为此监视器创建的数据库表中。有关锁定事件监视器主题,请参阅写入表的信息。这些表中的数据量取决于数据库配置参数的设置:
锁超时事件(MON_LOCKTIMEOUT) = HIST_AND_VALUES
锁等待事件(MON_LOCKWAIT) = HIST_AND_VALUES
锁等待事件阈值(MON_LW_THRESH) = 5000000
例如,如果像上面那样设置这些参数,那么所有3种类型事件(如果请求者等待超过5秒,将生成lockwait事件)的非常详细的信息(包括所有语句参数值)将被写入事件监视器表。
如果您有这样一个活动的事件监视器,并且至少有MON_DEADLOCK = HISTORY
,那么对于当前在服务器上运行的所有与db2pd -apinfo -db mydb
有开放事务的应用程序的整个事务历史记录,您就有一个额外的活动。
到目前为止,为了帮助我更好地诊断DB2和WebSphere锁的相关性,我发现需要执行以下操作。
首先,我需要知道哪些表被死锁了。我可以通过发出以下命令之一找到它:
> db2pd -locks showlocks -db SAMPLE
Locks:
Address TranHdl Lockname Type Mode Sts Owner Dur HoldCount Att ReleaseFlg rrIID TableNm SchemaNm
0x0000A338B812C780 15 01008800050000000000000052 RowLock ..X G 15 1 0 0x00200000 0x40000000 0 TABLE DB2INST1 03008800050000000000000052 SQLP_RECORD (obj={2;136}, rid=d(0;0;5), x0500000000000000)
0x0000A338B812C780 15 01008800000000000000000054 TableLock .IX G 15 1 0 0x00202000 0x40000000 0 TABLE DB2INST1 03008800000000000000000054 SQLP_TABLE (obj={2;136})
然后我可以根据前面命令的结果查询ROWID:
> db2 connect to SAMPLE
> db2 "select rid(TABLE), COL1, COL2 from TABLE with ur" | grep 0500000000000000
基于表中的行信息(如果in锁不会被提交),那么我可以将其与应用程序关联起来,以发现哪个服务器引起了问题。