Você pode implementar um comportamento "cancelar" desta maneira:
Você executa a consulta em um thread separado, que continua em execução, independentemente de o tempo limite ocorrer ou não. O tempo limite ocorre no thread principal e define uma variável como "1" marcando que ocorreu. Então você faz o que quiser no seu thread principal.
O thread de consulta, uma vez que a consulta é concluída, verifica se o tempo limite ocorreu. Se não tiver, ele faz o resto do trabalho que precisa fazer. Se TEM, apenas desbloqueia as tabelas que acabou de bloquear.
Eu sei que parece um pouco inútil, mas o período de bloqueio e desbloqueio deve ser basicamente instantâneo, e você chega o mais próximo possível do resultado desejado.