Ошибка «База данных находится на переходном этапе»

12

Сегодня я пытался восстановить базу данных поверх уже существующей базы данных, я просто щелкнул правой кнопкой мыши базу данных в SSMS -> Задачи -> Отключить, чтобы я мог восстановить базу данных.

Небольшое всплывающее окно появилось и показывалось Query Executing.....некоторое время, а затем выдало ошибку, сказав Database is in use cannot take it offline. Из которого я собрал несколько активных соединений с этой базой данных, поэтому я попытался выполнить следующий запрос

USE master
GO
ALTER DATABASE My_DatabaseName
SET OFFLINE WITH ROLLBACK IMMEDIATE
GO

Снова в этот момент SSMS показывал Query Executing.....некоторое время, а затем выдавал следующую ошибку:

Msg 5061, Level 16, State 1, Line 1
ALTER DATABASE failed because a lock could not be placed on database 'My_DatabaseName'. Try again later.
Msg 5069, Level 16, State 1, Line 1
ALTER DATABASE statement failed.

После этого я не смог подключиться к базе данных через SSMS. и когда я попытался перевести его в автономный режим с помощью SSMS, он выдал ошибку, говорящую:

Database is in Transition. Try later .....

В этот момент я просто не мог дотронуться до базы данных, и все, что я пытался, вернуло то же сообщение об ошибке Database is in Transition.

Я попал в Google и прочитал несколько вопросов, где люди сталкивались с подобной проблемой, и они рекомендовали закрыть SSMS и открыть ее снова. Я тоже. Так как это был только сервер разработки, я просто удалил базу данных с помощью SSMS и восстановил в новой базе данных.

Мой вопрос, что могло быть причиной этого? и как я могу избежать этого в будущем, и если я когда-нибудь попаду в такую ​​же ситуацию в будущем, есть ли другой способ исправить это, кроме удаления всей базы данных ???

Спасибо

M.Ali
источник

Ответы:

24

репродукция

  1. Откройте SSMS
  2. Введите следующее в новом окне запроса

    use <YourDatabase>;
    go
  3. Перейдите к Обозревателю объектов (SSMS) и щелкните правой кнопкой мыши <YourDatabase>-> Tasks->Take Offline
  4. Откройте второе новое окно запроса и введите следующее:

    use <YourDatabase>;
    go

Вам будет предложено следующее сообщение:

Сообщение 952, уровень 16, состояние 1, строка 1
База данных «TestDb1» находится в процессе перехода. Попробуйте утверждение позже.

Причина, по которой это происходит, может быть найдена из диагностического запроса, аналогичного приведенному ниже:

select
    l.resource_type,
    l.request_mode,
    l.request_status,
    l.request_session_id,
    r.command,
    r.status,
    r.blocking_session_id,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    request_sql_text = st.text,
    s.program_name,
    most_recent_sql_text = stc.text
from sys.dm_tran_locks l
left join sys.dm_exec_requests r
on l.request_session_id = r.session_id
left join sys.dm_exec_sessions s
on l.request_session_id = s.session_id
left join sys.dm_exec_connections c
on s.session_id = c.session_id
outer apply sys.dm_exec_sql_text(r.sql_handle) st
outer apply sys.dm_exec_sql_text(c.most_recent_sql_handle) stc
where l.resource_database_id = db_id('<YourDatabase>')
order by request_session_id;

Для чего бы то ни было, вам не нужен Object Explorer, чтобы воспроизвести эту ошибку. Вам просто нужен заблокированный запрос, который пытается выполнить ту же операцию (в этом случае переведите базу данных в автономный режим). Смотрите на скриншот ниже для трех шагов в T-SQL:

введите описание изображения здесь

Скорее всего, вы увидите, что ваш сеанс Object Explorer заблокирован другим сеансом (показано blocking_session_id). Этот сеанс Object Explorer будет пытаться получить эксклюзивную блокировку ( X) для базы данных. В приведенном выше случае воспроизведения, сеансу Object Explorer была предоставлена ​​блокировка обновления ( U) и была предпринята попытка преобразования в эксклюзивную блокировку ( X). Он имел тип wait_type LCK_M_X, заблокированный нашей сессией, который был представлен первым окном запроса ( use <YourDatabase>захватывает общий замок ( S) в базе данных).

И затем эта ошибка возникла из-за еще одного сеанса, пытающегося получить блокировку, и это сообщение об ошибке приводит к отказу сеанса в получении доступа к базе данных, которая пытается перейти в другое состояние (в данном случае, состояние онлайн в автономный переход).

Что делать в следующий раз?

Во-первых, не паникуйте и не начинайте удалять базы данных . Вам необходимо использовать метод устранения неполадок (с аналогичным диагностическим запросом, подобным приведенному выше), чтобы выяснить, почему вы видите то, что видите. С таким сообщением или когда что-то кажется «зависшим», вы должны автоматически предположить отсутствие параллелизма и начать копаться в блокировке ( sys.dm_tran_locksэто хорошее начало).

В качестве примечания, я действительно верю, что вам лучше всего выяснить причину проблемы, прежде чем предпринимать какие-либо случайные действия. Не только с этой операцией, но и с поведением, которое вы не ожидаете. Зная, что на самом деле стало причиной вашей проблемы, очевидно, что это не было большой проблемой. По сути, у вас была цепочка блокировок, и родительский блокировщик - это то, что вы, скорее всего, могли бы просто выдать KILL, или, если это был запрос сеанса, который вы не хотели бы делать, KILLвы могли бы дождаться его завершения. В любом случае, у вас были бы знания, чтобы принять правильное и разумное решение с учетом вашего конкретного сценария (откат или ожидание коммита).

Стоит отметить еще одну вещь: это одна из причин, по которой я всегда выбираю альтернативу T-SQL вместо графического интерфейса. Вы точно знаете, что вы выполняете с T-SQL и что делает SQL Server. В конце концов, вы дали явную команду. Когда вы используете GUI, фактический T-SQL будет абстракцией. В этом случае я посмотрел на попытку заблокированного обозревателя объектов перевести базу данных в автономный режим, и это было так ALTER DATABASE <YourDatabase> SET OFFLINE. Не было попыток отката, поэтому он ждал бесконечно долго. В вашем случае, если вы хотите откатить сеансы с блокировками в этой базе данных, ALTER DATABASE ... SET OFFLINE WITH ROLLBACK IMMEDIATEскорее всего , вам будет достаточно, если вы вначале определили, что откат был в порядке.

Томас Стрингер
источник
4

Простое закрытие SQL Server Management Studio (SSMS) и повторное открытие исправили проблему для меня.

Майкл Болхофер
источник
0

Не нужно ничего делать, просто убейте процесс SqLWB.exeиз диспетчера задач, откройте SQL Server, щелкните правой кнопкой мыши базу данных и переведите ее в автономный режим. Если это не работает, то после завершения сеанса введите команду

ALTER DATABASE [Test4] SET OFFLINE WITH ROLLBACK IMMEDIATE

а затем в автономном режиме. Это будет работать так же, как и у меня.

Garima
источник