@@ -287,19 +287,31 @@ private boolean checkExistenceInLock(Database database, LockType lockType) {
287287 public void lockTablesWithIntensiveDbLock (Long dbId , List <Long > tableList , LockType lockType ) {
288288 Preconditions .checkState (lockType .equals (LockType .READ ) || lockType .equals (LockType .WRITE ));
289289 List <Long > tableListClone = new ArrayList <>(tableList );
290+ <<<<<<< HEAD
290291 if (Config .lock_manager_enabled && Config .lock_manager_enable_using_fine_granularity_lock ) {
292+ ====== =
293+ if (Config .lock_manager_enabled ) {
294+ LockType intentionType = (lockType == LockType .WRITE )
295+ ? LockType .INTENTION_EXCLUSIVE
296+ : LockType .INTENTION_SHARED ;
297+ boolean dbLockHeld = false ;
298+ List <Long > ridLockedList = new ArrayList <>();
299+ >>>>>>> f32f70b5ca ([BugFix ] Locker : rollback partial intensive -lock acquisition (#72423 ))
291300 try {
292- if (lockType == LockType .WRITE ) {
293- this .lock (dbId , LockType .INTENTION_EXCLUSIVE , 0 );
294- } else {
295- this .lock (dbId , LockType .INTENTION_SHARED , 0 );
296- }
301+ this .lock (dbId , intentionType , 0 );
302+ dbLockHeld = true ;
297303
298304 Collections .sort (tableListClone );
299305 for (Long rid : tableListClone ) {
300306 this .lock (rid , lockType , 0 );
307+ ridLockedList .add (rid );
301308 }
302309 } catch (LockException e ) {
310+ // Roll back any locks already acquired so that a partial failure
311+ // (e.g. deadlock victim selection on the second / Nth lock call)
312+ // does not leave a stranded DB intention or table lock that
313+ // would block subsequent DB-WRITE operations indefinitely.
314+ rollbackPartialIntensiveLock (dbId , intentionType , dbLockHeld , ridLockedList , lockType );
303315 throw ErrorReportException .report (ErrorCode .ERR_LOCK_ERROR , e .getMessage ());
304316 }
305317 } else {
@@ -308,6 +320,30 @@ public void lockTablesWithIntensiveDbLock(Long dbId, List<Long> tableList, LockT
308320 }
309321 }
310322
323+ /**
324+ * Best-effort rollback of a partial intensive-lock acquisition. Releases each
325+ * already-acquired lock and swallows any errors raised by individual release
326+ * calls so that the original LockException (the actual cause of the rollback)
327+ * surfaces to the caller instead of being masked by a release-side error.
328+ */
329+ private void rollbackPartialIntensiveLock (Long dbId , LockType intentionType ,
330+ boolean dbLockHeld , List <Long > ridLockedList , LockType tableLockType ) {
331+ for (Long rid : ridLockedList ) {
332+ try {
333+ this .release (rid , tableLockType );
334+ } catch (Exception releaseEx ) {
335+ LOG .warn ("Failed to release table lock {} during partial-acquire rollback" , rid , releaseEx );
336+ }
337+ }
338+ if (dbLockHeld ) {
339+ try {
340+ this .release (dbId , intentionType );
341+ } catch (Exception releaseEx ) {
342+ LOG .warn ("Failed to release DB intention lock {} during partial-acquire rollback" , dbId , releaseEx );
343+ }
344+ }
345+ }
346+
311347 /**
312348 * No need to release lock explicitly, it will be released automatically when the locker failed.
313349 */
@@ -388,15 +424,24 @@ public void unLockTableWithIntensiveDbLock(Long dbId, Long tableId, LockType loc
388424 */
389425 public void lockTableWithIntensiveDbLock (Long dbId , Long tableId , LockType lockType ) {
390426 Preconditions .checkState (lockType .equals (LockType .READ ) || lockType .equals (LockType .WRITE ));
427+ <<<<<<< HEAD
391428 if (Config .lock_manager_enabled && Config .lock_manager_enable_using_fine_granularity_lock ) {
429+ ====== =
430+ if (Config .lock_manager_enabled ) {
431+ LockType intentionType = (lockType == LockType .WRITE )
432+ ? LockType .INTENTION_EXCLUSIVE
433+ : LockType .INTENTION_SHARED ;
434+ boolean dbLockHeld = false ;
435+ >>>>>>> f32f70b5ca ([BugFix ] Locker : rollback partial intensive -lock acquisition (#72423 ))
392436 try {
393- if (lockType == LockType .WRITE ) {
394- this .lock (dbId , LockType .INTENTION_EXCLUSIVE , 0 );
395- } else {
396- this .lock (dbId , LockType .INTENTION_SHARED , 0 );
397- }
437+ this .lock (dbId , intentionType , 0 );
438+ dbLockHeld = true ;
398439 this .lock (tableId , lockType , 0 );
399440 } catch (LockException e ) {
441+ // Roll back the DB intention lock if step 1 succeeded but the
442+ // table-lock acquisition failed (e.g. deadlock victim, interrupt).
443+ // Otherwise the caller would leak an IS/IX lock on the DB.
444+ rollbackPartialIntensiveLock (dbId , intentionType , dbLockHeld , Collections .emptyList (), lockType );
400445 throw ErrorReportException .report (ErrorCode .ERR_LOCK_ERROR , e .getMessage ());
401446 }
402447 } else {
0 commit comments