[MSSQL .NET] Как заблокировать БД?

agaaaa

Требуется на время работы программы заблокировать возможность изменения БД (пишется менеджер пакетов)?

AlexV769

транзакции - это типа не тру уже?

agaaaa

С ними есть проблемы. Если ты готов их разрешить - вперёд. Мне пока влом гуглить по этоу поводу.
Не думаю, что кому-то нужно запускать сразу два менеджера пакетов в режиме установки/удаления. Тем более, что виндовый MSI этого не позволяет.

AlexV769

С ними есть проблемы. Если ты готов их разрешить - вперёд. Мне пока влом гуглить по этоу поводу.
От имени всех админов, которые далее будут поддерживать БД, к которой ты пишешь некий интерфейс, предлагаю удалить все свои исходники и никогда больше не программировать.

agaaaa

Я и есть этот админ, нечего писать от моего имени, лол.

Helga87

С ними есть проблемы.
Может, ты и будешь узнавать, как они решаются, вместо поиска "как сделать транзакции без транзакций"?

agaaaa

Вопрос был как залочить все изменения БД на время работы программы. А не как сделать транзакции.
Впрочем, разумеется, я знаю в чём проблема с транзакциями.

agaaaa

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

AlexV769

открываем транзакцию
читаем список пакетов
строим последовательность установки
ставим первый из последовательности пакет
завершаем транзакцию
...

agaaaa

Долго

agaaaa

Вообще у меня сейчас есть транзакции, встроенные в LINQ to SQL.
Базируются на optimistic concurrency.
Проблема в том, что я пока не знаю точно как именно они себя ведут.
Давно пора купить книгу...

AlexV769

что, мне правда надо было написать, что результаты первого шага надо кешировать и сравнивать первичные данные для определения необходимости выполнения 2го шага?

agaaaa

Тебе надо было подумать, прежде чем писать это.
Совпадения входных данных (списка пакетов для установки) недостаточно для определения необходимости выполнения второго шага. В этом-то и заключается проблема.
Очевидно, список пакетов всегда тот же ;)

AlexV769

Значит схема БД по-просту построена некорректно, раз этап сбора необходимых для анализа данных (без непосредственного их анализа!) занимает больше времени, чем установка одного "пакета".

agaaaa

По-моему, ты просто пытаешься последним ответить.
Чтобы поставить пакет из одной exe-шки с 2 зависимостями достаточно проверить их наличие и скопировать эту exe-шку.
Чтобы построить дерево зависимостей для того же пакета, содержащее сотню-две других пакетов, требуется время. Ситуация, имхо, достаточно типичная (особенно если иметь дело с патчами).
Размещать ориентированный граф зависимостей в БД в виде матрицы достижимости слишком накладно с точки зрения занимаемого места (кроме того непонятно, как вписать в неё зависимости типа "хотябы одно из а, б, в").

serega1604

"хотябы одно из а, б, в"
meta-пакеты для чего по-твоему придуманы?

agaaaa

Для того, чтобы не ломать язык на словах "пакеты, имеющие зависимости типа хотя бы ...".
Однако это не решает проблемы представления их в БД.

evgen5555

Давно пора купить книгу...
Мозги бы прикупил сначала
Прошу прощения за банальность

agaaaa

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

evgen5555

безо всяких накладныъх расходов на размер БД,
А они так и так появятся

agaaaa

Как "так"? Сейчас в БД хранится список версий в одной таблице, для каждой версии список имён пакетов, которые ей нужны в другой таблице. Более короткую запись придумать нельзя.

AlexV769

Вопрос был как залочить все изменения БД на время работы программы. А не как сделать транзакции.
ты не должен этого хотеть (с)

agaaaa

я выше объяснял зачем это надо
почему, интересно, разработчики apt не сделали по-другому?

AlexV769

почему, интересно, разработчики apt не сделали по-другому?
потому что разработчики apt не используют MSSQL?

Dasar

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


begin transaction

var locked = select locked from my_install_locks
if (locked)
throw new Exception("Установка невозможна, параллельно уже выполняется другая установка");

insert my_install_locks (locked) values(true)

bla-bla
устанавливаем пакеты
bla-bla

delete my_install_locks

commit
end transaction

agaaaa

Точно! Спасибо!

Dasar

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

var locked = select locked from my_install_locks
if (locked)
throw new Exception("Установка невозможна, параллельно уже выполняется другая установка");

insert my_install_locks (locked) values(true)

6yrop

begin transaction
var locked = select locked from my_install_locks
if (locked)
  throw new Exception("Установка невозможна, параллельно уже выполняется другая установка");
insert my_install_locks (locked) values(true)
bla-bla
устанавливаем пакеты
bla-bla
delete my_install_locks
commit
end transaction
  

уровень изодяции транзакции Serializable? если да, то код странный. Вот эти строчки
 

var locked = select locked from my_install_locks
if (locked)
throw new Exception("Установка невозможна, параллельно уже выполняется другая установка");

insert my_install_locks (locked) values(true)

delete my_install_locks

можно спокойно удалить, и все будет работать абсолютно так же! (разве что вероятность дедлоков уменьшится)
Наверное имелось ввиду — разнести выставление лока и длинную операцию по разным транзакциям?

6yrop

надо делать двойную проверку(до наложения лока и после
зачем двойная проверка, если мы в транзакции?

hprt

Можно еще Single user выставить на время работы - но это совсем жестко наверное :)

Dasar

можно спокойно удалить, и все будет работать абсолютно так же! (разве что вероятность дедлоков уменьшится)
поведение разное
в одном случае вторая инсталяция прерывается с ошибкой, во втором случае - она повисает на локах на неопределенное время
соответственно на это будет накладываться на то, что serializable транзакции дорогие, и что надо быть аккуратным с использованием всех таблиц из под такой транзакции - даже вспомогательных
например, мы в инсталяшку запихали чисто в трасировочных целях вот такое сообщение:
Trace.Write(select count(*) from user_objects);
но в итоге такая безобидная строчка - запрещает изменение user_objects на все время выполнения инсталяции с использованием serializable транзакций
ps
т.е. решение с serializable - имеет право на жизнь, но это разные решения: одно с явной проверкой, другое - с неявной.

klyv

begin transaction

var locked = select locked from my_install_locks
if (locked)
throw new Exception("Установка невозможна, параллельно уже выполняется другая установка");

insert my_install_locks (locked) values(true)

bla-bla
устанавливаем пакеты
bla-bla

delete my_install_locks

commit
end transaction
а то же ли самое:
begin transaction 'some_unique_name'
--doit
commit transaction 'some_unique_name'
end transaction 'some_unique_name'
Я же правильно понимаю, что в системе не м.б. 2х транзакций одноимённых?

Dasar

Я же правильно понимаю, что в системе не м.б. 2х транзакций одноимённых?
хз, с именнованными транзакциями не сталкивался.
и с ходу по msdn-у не понял, может быть две транзакции с одним именем, или нет...

Dasar

Я же правильно понимаю, что в системе не м.б. 2х транзакций одноимённых?
но в целом я сомневаюсь, что, например, у разных пользователей транзакции не могут иметь одно и тоже имя - т.к. если такое есть, то имея минимальные права можно легко положить базу целиком.
да и в разных сессиях - имена скорее всего тоже можно делать одиннаковыми - иначе получается, что если один тот же код пускается два раза, то генерит уникальные имена транзакции... такой генерации не припоминаю чтобы встречалось.

klyv

имея минимальные права можно легко положить базу целиком
тогда в эти минимальные права должна входить возможность создавать порядка 2^(64*8) транзакций ;)

Dasar

тогда в эти минимальные права должна входить возможность создавать порядка 2^(64*8) транзакций
либо поставить такую же систему себе на комп и посмотреть как называются транзакции.

6yrop

не стоит выдирать из контекста отдельные фразы, я четко указзал условие "если уровень изоляции Serializable".
т.к. какой у тебя уровень изоляции в первоначальном посте?

6yrop

и что надо быть аккуратным
с остальными уровнями изоляции надо быть еще внимательнее
 
но в итоге такая безобидная строчка - запрещает изменение user_objects на все время выполнения инсталяции с использованием serializable транзакций
  

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

Dasar

и что? вполне себе безобидная ошибка, по крайней мере, не прошли неверные операции.
не хрена себе безобидная, если обновление длится, например, десятки минут, то на эти десятки минут подвисают все пользователи активно меняющие эти самые user_objects.

klyv

и посмотреть как называются транзакции
имена могут генерироваться на лету ;)
а доступ к таблице, в которой их хранить, необязательно давать всем подряд

Dasar

имена могут генерироваться на лету
можно конечно, но как уже говорил выше, с ходу такое по примерам и исходникам не припоминаю

6yrop

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

6yrop

не даром же у TransactionScope по умолчанию стоит уровень изоляции Serializable
Оставить комментарий
Имя или ник:
Комментарий: