Сборка | Build Project показывает все ошибки в проекте.
можно всегда выполнять имя таблицы ТАБЛИЦЫ БЛОКИРОВКИ от другой сессии (mysql CLI, например). Это могло бы добиться цели.
Это останется заблокированным, пока Вы не выпустите его или разъедините сессию.
Я не familar с Python, так извините мой неправильный язык, Если я говорю, что эта несправедливость..., но открывает две сессии (в отдельных окнах, или от отдельных процессов Python - от отдельных полей работал бы...), Затем...
. На сессии A:
Begin Transaction
Insert TableA() Values()...
. Затем на сессии B:
Begin Transaction
Insert TableB() Values()...
Insert TableA() Values() ...
. Затем вернитесь к сессии A
Insert TableB() Values () ...
Вы получите мертвую блокировку...
Вы хотите что-то вдоль следующих строк.
parent.py
import subprocess
c1= subprocess.Popen( ["python", "child.py", "1"], stdin=subprocess.PIPE, stdout=subprocess.PIPE )
c2= subprocess.Popen( ["python", "child.py", "2"], stdin=subprocess.PIPE, stdout=subprocess.PIPE )
out1, err1= c1.communicate( "to 1: hit it!" )
print " 1:", repr(out1)
print "*1:", repr(err1)
out2, err2= c2.communicate( "to 2: ready, set, go!" )
print " 2:", repr(out2)
print "*2:", repr(err2)
out1, err1= c1.communicate()
print " 1:", repr(out1)
print "*1:", repr(err1)
out2, err2= c2.communicate()
print " 2:", repr(out2)
print "*2:", repr(err2)
c1.wait()
c2.wait()
child.py
import yourDBconnection as dbapi2
def child1():
print "Child 1 start"
conn= dbapi2.connect( ... )
c1= conn.cursor()
conn.begin() # turn off autocommit, start a transaction
ra= c1.execute( "UPDATE A SET AC1='Achgd' WHERE AC1='AC1-1'" )
print ra
print "Child1", raw_input()
rb= c1.execute( "UPDATE B SET BC1='Bchgd' WHERE BC1='BC1-1'" )
print rb
c1.close()
print "Child 1 finished"
def child2():
print "Child 2 start"
conn= dbapi2.connect( ... )
c1= conn.cursor()
conn.begin() # turn off autocommit, start a transaction
rb= c1.execute( "UPDATE B SET BC1='Bchgd' WHERE BC1='BC1-1'" )
print rb
print "Child2", raw_input()
ra= c1.execute( "UPDATE A SET AC1='Achgd' WHERE AC1='AC1-1'" )
print ta
c1.close()
print "Child 2 finish"
try:
if sys.argv[1] == "1":
child1()
else:
child2()
except Exception, e:
print repr(e)
Отметьте симметрию. Каждый ребенок начинает держать один ресурс. Затем они пытаются получить чужой сохраненный ресурс. У Вас, для забавы, может быть 3 ребенка и 3 ресурса для действительно порочного круга.
Обратите внимание, что трудность при изобретении ситуации, в которой происходит мертвая блокировка. Если Ваши транзакции коротки - и последовательны - мертвой блокировки очень трудно достигнуть. Мертвая блокировка требует (a) транзакции, которые содержат блокировки в течение долгого времени И (b) транзакций, которые получают, привязывает непоследовательный порядок. Я нашел самым легким предотвратить мертвые блокировки путем сохранения моих транзакций короткими и последовательными.
Также отметьте недетерминизм. Вы не можете предсказать, какой ребенок умрет с мертвой блокировкой и который продолжится после другого умер. Только один из этих двух должен умереть для высвобождения необходимых средств на другой. Заявление некоторого RDBMS, что существует правило на основе количества ресурсов, сохраненных и тому подобное, но в целом, Вы никогда не будете знать, как жертва была выбрана.
Из-за двух записей, находящихся в определенном порядке, Вы сортируете, ожидают, что ребенок 1 умрет сначала. Однако Вы не можете гарантировать это. Это не мертвая блокировка до ребенка 2 попытки получить ребенка 1 ресурсы - последовательность того, кто получил, сначала может не определить, кто умирает.
Также обратите внимание, что это процессы, не потоки. Потоки - из-за GIL Python - могли бы непреднамеренно синхронизироваться и потребуют большого количества вызовов к time.sleep( 0.001 )
дать другому потоку шанс нагнать. Процессы - для этого - немного более просты, потому что они полностью независимы.
Не уверен, правильно ли что-то из вышеперечисленного. Посмотрите это:
http://www.xaprb.com/blog/2006/08/08/how-to-deliberately-cause-a-deadlock-in-mysql/