quieres algo a lo largo de las siguientes líneas.
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)
Nota la simetría. Cada niño comienza teniendo un recurso. Luego intentan obtener el recurso retenido de otra persona. Puede, por diversión, tener 3 hijos y 3 recursos para un círculo realmente vicioso.
Tenga en cuenta que es difícil solucionar una situación en la que se produce un interbloqueo. Si sus transacciones son cortas y constantes, es muy difícil lograr un punto muerto. El punto muerto requiere (a) una transacción que mantenga bloqueos durante un tiempo prolongado Y (b) transacciones que adquieren bloqueos en un orden incoherente. He encontrado que es más fácil evitar interbloqueos manteniendo mis transacciones cortas y consistentes.
También tenga en cuenta el no determinismo. No puede predecir qué niño morirá con un punto muerto y qué continuará después de que el otro muera. Solo uno de los dos debe morir para liberar los recursos necesarios para el otro. Algunos RDBMS afirman que hay una regla basada en la cantidad de recursos que posee, bla, bla, bla, pero en general, nunca sabrá cómo se eligió a la víctima.
Debido a que las dos escrituras están en un orden específico, se espera que primero muera el hijo 1. Sin embargo, no puedes garantizar eso. No es un punto muerto hasta que el niño 2 intente obtener los recursos del niño 1: la secuencia de quién adquirió primero no puede determinar quién muere.
También tenga en cuenta que estos son procesos, no hilos. Los subprocesos, debido a Python GIL, podrían sincronizarse inadvertidamente y requerirían muchas llamadas al time.sleep(0.001)
para darle al otro subproceso la oportunidad de ponerse al día. Los procesos, por esto, son un poco más simples porque son completamente independientes.
Eso solo causaría un error operacional: (1205, 'Se agotó el tiempo de espera de espera de bloqueo; intente reiniciar la transacción'), ¿no? – Greg
@Greg: Creo que están hablando de una sesión haciendo LOCK TABLE A, y otra sesión haciendo LOCK TABLE B. Deben sincronizarse de alguna manera en este momento. Luego, la sesión uno intenta una TABLA DE BLOQUEO B. Cuando la sesión dos intenta BLOQUEAR LA TABLA A, bloqueará. –