/**
* MySQL Resource - Locks
*/
import type { MySQLAdapter } from "../MySQLAdapter.js";
import type {
ResourceDefinition,
RequestContext,
} from "../../../types/index.js";
export function createLocksResource(adapter: MySQLAdapter): ResourceDefinition {
return {
uri: "mysql://locks",
name: "Lock Contention",
title: "MySQL Lock Contention",
description: "Current InnoDB lock waits and blocking transactions",
mimeType: "application/json",
annotations: {
audience: ["user", "assistant"],
priority: 0.8,
},
handler: async (_uri: string, _context: RequestContext) => {
try {
// Get current lock waits from performance_schema
const lockWaitsResult = await adapter.executeQuery(`
SELECT
r.trx_id AS waiting_trx_id,
r.trx_mysql_thread_id AS waiting_thread,
r.trx_query AS waiting_query,
b.trx_id AS blocking_trx_id,
b.trx_mysql_thread_id AS blocking_thread,
b.trx_query AS blocking_query,
TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) AS wait_seconds
FROM performance_schema.data_lock_waits w
JOIN information_schema.innodb_trx r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID
JOIN information_schema.innodb_trx b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID
LIMIT 20
`);
// Get global lock status
const lockStatusResult = await adapter.executeQuery(`
SHOW STATUS LIKE 'Innodb_row_lock%'
`);
const lockStats: Record<string, unknown> = {};
for (const row of lockStatusResult.rows ?? []) {
const varName = row["Variable_name"];
if (typeof varName === "string") {
lockStats[varName] = row["Value"];
}
}
return {
currentLockWaits: lockWaitsResult.rows?.length ?? 0,
lockWaits: lockWaitsResult.rows ?? [],
lockStatistics: lockStats,
};
} catch {
return {
currentLockWaits: 0,
lockWaits: [],
lockStatistics: {},
error: "Unable to retrieve lock information",
};
}
},
};
}