CREATE TABLE TEST_LOCK( ID INT PRIMARY KEY, VAL VARCHAR(100) ); INSERT INTO TEST_LOCK VALUES(1,'K1'),(2,'K2'), (3,'K3'),(4,'K4'),(5,'K5'); COMMIT; -- AUTO COMMIT 是 OFF 的状态 -- 事务1 (先执行) SELECT * FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; -- 事务2 SELECT ID FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; -- 进入锁等待
SELECT K.R_ID "锁对ID", K3.ID "会话ID", CASE WHEN K.TRANS_ID = K1.TRANS_ID THEN '申请锁' WHEN K.ID1 = K1.TRANS_ID THEN '持有锁' END AS "操作", K1.TRANS_ID "事务ID", ROUND(K1.CTIME /1000000,2) "持续时间(s)", K3.INFO, K3.TOP_INFO, K3.RETRY_INFO, K3.RETRY_CNT, K2.DATABASE_NAME , K2.TABLE_NAME , K.ID3_2 "上锁行", NOW() TIME_NOW, DATE_SUB(NOW(), INTERVAL round(K1.CTIME / 1000000,3) SECOND) AS LOCK_TIME, CASE WHEN K1.ID1 = K3.TRANS_ID THEN concat( 'WITH KK AS (SELECT REQUEST_ID FROM OCEANBASE.GV$OB_SQL_AUDIT WHERE TX_ID = ', K1.ID1 ,' ) SELECT /*+ USE_NL(KK K) */K.* FROM OCEANBASE.GV$OB_SQL_AUDIT K WHERE SVR_IP = \'' , K1.SVR_IP , ''' AND SVR_PORT = ' , K1.SVR_PORT , ' AND TENANT_ID = ' , K1.TENANT_ID , ' AND REQUEST_ID IN (SELECT REQUEST_ID FROM KK) AND REQUEST_TIME IS NOT NULL AND UPPER(QUERY_SQL) LIKE \'%' , UPPER(K2.TABLE_NAME) , '%\';') END AS DO_SQL FROM (SELECT ROW_NUMBER() OVER () AS R_ID,K.TRANS_ID,K.ID1,K.ID3, SUBSTR(K.ID3,1,INSTR(K.ID3,'-')-1) AS ID3_1, SUBSTR(K.ID3,INSTR(K.ID3,'-')+1)AS ID3_2 FROM OCEANBASE.GV$OB_LOCKS K WHERE K.TYPE = 'TR' AND K.BLOCK = 1) K LEFT JOIN OCEANBASE.GV$OB_LOCKS K1 ON K.ID3 = K1.ID3 LEFT JOIN OCEANBASE.DBA_OB_TABLE_LOCATIONS K2 ON K.ID3_1 = K2.TABLET_ID AND ROLE = 'LEADER' LEFT JOIN OCEANBASE.GV$OB_PROCESSLIST K3 ON K1.TRANS_ID = K3.TRANS_ID ORDER BY K.R_ID,K1.TRANS_ID;
WITH KK AS(SELECT REQUEST_ID FROM OCEANBASE.GV$OB_SQL_AUDIT WHERE TX_ID = 14983239 ) SELECT /*+ USE_NL(KK K) */K.* FROM OCEANBASE.GV$OB_SQL_AUDIT K WHERE SVR_IP = '11.161.204.62' AND SVR_PORT = 2882 AND TENANT_ID = 1002 AND REQUEST_ID IN (SELECT REQUEST_ID FROM KK) AND REQUEST_TIME IS NOT NULL AND UPPER(QUERY_SQL) LIKE '%TEST_LOCK%';
def_table_schema(
owner = 'xiaoyi.xy',
tablegroup_id = 'OB_INVALID_ID',
table_name = '__all_virtual_sql_audit',
rowkey_columns = [
('svr_ip', 'varchar:MAX_IP_ADDR_LENGTH'),
('svr_port', 'int'),
('tenant_id', 'int'),
('request_id', 'int'),
],
normal_columns = [
...
],
partition_columns = ['svr_ip', 'svr_port'],
vtable_route_policy = 'distributed',
index = {'all_virtual_sql_audit_i1' : { 'index_columns' : ['tenant_id', 'request_id'],
'index_using_type' : 'USING_BTREE','index_table_id' : '14992','index_table_id_ora' : '19999'}},
)
-- 事务1 SELECT * FROM TEST_LOCK FOR UPDATE; -- 查看 SQL SELECT * FROM OCEANBASE.GV$OB_LOCKS;
说明: 在与研发沟通以后,后续版本将得到优化,上面红圈内的 CTIME 将保持一致,也就是抵消了行先后构造造成的 current_time 误差。
-- 创建一个存过 DELIMITER $$ CREATE PROCEDURE JINCHUAN_TEST1() BEGIN SELECT 1 ; SELECT ID FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; END$$ DELIMITER ; -- AUTO COMMIT 是 ON 的状态【这个很重要!!!!!】 SET autocommit = ON; -- 事务1 (先执行) BEGIN; SELECT * FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; -- 事务2 BEGIN; CALL JINCHUAN_TEST1; -- 进入锁等待
-- 按顺序操作事务 -- 事务1 SELECT * FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; -- 事务2 SELECT * FROM TEST_LOCK WHERE ID = 3 FOR UPDATE; SELECT * FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; -- 被事务1卡 -- 事务3 SELECT * FROM TEST_LOCK WHERE ID = 3 FOR UPDATE; -- 被事务2卡
WITH RECURSIVE ANCESTRY_PATH (START_CHILD,CURRENT_PARENT,GENERATIONS)AS( SELECT TRANS_ID, ID1, 1 FROM OCEANBASE.GV$OB_LOCKS WHERE TYPE = 'TR' AND BLOCK = 1 UNION ALL SELECT AP.START_CHILD, PC.ID1, AP.GENERATIONS + 1 FROM ANCESTRY_PATH AP JOIN OCEANBASE.GV$OB_LOCKS PC ON AP.CURRENT_PARENT = PC.TRANS_ID AND TYPE = 'TR' AND BLOCK = 1 ) SELECT AP.START_CHILD AS '等待事务ID', AP.CURRENT_PARENT AS '最终持锁事务ID', AP.GENERATIONS AS '迭代查找次数' FROM ANCESTRY_PATH AP WHERE AP.CURRENT_PARENT NOT IN( SELECT TRANS_ID FROM OCEANBASE.GV$OB_LOCKS WHERE TYPE = 'TR' AND BLOCK = 1);
-- 按顺序操作事务 -- 事务1 SELECT * FROM TEST_LOCK WHERE ID = 3 FOR UPDATE; -- 事务2 SELECT * FROM TEST_LOCK WHERE ID >= 2 FOR UPDATE; -- 被事务1卡
-- 继续执行 -- 事务3 SELECT * FROM TEST_LOCK WHERE ID = 2 FOR UPDATE;
-- 创建一个存过 DELIMITER $$ CREATE PROCEDURE JINCHUAN_TEST2() BEGIN DECLARE KA VARCHAR(200); SELECT VAL INTO KA FROM TEST_LOCK WHERE ID = 3 FOR UPDATE; UPDATE TEST_LOCK SET VAL = KA WHERE ID = 4; SELECT * FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; COMMIT; END$$ DELIMITER ; -- AUTO COMMIT 是 OFF 的状态【这个很重要!!!!!】 SET autocommit = OFF; -- 按顺序操作事务 -- 事务1 SELECT * FROM TEST_LOCK WHERE ID = 2 FOR UPDATE; -- 事务2 SELECT * FROM TEST_LOCK WHERE ID = 4 FOR UPDATE; CALL JINCHUAN_TEST2;
-- 继续执行 -- 事务3 UPDATE TEST_LOCK SET VAL = 'kkk' WHERE ID = 3; COMMIT; -- 事务1 ROLLBACK;
-- oracle 租户版查锁 SQL SELECT K.R_ID "锁对ID", K3.ID "会话ID", CASE WHEN K.TRANS_ID = K1.TRANS_ID THEN '申请锁' WHEN K.ID1 = K1.TRANS_ID THEN '持有锁' END AS "操作", K1.TRANS_ID "事务ID", ROUND(K1.CTIME /1000000,2) "持续时间", K3.INFO, K3.TOP_INFO, K3.RETRY_INFO, K3.RETRY_CNT, K2.DATABASE_NAME , K2.TABLE_NAME , K.ID3_2 "上锁行", SYSDATE TIME_NOW, (SYSTIMESTAMP - K1.CTIME / 86400000000 ) AS LOCK_TIME, CASE WHEN K1.ID1 = K3.TRANS_ID THEN 'WITH KK AS (SELECT REQUEST_ID FROM GV$OB_SQL_AUDIT WHERE TX_ID = ' || K1.ID1 || ' ) SELECT /*+ USE_NL(KK K) */ K.* FROM GV$OB_SQL_AUDIT K WHERE SVR_IP = ''' || K1.SVR_IP || ''' AND SVR_PORT = ' || K1.SVR_PORT || ' AND TENANT_ID = ' || K1.TENANT_ID || ' AND REQUEST_ID IN (SELECT REQUEST_ID FROM KK) AND REQUEST_TIME IS NOT NULL AND UPPER(QUERY_SQL) LIKE ''%' || K2.TABLE_NAME || '%'';' END AS DO_SQL FROM (SELECT ROWNUM AS R_ID,K.TRANS_ID,K.ID1,K.ID3, SUBSTR(K.ID3,1,INSTR(K.ID3,'-')-1) AS ID3_1, SUBSTR(K.ID3,INSTR(K.ID3,'-')+1)AS ID3_2 FROM GV$OB_LOCKS K WHERE K.TYPE = 'TR' AND K.BLOCK = 1) K LEFT JOIN GV$OB_LOCKS K1 ON K.ID3 = K1.ID3 LEFT JOIN DBA_OB_TABLE_LOCATIONS K2 ON K.ID3_1 = K2.TABLET_ID AND ROLE = 'LEADER' LEFT JOIN GV$OB_PROCESSLIST K3 ON K1.TRANS_ID = K3.TRANS_ID ORDER BY K.R_ID,K1.TRANS_ID; -- 递归找锁源头的 SQL WITH ANCESTRY_PATH (START_CHILD,CURRENT_PARENT,GENERATIONS)AS( SELECT TRANS_ID, ID1, 1 FROM GV$OB_LOCKS WHERE TYPE = 'TR' AND BLOCK = 1 UNION ALL SELECT AP.START_CHILD, PC.ID1, AP.GENERATIONS + 1 FROM ANCESTRY_PATH AP JOIN GV$OB_LOCKS PC ON AP.CURRENT_PARENT = PC.TRANS_ID AND TYPE = 'TR' AND BLOCK = 1 ) SELECT AP.START_CHILD AS "等待事务ID", AP.CURRENT_PARENT AS "最终持锁事务ID", AP.GENERATIONS AS "迭代查找次数" FROM ANCESTRY_PATH AP WHERE AP.CURRENT_PARENT NOT IN( SELECT TRANS_ID FROM GV$OB_LOCKS WHERE TYPE = 'TR' AND BLOCK = 1);
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69909943/viewspace-3174497/ ,如需转载,请注明出处,否则将追究法律责任。