SQL Server: database bloccato nello stato "Ripristino"


564

Ho eseguito il backup di un database:

BACKUP DATABASE MyDatabase
TO DISK = 'MyDatabase.bak'
WITH INIT --overwrite existing

E poi ho provato a ripristinarlo:

RESTORE DATABASE MyDatabase
   FROM DISK = 'MyDatabase.bak'
   WITH REPLACE --force restore over specified database

E ora il database è bloccato nello stato di ripristino.

Alcune persone hanno teorizzato che è perché non c'era alcun file di registro nel backup e doveva essere portato avanti usando:

RESTORE DATABASE MyDatabase
WITH RECOVERY 

Solo che, ovviamente, fallisce:

Msg 4333, Level 16, State 1, Line 1
The database cannot be recovered because the log was not restored.
Msg 3013, Level 16, State 1, Line 1
RESTORE DATABASE is terminating abnormally.

Ed esattamente quello che vuoi in una situazione catastrofica è un ripristino che non funzionerà.


Il backup contiene sia un file di dati che di registro:

RESTORE FILELISTONLY 
FROM DISK = 'MyDatabase.bak'

Logical Name    PhysicalName
=============   ===============
MyDatabase    C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\MyDatabase.mdf
MyDatabase_log  C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\MyDatabase_log.LDF

3
Ho avuto lo stesso identico problema e tutte le soluzioni sono fallite. È interessante notare che ho effettuato l'accesso direttamente al server SQL ed emesso il DROP DATABASE dbcomando tramite SSMS e ha funzionato (in precedenza utilizzavo SSMS da un'altra macchina per emettere i comandi). Immagino che anche le altre soluzioni avrebbero funzionato.
Salman,

Risposte:


437

È necessario utilizzare l' WITH RECOVERYopzione, con il RESTOREcomando del database , per rendere il database online come parte del processo di ripristino.

Questo è ovviamente solo se non si intende ripristinare alcun backup del registro delle transazioni, ovvero si desidera ripristinare solo un backup del database e quindi poter accedere al database.

Il tuo comando dovrebbe assomigliare a questo,

RESTORE DATABASE MyDatabase
   FROM DISK = 'MyDatabase.bak'
   WITH REPLACE,RECOVERY

Potresti avere più successo utilizzando la procedura guidata di ripristino del database in SQL Server Management Studio. In questo modo è possibile selezionare le posizioni specifiche dei file, l'opzione di sovrascrittura e l'opzione WITH Recovery.


3
Non ho mai dovuto usare la dichiarazione di recupero quando facevo quello che stava facendo. CON SOSTITUIRE dovrebbe essere sufficiente.
Sam,

8
Sì, stavo usando NORECOVERY ma il processo di ripristino si blocca. Usando WITH RECOVERY, REPLACE non si blocca più il processo
Junior Mayhé,

Questo ha risolto il mio problema. Si è verificato un errore SAN durante un ripristino e questa è stata una soluzione rapida e pulita.
Utente registrato

Ho avuto un problema simile oggi con un database SQL Server 2005. Nel mio caso, ho dovuto aggiungere ', RESTART' alla clausola WITH, per risolvere il problema. Mi stava dando un messaggio di errore che indicava che l'operazione precedente non aveva avuto successo.
XpiritO,

3
@FistOfFury Se un'operazione di ripristino precedente sullo stesso database si trova in uno stato sospeso / inattivo, sì. La semplice interruzione / annullamento del ripristino in corso dovrebbe avere lo stesso effetto.
John Sansom,

692

Ho avuto questa situazione ripristinando un database in un'istanza di SQL Server 2005 Standard Edition utilizzando Symantec Backup Exec 11d. Dopo il completamento del processo di ripristino, il database è rimasto in uno stato "Ripristino". Non ho avuto problemi di spazio su disco: il database semplicemente non è uscito dallo stato "Ripristino".

Ho eseguito la seguente query sull'istanza di SQL Server e ho scoperto che il database è diventato immediatamente utilizzabile:

RESTORE DATABASE <database name> WITH RECOVERY

4
Abbiamo avuto un DB bloccato nel ripristino per 2 ore. Abbiamo eseguito questo comando da un'altra macchina contro master e ci ha risolto. Grazie!
Pete,

11
+1, con un gotcha. Quando l'ho eseguito, ho ricevuto un messaggio di errore che diceva che il database era già stato completamente ripristinato. Ma mostrava ancora lo stato "In Recovery". Quindi l'ho cliccato con il tasto destro in Management Studio, ho fatto clic su Aggiorna ed è tornato alla normalità.
dario_ramos,

2
Ho ripristinato usando la procedura guidata di Mng Studio, ho inserito un nuovo nome di database ma per errore ho lasciato i nomi dei file come quelli di un database esistente. Ho ricevuto l'errore "Ripristino non riuscito ma la coda del registro ha avuto esito positivo" e il database collegato a tali file è stato bloccato in uno stato di ripristino. Questo comando sembra aver ripristinato il database al suo stato precedente.
Chris,

3
Questo ha funzionato. Stavo cercando di ripristinare un backup su un database laterale, ma il mio database principale è entrato in uno stato di ripristino per qualche motivo. Questo in realtà ha recuperato il mio DB. Grazie mille!
Aravindh,

2
Alcune impostazioni predefinite della procedura guidata di ripristino di SSMS lasceranno il DB di origine in stato di ripristino in modo tale da poter continuare a ripristinare vari backup o registri senza timore degli utenti e questo comando è il modo corretto di riportare il DB alla normalità una volta terminato.
Tim Lehner,

102

Ecco come lo fai:

  1. Interrompere il servizio (MSSQLSERVER);
  2. Rinominare o eliminare i file di database e di registro (C: \ Programmi \ Microsoft SQL Server \ MSSQL.1 \ MSSQL \ Data ...) o ovunque si disponga dei file;
  3. Avviare il servizio (MSSQLSERVER);
  4. Elimina il database con problemi;
  5. Ripristinare nuovamente il database.

Tipu, grazie per quello. Ho avuto un problema simile al poster originale, ma è stato causato dal fatto che il server ha esaurito lo spazio su disco durante il ripristino e quindi ha causato uno stato di ripristino permanente.
Pauk,

8
Perché non rilasciare semplicemente il database? In questo modo non è necessario interrompere il servizio.
ErikE,

8
@ErikE Per me, il server SQL ha detto che non è possibile eliminare un database nel bel mezzo di un ripristino, anche se non stava davvero ripristinando ....
Erik Philips

@ErikPhilips In tal caso suppongo che uno sia tornato a interrompere il servizio. Mi chiedo se ciò accada ogni volta o solo in alcuni casi del problema di ripristino bloccato.
ErikE,

5
Nel mio caso, è stato sufficiente eliminare il database sospeso nello stato "Ripristino in corso ..." con il comando SQL drop database <dbname>in una finestra di query. Quindi ho fatto clic con il pulsante destro del mouse su Database e ho selezionato Aggiorna per rimuovere la voce in Management Studio. Successivamente ho fatto un nuovo ripristino che ha funzionato bene (si noti che non è riuscito a renderlo offline, un riavvio del servizio SQL non ha funzionato, un riavvio del server non ha funzionato).
Matt,

84

Ho avuto un incidente simile con l'arresto di un server secondario di distribuzione dei log. Dopo il comando per rimuovere il server dal log shipping e arrestare il log shipping dal server primario, il database sul server secondario si è bloccato nel ripristino dello stato dopo il comando

RESTORE DATABASE <database name> WITH RECOVERY

I messaggi del database:

RESTORE DATABASE ha elaborato correttamente 0 pagine in 18.530 secondi (0.000 MB / sec).

Il database era di nuovo utilizzabile dopo quei 18 secondi.


6
Particolarmente utile quando hai già ripristinato il database ma hai dimenticato l'opzione RECOVERY ...
JBickford

2
Era tutto ciò di cui avevo bisogno per farlo uscire dallo stato "Ripristino" dopo aver ripristinato un backup di questo database con un nome DB diverso. Grazie mille.
Sean,

81

Ho avuto un problema simile con il ripristino tramite SQL Management Studio. Ho provato a ripristinare un backup del database con uno nuovo con un nome diverso. Inizialmente questo non è riuscito e dopo aver corretto i nomi dei file del nuovo database è stato eseguito correttamente - in ogni caso il problema che sto descrivendo si è ripresentato anche se ho capito bene dalla prima volta. Quindi, dopo il restauro, il database originale è rimasto con un (Ripristino ...) accanto al suo nome. Considerando le risposte del forum sopra (Bhusan's) ho provato a eseguire nell'editor di query sul lato il seguente:

RESTORE DATABASE "[NAME_OF_DATABASE_STUCK_IN_RESTORING_STATE]"

che ha risolto il problema. Inizialmente ho avuto problemi a causa del nome del database che conteneva caratteri speciali. Ho risolto questo aggiungendo virgolette doppie - le virgolette singole non funzionavano dando un errore "Sintassi errata vicino ...".

Questa è stata la soluzione minima che ho provato a risolvere questo problema (database bloccato nello stato di ripristino) e spero che possa essere applicato a più casi.


2
Ha funzionato perfettamente, senza bisogno di strapparlo su e giù di nuovo. 3 Dbs di 80+ GB ciascuno richiedono un po 'di tempo! Grazie!
Christer,

1
L'ho quasi fatto nell'ambiente di produzione. L'ho provato prima sul locale, sono finito in questa stessa situazione e ho trovato il tuo commento. Lezione appresa: utilizzare gli script e non fidarsi di SSMS in situazioni importanti.
Mariusz,

1
Ho riscontrato questo problema durante il ripristino di un backup di file di sola copia di un database in un nuovo database. Il database originale ha mostrato l'errore. Questa soluzione ha funzionato e la risposta che ho ricevuto è stata "RESTORE DATABASE elaborato con successo 0 pagine in 0,263 secondi (0.000 MB / sec)." , quindi sembra che SQL Server fosse confuso sullo stato del database.
R. Schreurs,

1
Ha funzionato per me, ma solo quando ho rimosso le doppie virgolette - avevo appena [MY_DB_NAME] come parametro.
StackOverflowUser

34

OK, ho un problema simile ed esattamente come nel caso di Pauk, è stato causato dal fatto che il server ha esaurito lo spazio su disco durante il ripristino e quindi ha causato uno stato di ripristino permanente. Come terminare questo stato senza arrestare i servizi di SQL Server?

Ho trovato una soluzione :)

Drop database *dbname*

29

L'opzione WITH RECOVERY viene utilizzata per impostazione predefinita quando vengono eseguiti i comandi RESTORE DATABASE / RESTORE LOG. Se sei bloccato nel processo di "ripristino" puoi riportare un database allo stato online eseguendo:

RESTORE DATABASE YourDB WITH RECOVERY
GO

Se è necessario ripristinare più file, i comandi CLI richiedono rispettivamente WITH NORECOVERY e WITH RECOVERY: solo l'ultimo file in comando dovrebbe avere WITH RECOVERY per riportare il database online:

RESTORE DATABASE YourDB FROM DISK = 'Z:\YourDB.bak'
WITH NORECOVERY
GO
RESTORE LOG YourDB FROM DISK = 'Z:\YourDB.trn'
WITH RECOVERY
GO

È inoltre possibile utilizzare la procedura guidata di SQL Server Management Studio:

inserisci qui la descrizione dell'immagine

Esiste anche un processo di ripristino virtuale, ma dovrai utilizzare soluzioni di terze parti. Di solito è possibile utilizzare un backup del database come database online live. ApexSQL e Idera ha le proprie soluzioni. Recensione di SQL Hammer su ApexSQL Restore . Il ripristino virtuale è una buona soluzione se hai a che fare con un numero elevato di backup. Il processo di ripristino è molto più veloce e può anche risparmiare molto spazio sull'unità disco. Puoi dare un'occhiata all'infografica qui per un confronto.


23

Questo può essere abbastanza ovvio, ma mi ha fatto scattare proprio ora:

Se si esegue un backup del registro di coda, questo problema può essere causato anche dal fatto che questa opzione sia selezionata nella procedura guidata di ripristino di SSMS - "Lascia il database di origine nello stato di ripristino (WITH NORECOVERY)"

inserisci qui la descrizione dell'immagine


7
Se ti trovi in ​​questo stato, la soluzione migliore è: 1. Fai clic con il pulsante destro del mouse sul database, vai su Attività-> Ripristina-> Registri delle transazioni 2. Trova il file di backup utilizzato per il backup del registro di coda 3. Ripristina il backup Il ripristino dovrebbe avere esito positivo e riportare il database in linea.
Ryan Gross,

16

Ho capito perché.

Se il client che ha emesso il RESTORE DATABASEcomando si disconnette durante il ripristino, il ripristino verrà bloccato.

È strano che al server, quando viene richiesto di ripristinare un database da una connessione client, non finirà il ripristino a meno che il client non rimanga connesso per tutto il tempo.


10
Tutti i comandi SQL richiedono che il client rimanga connesso per tutto il tempo.
mrdenny,

2
@mrdenny: avrei supposto che le modifiche si annullassero quando un client si disconnette.
Ian Boyd,

Ho lo stesso problema nell'esecuzione di questo comando con il driver PHP PDO di Microsoft. tuttavia quando si esegue con Microsoft SQL Server Server Management Studio funziona perfettamente. Mi chiedo come rendere la mia applicazione php connessa per tutto il tempo?
Channa ly,

È successo anche qui, DB bloccato nel ripristino / utente singolo dopo una possibile interruzione della connessione. Hai ucciso tutti gli altri SPID dalla nuova sessione ma ancora bloccato. È stato in grado di eliminare il database come soluzione.
crokusek,

10

questo ha funzionato:

http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/8dd1b91d-3e14-4486-abe6-e3a550bfe457

Ho avuto una situazione in cui il mio database mostrava lo stato di ripristino e non riuscivo a eseguire alcuna query e non riuscivo a connettermi con il nostro software.

Quello che ho fatto per uscire da questa situazione è:

  1. Arresta tutti i servizi relativi a SQL dai servizi di Windows.

  2. Ho aperto la cartella DATA in cui risiedono i file Ldf e Mdf nella directory SQL, normalmente simile a: "C: \ Programmi *********** \ MSSQL \ DATA

  3. Quindi ho copiato i file Ldf e Mdf del database: [nome db] .mdf e [nome db] _log.ldf

Ho copiato entrambi questi file in un'altra cartella.

  1. Quindi ho avviato nuovamente tutti i servizi relativi a SQL (nel passaggio 1) dai servizi di Windows.

  2. Ho iniziato il mio studio di gestione MS SQL con accesso normale.

  3. Fare clic con il tasto destro sul database dei colpevoli e premere CANC (per eliminare del tutto il database).

  4. Tutti i file LDF e MDF relativi a questo database sono passati dalla cartella DATA (menzionata al passaggio 2).

  5. Creato un nuovo database con lo stesso nome (stesso nome di quello che ho eliminato al passaggio 6 - il database dei colpevoli).

  6. Quindi [nome database] -> tasto destro -> attività -> Porta offline.

  7. Ho quindi copiato entrambi i file (dal passaggio 3) nella cartella DATA (passaggio 2).

  8. [nome database] -> tasto destro -> attività -> Porta online.


Questo ha funzionato anche per me. Al passaggio 10, ho scelto di sovrascrivere i file esistenti.
Divi perdomo,

8

Ho avuto una . nel mio nome di database e la query non ha funzionato a causa di ciò (dicendo Sintassi errata vicino a '.') Quindi ho capito che ho bisogno di una parentesi per il nome:

RESTORE DATABASE [My.DB.Name] WITH RECOVERY

5

Nel mio caso, è stato sufficiente eliminare il database sospeso nello stato "Ripristino in corso ..." con il comando SQL

 drop database <dbname> 

in una finestra di query.

Quindi ho fatto clic con il pulsante destro del mouse su Database e ho selezionato Aggiorna per rimuovere la voce in Management Studio. Successivamente ho fatto un nuovo ripristino che ha funzionato bene (notare che non è riuscito a renderlo offline, un riavvio del servizio SQL non ha funzionato, un riavvio del server non ha funzionato).


3

Ho avuto questo problema quando ho anche ricevuto un errore TCP nel registro eventi ...

Rilascia il DB con sql o fai clic destro su di esso nel gestore "elimina" e ripristina nuovamente.

In realtà ho iniziato a farlo di default. Scrivere il drop DB, ricrearlo e ripristinarlo.


3

Per impostazione predefinita, ogni RESTORE DATABASEviene fornito con l' RECOVERYinstallazione. Le opzioni "NORECOVERY" indicano sostanzialmente a SQL Server che il database è in attesa di altri file di ripristino (potrebbe essere un file DIFF e un file LOG e, se possibile, includere un file di backup del registro di coda). Le opzioni "RECOVERY" completano tutte le transazioni e consentono al database di eseguire le transazioni.

Così:

  1. se il database è impostato con il modello di recupero SEMPLICE , è possibile eseguire un ripristino COMPLETO con NORECOVERYopzione solo quando si dispone di un backup DIFF . Nessun backup LOG è consentito nel database del modello di recupero SEMPLICE .
  2. Altrimenti, se il database è impostato con FULL modello di recupero o BULK-LOGGED , è possibile eseguire un ripristino FULL seguito NORECOVERYdall'opzione, quindi eseguire un DIFF seguito da NORECOVERYe, infine, eseguire il ripristino LOG con l' RECOVERYopzione.

Ricorda, L'ULTIMA RICHIESTA DI RESTAURO DEVE AVERE RECOVERYOPZIONE . Potrebbe essere un modo esplicito o meno. In therms di T-SQL, la situazione:

1.

 USE [master]
    GO
    RESTORE DATABASE Database_name 
    FROM DISK = N'\\path_of_backup_file.bak WITH FILE = 1, [REPLACE],NOUNLOAD, 
    RECOVERY -- This option could be omitted.
    GO

L'opzione WITH REPLACE deve essere utilizzata con cautela poiché può causare la perdita di dati

Oppure, se si esegue un backup COMPLETO e DIFF, è possibile utilizzare questo

   USE [master]
    GO
    RESTORE DATABASE Database_name
      FROM DISK = N'\\path_of_backup_file.bak' WITH FILE = 1, 
       NOUNLOAD,NORECOVERY
    GO
    RESTORE DATABASE Database_name
      FROM DISK =N'\\path_of_**diff**backup_file.bak' WITH FILE = 1, 
     NOUNLOAD, RECOVERY
    GO

 2. USE [master]
    GO
   -- Perform a Tail-Log backup, if possible. 
   BACKUP LOG Database_name
   GO
   -- Restoring a FULL backup
   RESTORE DATABASE Database_name
    FROM DISK = N'\\path_of_backup_file.bak' WITH FILE = 1, 
     NOUNLOAD,NORECOVERY
  GO 
  -- Restore the last DIFF backup
  RESTORE DATABASE Database_name
    FROM DISK = N'\\path_of_DIFF_backup_file.bak' WITH FILE = 1,
     NORECOVERY,NOUNLOAD
  GO
  -- Restore a Log backup
  RESTORE LOG Database_name
    FROM DISK = N'path_of_LOG_backup_file.trn' WITH FILE = 2,
    RECOVERY, NOUNLOAD
  GO

Naturalmente, è possibile eseguire un ripristino con l'opzione STATS = 10 che indica a SQL Server di segnalare ogni 10% completato.

Se preferisci, puoi osservare il processo o ripristinarlo in una query basata in tempo reale. Come segue:

USE[master]
GO
SELECT session_id AS SPID, command, a.text AS Query, start_time, percent_complete, dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time 
    FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) a 
        WHERE r.command in ('BACKUP DATABASE','RESTORE DATABASE')
GO

Spero che questo aiuto.


2

Potrebbe esserci anche un problema durante l'eliminazione di un database bloccato se l'istantanea è abilitata. Per me questo ha funzionato:

  1. Per prima cosa ho seguito Tipu Delacablu passaggi (leggi alcuni post in alto)
  2. comando run: drop database [il tuo database], che ti darà un errore che ti dice il nome del database snapshot
  3. comando run: rilascia il database [database snapshot], quindi esegui nuovamente il comando nel passaggio 2.


1

Ho il caso MyDbName (Ripristino ...) a causa del limite di licenza di SQL Express.

Nel file di registro, ho trovato questo:

CREATE DATABASE o ALTER DATABASE non sono riusciti perché la dimensione cumulativa del database risultante supererebbe il limite di licenza di 10240 MB per database.

Pertanto, se si sta tentando di ripristinare un database più grande, ad esempio è necessario passare il server SQL Express all'edizione Developer .


Era il database TFS e il client TFS mi aveva già detto: Database pieno.
cskwg,

1

Si è verificato un problema simile durante il ripristino del database utilizzando SQL Server Management Studio e si è bloccato in modalità di ripristino. Dopo diverse ore di rilevamento dei problemi, la seguente query ha funzionato per me. La query seguente ripristina il database da un backup esistente a uno stato precedente. Credo che il problema sia avere il file .mdf e .log nella stessa directory.

RESTORE DATABASE aqua_lc_availability
FROM DISK = 'path to .bak file'
WITH RECOVERY

0
  1. Consentire innanzitutto di controllare ed eseguire il servizio SQL Agent.
  2. Utilizzando il seguente T-SQL:

    SELEZIONA il nome file FROM master.sys.sysaltfiles WHERE dbid = DB_ID ('nome_db');

  3. Utilizzo continuo di T-SQL:

    RIAVVIA DATABASE DA DISCO = 'Percorso_BB' CON RIAVVIO, SOSTITUIRE;

Spero che questo aiuto!


0

Tutte le opzioni basate su WITH RECOVERY non hanno funzionato per me.

Ciò che ha fatto è stato eseguire il ripristino completo da Management Studio.

USE [master]
RESTORE DATABASE Sales_SSD
FROM  DISK = N'D:\databaseBackups02\Daily_Sales_20150309_0941.bak' 
WITH  FILE = 1,  
MOVE N'Sales_Data' TO N'C:\Data\SSD\Sales.mdf',  
MOVE N'Sales_Log' TO N'C:\Data\SSD\Sales_1.ldf',  
NOUNLOAD,  REPLACE,  STATS = 5

0

Ho avuto lo stesso problema ... anche se non so perché il mio database ha riscontrato questo problema in quanto l'unità non era piena ... È come se fosse danneggiato o qualcosa del genere. Ho provato tutto quanto sopra nessuno di loro ha funzionato completamente, ho pensato in particolare che il suggerimento di interrompere il servizio e di eliminare i file mdf e ldf avrebbe funzionato ... ma si è comunque bloccato sul ripristino?

Ho finito per risolverlo eliminando i file come menzionato ma invece di provare a ripristinare nuovamente il DB ho copiato su nuovi file .mdf e .ldf e li ho allegati utilizzando la procedura guidata di Front End Attachment. Rilievo, ha funzionato !!

Ci è voluto PER SEMPRE per copiare i nuovi file mentre sto usando una macchina virtuale ... quindi la copia e l'incollaggio usando gli appunti ha richiesto un'ora stessa, quindi lo consiglierei solo come ultimo tentativo.


0

Ciò che l'ha risolto per me è stato

  1. arrestando l'istanza
  2. creando un backup dei file .mdf e .ldf nella cartella dei dati
  3. Riavvia l'istanza
  4. elimina il ripristino bloccato del database
  5. rimettere i file .mdf e.ldf nella cartella dei dati
  6. Allegare l'istanza ai file .mdf e .ldf

0
RESTORE DATABASE {DatabaseName}
   FROM DISK = '{databasename}.bak'
   WITH REPLACE, RECOVERY

Si prega di sottolineare le informazioni aggiuntive fornite da questa risposta rispetto alla risposta più vecchia, accettata e altamente votata. Ciò contribuirebbe a evitare l'impressione di averlo appena copiato nella speranza di ottenere reputazione. Inoltre, le risposte solo al codice (che è la principale differenza visibile) non sono apprezzate qui, perché danno l'impressione sbagliata che StackOverflow sia un servizio di scrittura di codice gratuito,
Yunnosch

Ho corretto la formattazione, solo per rendere più ovvia la somiglianza con la risposta precedente. Ma potresti imparare a farlo qui stackoverflow.com/editing-help nel caso in cui in futuro cerchi di rendere più facilmente leggibili le risposte.
Yunnosch,

0

Utilizzare il comando seguente per risolvere questo problema

RESTORE DATABASE [DatabaseName] WITH RECOVERY
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.