Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Взаимоблокировки / 23 сообщений из 23, страница 1 из 1
17.08.2018, 15:54
    #39689554
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Подскажите если у меня в цикле проходит обращение в процедуре и происходит взаимоблокировка, как я могу избежать этого?

Посоветовали concurent dictionary - то я даже нагуглить не смог

Пробовал SERIALIZABLE - не помогло
...
Рейтинг: 0 / 0
17.08.2018, 15:59
    #39689558
Гавриленко Сергей Алексеевич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Начните, для начала, с публикации сообщения об ошибке.
...
Рейтинг: 0 / 0
17.08.2018, 16:00
    #39689560
Владимир Затуливетер
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0,

ConcurrentDictionary это вроде как из C#, вам точно это для SQL Server посоветовали?
https://msdn.microsoft.com/ru-ru/library/dd287191(v=vs.110).aspx

Вам вероятно придется код скинуть этих процедур, иначе сложно помочь.
...
Рейтинг: 0 / 0
17.08.2018, 18:47
    #39689632
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Да вот я тоже увидел что это для C, сначала я пытался эмитировать взаимо блокировку, а теперь нужно решение как обойти))

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
	SET NOCOUNT ON;
	
	set xact_abort on; -- специально 
	
		begin TRANSACTION
		
Какой то код ...
		
		commit transaction;

	
	return 0
...
Рейтинг: 0 / 0
17.08.2018, 18:50
    #39689633
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
В том то и дело, что ошибки у меня нету, но когда выполняется в цикле то иногда выдает "0"
...
Рейтинг: 0 / 0
17.08.2018, 19:20
    #39689648
Гавриленко Сергей Алексеевич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0, ваш поток сознания слишком мутный, чтобы в нем что-то углядеть.
Взаимоблокировка имеет четкое определение и всегда заканчивается тем, что один из потоков отстреливается с соответствующей ошибкой.
...
Рейтинг: 0 / 0
17.08.2018, 19:27
    #39689649
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
У меня цикл включается в API и потом пуляет на SQL я просто тупо не знаю как мне увидеть эту взаимоблокировку.

Когда во время своего цикла я нажимаю sp_lock то показывает очень много Х

Я смотрел в Управление - Журнале MS SQL но так не чего и не увидел там

Ошибки происходят 100, потому что из цикла к примеру на 100 оборотов, добавляет в базу только 70+-, а должен добавить 100

И тут вопрос толи он не успевает добавить в базу, то ли взаимо блокировки но где ошибку посмотреть
...
Рейтинг: 0 / 0
17.08.2018, 19:29
    #39689650
Гавриленко Сергей Алексеевич
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Ну так разберитесь в вашем API, как получать ошибки, и залогируйте их.
...
Рейтинг: 0 / 0
17.08.2018, 19:51
    #39689658
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Такс отлично, ошибок я получил 180 штук, все идентичны

"Транзакция (идентификатор процесса РАЗНОЕ ЧИСЛО) вызвала взаимоблокировку ресурсов блокировка с другим процессом и стала жертвой взаимоблокировки. Запустите транзакцию повторно."

Теперь мы уверены что это взаимно блокировки, теперь если я подниму уровень изоляции до Repetable Read это меня спасет?
...
Рейтинг: 0 / 0
17.08.2018, 19:57
    #39689660
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
SERIALIZABLE даже он не помог :(
...
Рейтинг: 0 / 0
17.08.2018, 20:10
    #39689665
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Вот код

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
	SET NOCOUNT ON;
	
	set xact_abort on;
	
		begin TRANSACTION
		
    	insert into dbo.City([From])
		select @from
		
		IF NOT EXISTS(SELECT * FROM Estimate (NOLOCK) a WHERE a.id = @Id)
		BEGIN
			INSERT INTO Estimate (id, sum)
			SELECT @Id, -@sum
		END 
		ELSE 
		BEGIN
			UPDATE Estimate
				SET sum = sum - @sum
			WHERE id = @Id
		END


		IF NOT EXISTS(SELECT * FROM Estimate (NOLOCK) a WHERE a.id = @Id)
		BEGIN
			INSERT INTO Estimate (id, sum)
			SELECT @Id, -@sum
		END 
		ELSE 
		BEGIN
			UPDATE Estimate
				SET sum = sum - @sum
			WHERE id = @Id
		END

		
		commit transaction;;

	
	return 0
...
Рейтинг: 0 / 0
17.08.2018, 20:26
    #39689669
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Если все 3 блока разбить на отдельные транзакции все будет работать, скажите правильно ли это?
...
Рейтинг: 0 / 0
18.08.2018, 11:36
    #39689744
nvv
nvv
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0, вероятно две сессии пишут один id. Или по id нет индекса.
Очевидно же, что дедлок на апдейте.
Serializable - помочь не сможет, на блокировке диапазонов сделает только хуже.
...
Рейтинг: 0 / 0
18.08.2018, 12:17
    #39689748
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0Вот код

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
	SET NOCOUNT ON;
	
	set xact_abort on;
	
		begin TRANSACTION
		
    	insert into dbo.City([From])
		select @from
		
		IF NOT EXISTS(SELECT * FROM Estimate (NOLOCK) a WHERE a.id = @Id)
		BEGIN
			INSERT INTO Estimate (id, sum)
			SELECT @Id, -@sum
		END 
		ELSE 
		BEGIN
			UPDATE Estimate
				SET sum = sum - @sum
			WHERE id = @Id
		END


		IF NOT EXISTS(SELECT * FROM Estimate (NOLOCK) a WHERE a.id = @Id)
		BEGIN
			INSERT INTO Estimate (id, sum)
			SELECT @Id, -@sum
		END 
		ELSE 
		BEGIN
			UPDATE Estimate
				SET sum = sum - @sum
			WHERE id = @Id
		END

		
		commit transaction;;

	
	return 0



Ну, если у вас все верно написано - это эвивалентно

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
begin TRANSACTION;
            
		
    	    insert into dbo.City([From])
		    select @from;
		
		
            with t as ( SELECT * FROM Estimate  )
               , x as ( SELECT id = @Id, sum = - @sum )
              merge t using x on t.id = x.id
                when not matched then insert(id, sum) values(id, sum)
                when matched then update set sum = sum + 2 * x.sum
		
commit transaction;
...
Рейтинг: 0 / 0
19.08.2018, 07:31
    #39689878
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
nvv, да, я с вами полностью согласен на изменении дедлоки
...
Рейтинг: 0 / 0
19.08.2018, 07:58
    #39689879
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
aleks222, я сильно извиняюсь, но с кодом ппц намудрил, вот как должно быть

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
	SET NOCOUNT ON;
	
	set xact_abort on;
	
		begin TRANSACTION
		
    	insert into dbo.City([From])
		select @from
		
		IF NOT EXISTS(SELECT * FROM Estimate (NOLOCK) a WHERE a.id = @to)
		BEGIN
			INSERT INTO Estimate (id, sum)
			SELECT @to, -@sum
		END 
		ELSE 
		BEGIN
			UPDATE Estimate
				SET sum = sum - @sum
			WHERE id = @to
		END


		IF NOT EXISTS(SELECT * FROM Estimate (NOLOCK) a WHERE a.id = @from)
		BEGIN
			INSERT INTO Estimate (id, sum)
			SELECT @from, +@sum
		END 
		ELSE 
		BEGIN
			UPDATE Estimate
				SET sum = sum + @sum
			WHERE id = @ from
		END

		
		commit transaction;;

	
	return 0



извините еще раз пожалуйста
...
Рейтинг: 0 / 0
19.08.2018, 10:01
    #39689894
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0,

Замените вашу череду excists/insert/update на это
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
merge into Estimate t
using
(
 values
  (@from, @sum), (@to, -@sum)
) s(id, sum)
when not matched then
 insert (id, sum) values (s.id, s.sum)
when matched then
 update set sum += s.sum;


О дедлоке можно предметно говорить, если покажете его граф (в виде ml, картинка бесполезна).
...
Рейтинг: 0 / 0
19.08.2018, 13:54
    #39689972
Pabl0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
А если как я сделал в отдельные транзакции это не правильно?
...
Рейтинг: 0 / 0
19.08.2018, 14:17
    #39689984
Владимир Затуливетер
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0,

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

Лучше попробуйте разобраться с предложенным merge решением. Вы сохраняете транзакцию и не делаете лишних движений.
...
Рейтинг: 0 / 0
19.08.2018, 14:43
    #39690000
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0А если как я сделал в отдельные транзакции это не правильно?Ну если вам наплевать, что, например, к @from @sum прибавится, а от @to @sum не отнимется, то можете вообще не заморачиваться с транзакциями.

Если таки решите разобраться с транзакциями и дедлоками, то мой пример лучше переписать так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
declare @s table (id ... primary key, sum ...);
insert into @s
values
 (@from, @sum), (@to, -@sum)

merge into Estimate t
using @s s on s.id = t.id
when not matched then
 insert (id, sum) values (s.id, s.sum)
when matched then
 update set sum += s.sum;


ЗЫ: А исходный пример надо бы поправить
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
merge into Estimate t
using
(
 values
  (@from, @sum), (@to, -@sum)
) s(id, sum) s on s.id = t.id
when not matched then
 insert (id, sum) values (s.id, s.sum)
when matched then
 update set sum += s.sum;
...
Рейтинг: 0 / 0
20.08.2018, 10:03
    #39690243
Владимир Затуливетер
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
invmлучше переписать так
Поясните пожалуйста почему лучше?
...
Рейтинг: 0 / 0
20.08.2018, 10:12
    #39690248
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Владимир ЗатуливетерПоясните пожалуйста почему лучше?Чтобы снизить вероятность дедлока, если несколько сессий пересекуться по (@from, @to).
...
Рейтинг: 0 / 0
20.08.2018, 14:33
    #39690434
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Взаимоблокировки
Pabl0,

Код: sql
1.
IF NOT EXISTS(SELECT * FROM Estimate (NOLOCK) a WHERE a.id = @from)



(NOLOCK) не используйте в процедурах, изменяющих данные или готовящих изменения. Потом будете списывать загадочные случаи на "компьютерный сбой" :)
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Взаимоблокировки / 23 сообщений из 23, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]