Pentru o aplicatie de cantarire am facut cateva teste de utilizare a programului, o simulare de peste 7,000 de retete pe zi, timp de cateva zile.
Dupa o vreme, uneori dupa cateva ore de utilizare, alteori dupa cateva zile, obtin o eroare la introducerea datelor in SQL:
14-Oct-2017 12:17 - Task #0 retry 0 create cantariri (pymssql.IntegrityError) (2627, "Violation of PRIMARY KEY constraint 'PK__Cantarir__3213E83FDC5B857F'. Cannot insert duplicate key in object 'dbo.Cantariri'. The duplicate key value is (1041876).DB-Lib error message 20018, severity 14:\nGeneral SQL Server error: Check messages from the SQL Server\n") [SQL: 'INSERT INTO [Cantariri] (dataora, id_sarja, id_ingredient, valoare, dozarevalida) OUTPUT inserted.id VALUES (%(dataora)s, %(id_sarja)s, %(id_ingredient)s, %(valoare)s, %(dozarevalida)s)'] [parameters: {'dozarevalida': 1, 'valoare': 991.0, 'id_ingredient': 3, 'dataora': datetime.datetime(2017, 10, 14, 12, 17, 18, 886000), 'id_sarja': 365234}]
Cred ca este o consecinta a utilizarii parametrului -T272 la pornirea serverului SQL, ca sa rezolve o problema mentionata de mine mai de mult.
Ca sa ocolesc problema fara sa pierd date, in program am inserat o secventa de reluare de cateva ori (SQL_RETRY) a tranzactiei SQL, pana se termina cu succes sau se epuizeaza numarul de incercari. In caz de eroare, tranzactia este abandonata (rollback):
...
...
...
for i in range(SQL_RETRY):
try:
cantarire = Cantariri()
cantarire.dataora = datetime.datetime.now()
cantarire.id_sarja = sarja.id
cantarire.id_ingredient = id_ingredient
cantarire.id_operator = operator.id
cantarire.valoare = greutate_dozare
if abs(cantarire.valoare - cantitate) <= toleranta:
cantarire.dozarevalida = 1
else:
cantarire.dozarevalida = 0
if isvqm:
flag_vqm_valid = False
session.add(cantarire)
session.commit()
greutate_sac += cantarire.valoare
greutate_dozare = 0
confirmare_target = False
break
except Exception as ex:
self.log('Task #{} retry {} create cantariri\n{}'.format(ix, i, str(ex)))
session.rollback()
time.sleep(0.5)
#aici trebuie sa scriu in log ca tranzactia SQL a esuat de SQL_RETRY ori
...
...
...
In testele mele niciodata nu au fost doua erori SQL de integritate consecutive (s-ar fi vazut in log-uri numarul de incercari esuate), intotdeauna la a doua incercare datele au fost memorate cu succes.