Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Зеркало. Безопасный режим и потеря данных  [new]
GPP_Coder
Guest
Добрый день, коллеги.

Вопрос: Как настроить зеркало, чтобы все изменения фиксировались гарантировано на обоих серверах даже ценой большой потери производительности (канал плохой/зеркальный сервер медленный и т.д.)? И возможно ли это на MS SQL (на оракле возможно :/).
Обязательно с уведомлением клиента об успехе отработки транзакции только после гарантированной фиксации транзакций на обоих серверах!

Вопрос задаю потому, что после тестирования зеркала в безопасном режиме возникло недопонимание:

Вводная - 2 сервера 2012:

1) SRV01 (Principal) - Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64) Enterprise Edition (64-bit)
2) SRV02 (Mirror) - Microsoft SQL Server 2012 (SP1) - 11.0.3153.0 (X64) Enterprise Edition (64-bit)

Настроено зеркало для БД без свидетеля. Безопасный режим:

+ select t.mirroring_state, t.mirroring_safety_level,t.mirroring_safety_level_desc, t.mirroring_safety_sequence from sys.database_mirroring t where database_id =6

mirroring_state mirroring_safety_level mirroring_safety_level_desc mirroring_safety_sequence
4 2 FULL 1



Что про безопасный режим пишет MSDN:
+ SQL Server 2012 Синхронное зеркальное отображение базы данных (режим высокой безопасности)

Синхронность операции достигается следующим образом.

1. Получив транзакцию от клиента, основной сервер записывает ее в журнал транзакций.


2. Основной сервер записывает транзакцию в базу данных и одновременно направляет журнальную запись зеркальному серверу. Основной сервер ждет, пока от зеркального сервера поступит подтверждение, после чего он направляет клиенту одно из следующих подтверждений: о фиксации или откате транзакции.


3. Зеркальный сервер записывает журнал на диск и возвращает подтверждение основному серверу.


4. Получив подтверждение от зеркального сервера, основной сервер направляет клиенту сообщение с подтверждением.



Проводим тестирование DRP:
Запускаем в приложении постоянную вставку (строка подключения настроена на работу с зеркалом)
Для чистоты эксперимента для каждой вставки открывается новое подключение

+ Код вставки, кому интересно

var i = 0;

                do
                {
                    while (!Console.KeyAvailable)
                    {
                        
                        try
                        {
                            using (SqlConnection connection = new SqlConnection("Data Source=SRV01;failover partner=SRV02;initial catalog=MirrorTestDB;integrated security=True;"))
                            {
                                connection.Open();
                                var text = $"{DateTime.Now} Iteration {i++}";

                                using (SqlTransaction transaction = connection.BeginTransaction("SampleTransaction"))
                                {
                                    using (SqlCommand command = new SqlCommand($@"INSERT INTO [dbo].[MirrDateTable] ([Text],[RowAddDate]) VALUES ('{text}', GETDATE() )", connection) { Transaction = transaction })
                                    {
                                        try
                                        {
                                            command.ExecuteNonQuery();
                                            transaction.Commit();
                                            Console.WriteLine(text);
                                        }
                                        catch (Exception exx1)
                                        {
                                            try
                                            {
                                                transaction.Rollback();
                                            }
                                            catch (Exception ex2)
                                            {
                                                Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
                                                Console.WriteLine("  Message: {0}", ex2.Message);
                                            }

                                            Console.WriteLine($"TrnError - {exx1.Message}!");
                                        }

                                    }
                                }

                            }
                        }
                        catch (Exception exx)
                        {
                            Console.WriteLine($"Ошибка добавления - {exx.Message}!");
                        }

                    }
                } while (Console.ReadKey(true).Key != ConsoleKey.Escape);



Сценарий 1:
1.1 Запускаем приложение - непрерывная вставка данных в таблицу
1.2 Гасим основной сервер - C:\Windows\system32>net stop MSSQLSERVER
1.3 Клиент показывает, что последняя успешно вставленная запись 1493
1.4 Поднимаем основной сервер.
1.5 База поднимается. Все записи на месте (1493 присутствует)


Сценарий 2:
2.1 Запускаем приложение - непрерывная вставка данных в таблицу
2.2 Гасим основной сервер - C:\Windows\system32>net stop MSSQLSERVER
2.3 Клиент показывает, что последняя успешно вставленная запись 1493
2.4 Переводим зеркальную БД в режим главной
2.6 Последняя запись с кодом 1327 - Итог "потеряно" 166 записей.
Проверял раз 10. С разными настройками подключения клиента (в том числе с использованием EntityFramework) - результат везде одинаковый. Везде "потеря данных"

Понятно, что эти "потерянные" данные спокойно лежат в логе основной БД. И для их восстановления я должен прибить зеркалирование, поднять первый сервер, и импортом экспортом их куда-то сохранить.

Вот тут собственно вопрос. В чем заключается режим "Высокой безопасности", если клиент получает уведомление об "успешной" транзакции без фиксации этой транзакции на зеркальной БД. И чем он принципиально отличается от режима высокой производительности?

Для MS SQL 2008 есть такая статья, которая не соответствует приведенному выше алгоритму работы зеркала в безопасном режиме: TechNet
+ Принудительное обслуживание

Важно понимать, что принудительное обслуживание может привести к потере данных. Возможность потери данных обусловлена тем, что зеркальный сервер не может взаимодействовать с основным, и поэтому не может гарантировать синхронизацию двух баз данных. Кроме того, принудительное обслуживание создает новую вилку восстановления.


Повторю вопрос: Как настроить зеркало, чтобы все изменения фиксировались гарантировано на обоих серверах или не фиксировались вовсе с уведомлением клиента (конечно при доступности зеркальной БД. Если она недоступна, по таймауту например, то фиксация только в основной).

Спасибо, что дочитали.
10 ноя 15, 09:13    [18393225]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
aleks2
Guest
GPP_Coder
Повторю вопрос: Как настроить зеркало, чтобы все изменения фиксировались гарантировано на обоих серверах или не фиксировались вовсе с уведомлением клиента (конечно при доступности зеркальной БД. Если она недоступна, по таймауту например, то фиксация только в основной).

Спасибо, что дочитали.


Против ядерного взрыва - все бессильно.
Даже против умелого электрика.

Клиент получает уведомление о сбое. Вот пущай и проверит: чего там реально вставилось.
10 ноя 15, 09:31    [18393270]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
aleks2
Клиент получает уведомление о сбое. Вот пущай и проверит: чего там реально вставилось.

Это не жизнеспособный вариант. Проходит 150+ независимых транзакций. На 151 ошибка и вы предлагаете проверять клиенту предыдущие транзакции? За какой период? За последние 15 минут? Или за последний год?
Вопрос открыт. Если нет режима гарантированной отработки транзакций на обоих серверах, то зеркалирование в принципе является бесполезным процессом с точки зрения отказоустойчивости на критичных БД (только прошу про always on не нужно).
10 ноя 15, 10:44    [18393618]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
select count(*) from dbo.MirrDataTable
возвращает разные значения?
10 ноя 15, 12:03    [18394044]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
запустил ваш сценарий.
убил процесс sql server на основном сервере.
значение в сценарии i = 8723.
перевел зеркало в рабочий режим:
ALTER DATABASE <database name> SET PARTNER OFF;
RESTORE DATABASE <database name> WITH RECOVERY;
select count(*) from dbo.MirrDataTable;
вернул 8723.
10 ноя 15, 14:15    [18394904]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
komrad
Member

Откуда:
Сообщений: 5249
GPP_Coder
2.3 Клиент показывает, что последняя успешно вставленная запись 1493

на основании чего он делает такой вывод?

GPP_Coder
2.4 Переводим зеркальную БД в режим главной
2.6 Последняя запись с кодом 1327 - Итог "потеряно" 166 записей.
Проверял раз 10. С разными настройками подключения клиента (в том числе с использованием EntityFramework) - результат везде одинаковый. Везде "потеря данных"

такое ощущение, что у вас не отдельные транзакции были
либо затык в передаче логов на зеркало
10 ноя 15, 14:39    [18395046]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
andrey odegov
select count(*) from dbo.MirrDataTable
возвращает разные значения?


Остановил SRV01.
Сделал освновным SRV02 -
ALTER DATABASE MirrorTestDB SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS
На SRV02
SELECT count(*)  FROM [MirrorTestDB].[dbo].[MirrDateTable]

2557

Удалил зеркалирование. Поднял SRV01
На SRV01
SELECT count(*)  FROM [MirrorTestDB].[dbo].[MirrDateTable]

2730

Клиент успел успешно вставить до остановки SRV01 2730 записей
10 ноя 15, 15:43    [18395405]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
komrad
GPP_Coder
2.3 Клиент показывает, что последняя успешно вставленная запись 1493

на основании чего он делает такой вывод?

GPP_Coder
2.4 Переводим зеркальную БД в режим главной
2.6 Последняя запись с кодом 1327 - Итог "потеряно" 166 записей.
Проверял раз 10. С разными настройками подключения клиента (в том числе с использованием EntityFramework) - результат везде одинаковый. Везде "потеря данных"

такое ощущение, что у вас не отдельные транзакции были
либо затык в передаче логов на зеркало


В коде .net конструкция using подразумевает удаление объекта после выхода за границы юзинга.
Для верности для каждой вставки открывал подключение и вставлял в контексте транзакций.
В основной сервер данные падают. Экспериментально подтверждено.
10 ноя 15, 15:46    [18395426]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
andrey odegov
запустил ваш сценарий.
убил процесс sql server на основном сервере.
значение в сценарии i = 8723.
перевел зеркало в рабочий режим:
ALTER DATABASE <database name> SET PARTNER OFF;
RESTORE DATABASE <database name> WITH RECOVERY;
select count(*) from dbo.MirrDataTable;
вернул 8723.


Завтра попробую завтра с убиением зеркала. По вашему сценарию.
До этого я восстанавливал зеркало командой

ALTER DATABASE MirrorTestDB SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS
10 ноя 15, 15:48    [18395439]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2421
Ш.И.В.,

прикольный Вы, оговорка про FORCE_SERVICE_ALLOW_DATA_LOSS
БОЛ
Рекомендуется включать вынужденное обслуживание только в том случае, если основной сервер больше не работает. Иначе некоторые клиенты могут продолжить обращаться к оригинальной основной базе данных вместо новой основной базы данных.

Вас не наводит на мысль почему у вас каунты не сходятся?
10 ноя 15, 16:44    [18395868]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
а в чем вы выполняете свой код?
мне пришлось его слегка перепилить,
что бы запустить в linqpad-е.
10 ноя 15, 16:48    [18395904]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
churupaha
Member

Откуда: Краснодар
Сообщений: 1015
GPP_Coder
Сценарий 2:
2.1 Запускаем приложение - непрерывная вставка данных в таблицу
2.2 Гасим основной сервер - C:\Windows\system32>net stop MSSQLSERVER
2.3 Клиент показывает, что последняя успешно вставленная запись 1493
2.4 Переводим зеркальную БД в режим главной
2.6 Последняя запись с кодом 1327 - Итог "потеряно" 166 записей.


Все верно.


GPP_Coder
Вот тут собственно вопрос. В чем заключается режим "Высокой безопасности", если клиент получает уведомление об "успешной" транзакции без фиксации этой транзакции на зеркальной БД. И чем он принципиально отличается от режима высокой производительности?


Тем, что когда базы synchronized (send queue = 0) и mirrored доступна с principal, вам в случае High Protecion гарантируется синхронный commit на обоих узлах. В остальных случаях связка работает асинхронно. Когда вы выполнили в Сценарии 2 шаг 2.2, тем самым нарушив условия когда вам гарантируется синхронный commit, то send queue стала расти (это transaction log).
10 ноя 15, 18:52    [18396694]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
churupaha
Member

Откуда: Краснодар
Сообщений: 1015
+ могу вам посоветовать докатить кусочек transaction log'а в таком случае. c primary на mirror.
10 ноя 15, 18:58    [18396735]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
WarAnt
Ш.И.В.,

прикольный Вы, оговорка про FORCE_SERVICE_ALLOW_DATA_LOSS
БОЛ
Рекомендуется включать вынужденное обслуживание только в том случае, если основной сервер больше не работает. Иначе некоторые клиенты могут продолжить обращаться к оригинальной основной базе данных вместо новой основной базы данных.

Вас не наводит на мысль почему у вас каунты не сходятся?


Я бы понял почему они не сходились в режиме высокой производительности.
Главный действительно не работает.
Приколы заканчиваются в тот момент, когда клиент за секунду до отказа главного сервера выполняет часть транзакций считая, что они будут зафиксированы в обоих БД.
А на самом деле ситуация выглядит так - SQL Server говорит клиенту, что транзакции выполнены успешно.
Быстро помирает.
Мы переключаемся на зеркальную БД (не убивая зеркало - вдруг проблема не серьезная и главный сервер быстро поднимется) с использованием FORCE_SERVICE_ALLOW_DATA_LOSS (если есть другой способ переключиться на зеркальную БД без разбиения зеркалирования, то подскажите как это сделать, пожалуйста)
Клиент начинает выполнять транзакции с того же места, где остановился подозревая, что до ошибки все легло в БД.
И тут собственно проблема описанная в начальном посте.

Планируется использовать зеркалирование на БД с высокой частотой вставки (документооборот в крупной организации) и хотелось бы избежать неприятностей в виде вилок.
11 ноя 15, 06:30    [18397998]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
churupaha, благодарю за ответ, однако хотелось бы уточнить до конца некоторые моменты.
Поясню - меня интересует процесс зеркалирования с точки зрения абстрактного клиента. Задача простая - если клиент получает уведомление об успешном выполнении транзакции, то должна быть 99,99% уверенность, что эта транзакция зафиксирована на зеркальном сервере. Даже за счет потери производительности. Или SQL Server не умеет это?

churupaha
GPP_Coder
Сценарий 2:
...
2.2 Гасим основной сервер - C:\Windows\system32>net stop MSSQLSERVER


Все верно.

GPP_Coder
Вот тут собственно вопрос. В чем заключается режим "Высокой безопасности", если клиент получает уведомление об "успешной" транзакции без фиксации этой транзакции на зеркальной БД. И чем он принципиально отличается от режима высокой производительности?


Тем, что когда базы synchronized (send queue = 0) и mirrored доступна с principal, вам в случае High Protecion гарантируется синхронный commit на обоих узлах. В остальных случаях связка работает асинхронно. Когда вы выполнили в Сценарии 2 шаг 2.2, тем самым нарушив условия когда вам гарантируется синхронный commit, то send queue стала расти (это transaction log).

Непонятно почему SQL SERVER тогда сообщал об успехе выполнения транзакций клиенту?

Получается, что я не правильно интерпретировал этот текст ниже и главный сервер не дожидается успешной фиксации транзакции на зеркале, а просто не дожидаясь завершения синхронизации отвечает клиенту, что все ОК? Тогда это уже больше режим высокой производительности, где никто ничего не обещает в плане одновременной фиксации транзакции на основном и зеркальном сервере.

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

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



Но на этой же странице чуть ниже:

technet
Синхронность операции достигается следующим образом.

1.Получив транзакцию от клиента, основной сервер записывает ее в журнал транзакций.
2.Сервер участника записывает транзакцию в базу данных и одновременно направляет журнальную запись зеркальному серверу. Основной сервер ждет, пока от зеркального сервера поступит подтверждение, после чего он направляет клиенту одно из следующих подтверждений: о фиксации или откате транзакции.
3.Зеркальный сервер записывает журнал на диск и возвращает подтверждение серверу участника.
4.Получив подтверждение от зеркального сервера, сервер участника направляет клиенту сообщение с подтверждением.

В режиме высокой безопасности данные защищаются за счет их синхронизации в двух местах хранения. Гарантируется запись всех зафиксированных транзакций на диск зеркального сервера.

11 ноя 15, 07:02    [18398030]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
andrey odegov, обычное консольное .net приложение (.net fw 4.5).
Полный код:
+

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MSSQL.LoadTestServices.MirorTestApp
{
    class Program
    {
        static void Main(string[] args)
        {

            RunSqlUpdate();
        }


        static void RunSqlUpdate()
        {
            Console.WriteLine("Press ESC to stop");
            using (StreamWriter outputFile = new StreamWriter(@"C:\temp\WriteLines.txt"))
            {
                var i = 0;

                do
                {
                    while (!Console.KeyAvailable)
                    {
                        
                        try
                        {
                            using (SqlConnection connection = new SqlConnection("Data Source=SRV01;failover partner=SRV02;initial catalog=MirrorTestDB;integrated security=True;"))
                            {
                                connection.Open();
                                var text = $"{DateTime.Now} Iteration {i++}";

                                using (SqlTransaction transaction = connection.BeginTransaction("SampleTransaction"))
                                {
                                    using (SqlCommand command = new SqlCommand($@"INSERT INTO [dbo].[MirrDateTable] ([Text],[RowAddDate]) VALUES ('{text}', GETDATE() )", connection) { Transaction = transaction })
                                    {
                                        try
                                        {

                                            command.ExecuteNonQuery();
                                            transaction.Commit();
                                            Console.WriteLine(text);

                                        }
                                        catch (Exception exx1)
                                        {
                                            try
                                            {
                                                transaction.Rollback();
                                            }
                                            catch (Exception ex2)
                                            {                                               
                                                Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
                                                Console.WriteLine("  Message: {0}", ex2.Message);
                                            }

                                            Console.WriteLine($"TrnError - {exx1.Message}!");
                                        }

                                    }
                                }

                            }
                        }
                        catch (Exception exx)
                        {
                            Console.WriteLine($"Ошибка добавления - {exx.Message}!");
                            outputFile.WriteLine($"Ошибка добавления - {exx.Message}!");
                            Thread.Sleep(250);
                        }

                    }
                } while (Console.ReadKey(true).Key != ConsoleKey.Escape);

            }
            Console.ReadLine();
        }

        static void RunEfUpdate()
        {
            Console.WriteLine("Press ESC to stop");
            using (StreamWriter outputFile = new StreamWriter(@"с:\temp\WriteLines.txt"))
            {

                var i = 0;

                do
                {
                    while (!Console.KeyAvailable)
                    {

                        try
                        {
                            using (var context = new MirEntities())
                            {
                                context.Configuration.EnsureTransactionsForFunctionsAndCommands = true;
                                context.Configuration.ValidateOnSaveEnabled = true;

                                using (var dbContextTransaction = context.Database.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
                                {
                                    try
                                    {
                                        var text = $"{DateTime.Now} Iteration 1 insert#{i++}";
                                        context.MirrDateTables.Add(new MirrDateTable { Text = text, RowAddDate = DateTime.Now });
                                        context.SaveChanges();
                                        Console.WriteLine(text);
                                        outputFile.WriteLine(text);
                                        dbContextTransaction.Commit();

                                    }
                                    catch (Exception exx1)
                                    {
                                        dbContextTransaction.Rollback();
                                        Console.WriteLine($"TrnError - {exx1.Message}!");
                                    }

                                }

                            }
                        }
                        catch (Exception exx)
                        {
                            Console.WriteLine($"Ошибка добавления - {exx.Message}!");
                            outputFile.WriteLine($"Ошибка добавления - {exx.Message}!");
                            Thread.Sleep(250);
                        }

                    }
                } while (Console.ReadKey(true).Key != ConsoleKey.Escape);

            }
            Console.ReadLine();
        }


    }
}

11 ноя 15, 07:08    [18398034]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
Ш.И.В.
Member

Откуда:
Сообщений: 8
Итак, коллеги.
В результате многоразовых стендовых испытаний из первого поста выяснилось следующее:
При зеркалировании если остановить процесс SQL SERVER (назовем его SRV01) на котором есть БД в роли Principal командой
NET STOP <INSTANCENAME>

Возможны следующие варианты (P-Principal, M-Mirror, X-сервер не работает, V-версия БД):

Действие Команда Роль SRV01 Роль SRV02 Результат
Опять запускаем процесс SRV01 любым способом P M Все в порядке - все транзакции сохранены
Делаем SRV02 главным без разбиения зеркала ALTER DATABASE MirrorTestDB SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS X P Потеря всех транзакций за последние секунды (последние транзакции находятся только на SRV01)
Делаем SRV02 главным без разбиения зеркала; поднимаем SRV01; восстанавливаем зеркало ALTER DATABASE MirrorTestDB SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS; ALTER DATABASE MirrorTestDB SET PARTNER RESUME M P Потеря всех транзакций за последние секунды (последние транзакции полностью утерены после восстановления зеркала)
Удаляем зеркало и поднимаем SRV01ALTER DATABASE MirrorTestDB SET PARTNER OFF; RESTORE DATABASE MirrorTestDB WITH RECOVERY V1 V2 Потеря всех транзакций за последние секунды (последние транзакции находятся только на SRV01 - получаем вилку)


Если завершать процесс SQL SERVER через диспетчер задач - все в порядке (зеркало отрабатывает отлично).
Если завершать процесс SQL SERVER через SSMS - все в порядке (зеркало отрабатывает отлично).

Ситуация с поведением зеркального отображения и команды net stop очень непонятна.
Сейчас нет возможности проверить поведение зеркала при перезагрузке (интересно каким путем завершается OS завершает работу процесса MS SQL SERVER)

Условия тестирования:
+ SRV01

Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64)
Oct 19 2012 13:38:57
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: )

OS: Windows Server 2012 R2 Datacenter Version 6.3 (Build 9600)


+ SRV02

Microsoft SQL Server 2012 (SP1) - 11.0.3153.0 (X64)
Jul 22 2014 15:26:36
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: )


OS: Windows Server 2012 R2 Datacenter Version 6.3 (Build 9600)


Если кто-нибудь сможет протестировать вариант с перезагрузкой - буду благодарен
11 ноя 15, 09:24    [18398346]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
zatar86
Member

Откуда: СПБ
Сообщений: 228
GPP_Coder а вам always on не подходит? На ent он работает. Зеркалирование - типа deprecated.
И почему разные билды sp?
11 ноя 15, 09:57    [18398476]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
zatar86
Member

Откуда: СПБ
Сообщений: 228
У зеркала
3 режима, если на русский.
— защищённый с автоматическим восстановлением
— защищённый с ручным восстановлением
— не защищённый/асинхронный

Обязательно с уведомлением клиента об успехе отработки транзакции только после гарантированной фиксации транзакций на обоих серверах! - Будет только в — защищённый с автоматическим восстановлением. т.е нет потери зафиксированных данных + следящий сервер.

— защищённый с ручным восстановлением - используют временно, если у вас следящий сервер отказал, до момента его восстановления!!!!
11 ноя 15, 10:01    [18398505]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
zatar86
Member

Откуда: СПБ
Сообщений: 228
Это как подобие- Maximum Availability в data guard
11 ноя 15, 10:06    [18398524]     Ответить | Цитировать Сообщить модератору
 Re: Зеркало. Безопасный режим и потеря данных  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
у меня на mss2008r2+sp3 для действия из 3-ей строки вашей таблицы в переключившейся из зеркала бд столько строк, сколько было залито в основную бд до остановки сервиса ее экземпляра.
тестировал в linqpad-е следующим скриптом скриптом:
static int[] counter = {0};
static string cs = @"Data Source=s82rnp\mss04np10;failover partner=s04rnp;initial catalog=ServerDB;integrated security=True";
public static void DoIns(){
  int i = 0;
  string text;
  do{
    try{
      using(SqlConnection connection = new SqlConnection(cs)){
        connection.Open();
        using(SqlTransaction transaction = connection.BeginTransaction("SampleTransaction")){
          text = String.Format("{0:yyyy-MM-dd HH:mm:ss} Thread {1} Iteration {2}",
                               DateTime.Now,
	                       Thread.CurrentThread.ManagedThreadId,
	 	               i + 1);
          string cmd = String.Format(@"INSERT INTO dbo.MirrDateTable([Text],RowAddDate)VALUES('{0}',GETDATE())", text);
          using(SqlCommand command = new SqlCommand(cmd, connection) { Transaction = transaction }){
            try{
              command.ExecuteNonQuery();
              transaction.Commit();
              Console.WriteLine(text);
              ++i;
            }catch(Exception exx1){
              try{
                transaction.Rollback();
              }catch(Exception ex2){
                Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
                Console.WriteLine(" Message: {0}", ex2.Message);
              }
              Console.WriteLine("TrnError - {0}!", exx1.Message);
              break;
            }
          }
        }
      }
    }catch (Exception exx){
      Console.WriteLine("InsError - {0}!", exx.Message);
      break;
    }
  }while(true);
  lock(counter){counter[0] += i;}
}
void Main(){
  var tt = System.Linq.Enumerable.Range(0,8).Select(_=>new Thread(new ThreadStart(DoIns))).ToArray();
  Array.ForEach(tt, t=>t.Start());
  Array.ForEach(tt, t=>t.Join());
  Console.WriteLine(counter[0]);
}


К сообщению приложен файл (mirrtest.linq - 1Kb) cкачать
11 ноя 15, 16:38    [18401282]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить