(Maybe) Parallel Madness!
Πόσες φορές μέχρι σήμερα δεν σας έτυχε να φτάσετε στα όρια της παράνοιας, της παραλίγο Ζαχαρίασης με την προοπτική της ανάγκης για μεταμόσχευση ύπατος πολύ κοντά, και όλα αυτά από ένα "bug" που απλά "Δεν γίνεται, δεν είναι λογικό"; Πολλές φαντάζομαι. Να ακόμη μία.
Έρχεται που λέτε το email του πελάτη. "Αξιότιμοι κύριοι, όταν κάνω αυτό και αυτό τότε παίρνω αυτό και αυτό και σας παρακαλώ μπλα μλπα μπλα και δεν γίνεται μπλα μλπα μλπα... as soon as possible! Regards...". Το exception που έπερνε ήταν ένα sqlexception που μιλά για παραβίαση foreing key constraint.
Χμ ας δούμε τι γίνεται. Κάνουμε αυτό και αυτό και... τίποτα! Το ξανακάνουμε... τιποτα! Δεν γίνεται, η αυτός έχει παρανοήσει ή εγώ τα εχω παίξει! Αλλά, το exception που μας έστειλε πού το βρήκε(Βλέπετε είμαστε σε beta, το exception handling δεν έχει ολοκληρωθεί ακόμα, μας έστειλε "ωμό" το exception που έφαγε, ντροπή...); Επικοινωνούμε και πάλι μαζί του να δούμε τι θα γίνει. "Ξέρετε", μας λεει "δεν μου ξανάτυχε από τότε, αλλά μου ξανασυνέβη την περασμένη βδομάδα. Συμβαίνει κάποιες φορές". Τί λεει αυτός; Περιστασιακά; Δεν γίνεται. Αν παραβιάζεται το foreing key constraint τότε παραβιάζεται κάθε φορά που καλείται η sp και όχι ... κάθε Παρασκευή! Αν δεν μπορώ να το αναπαράγω πώς θα το λύσω; Μάλλον θα του εκδώσω (του πελάτη) πιστοποιητικό παράνοιας τρίτου βαθμού. Αλλά το exception; WTF! Λες να έχουν παρανοήσει οι νόμοι της φύσης; Δεν γίνεται, ως απόλυτος ορθολογιστής ξέρω ότι κάτι συμβαίνει, κάτι πολύ κουφό η περίεργο... Ας δούμε λοιπόν τι έχουμε
Η sp που λέτε(στα πρόχειρα...):
BEGIN TRANSACTION
INSERT INTO TABLE1 (...)
VALUES (...)
IF @@ERRORCOUNT > 0
BEGIN
ROLLBACK TRANSACTION
END
INSERT INTO TABLE2(...)
VALUES(...)
IF @@ERRORCOUNT > 0
BEGIN
ROLLBACK TRANSACTION
END
COMMIT TRANSACTION
Ο TABLE2 έχει Foreing key constraint στο Primary του TABLE1. Το exception θα το φάμε μόνο αν το δεύτερο insert statement εκτελεστεί πρίν το πρώτο. Και πώς να γίνει αυτό; Εδώ ήταν που μου κατέβηκε η εξής ιδέα.
1) Ο SQL Server υποστηρίζει parallel query execution. Ενεργό by default
2) H sp έχει δυο statements.
3) Ο server είναι Dual Core. Άρα λογικά θα έχουμε παράλληλη εκτέλεση
Το execution plan της sp δινει 38% στο πρώτο statement και 62% στο δεύτερο. Άρα υπό κανονικές συνθήκες το πρώτο εκτελείται πάντα πριν το δεύτερο. Τώρα άν για οποιοδήποτε λόγο (bottleneck στον ένα από τους δύο επεξεργαστές) το δεύτερο εκτελεστεί πρίν το πρώτο τότε θα φάς exception! Είναι η μόνη λογική εξήγηση που σκέφτηκα. Τώρα το πώς λύνεται είναι απλό(νομίζω...). Απλά προσθέτεις ένα ELSE μετά το πρώτο IF. Έτσι υποχρεώνεις τον Server να εκτελέσει το πρώτο statement και αφότου επιτύχει τότε να προχωρήσει στο δεύτερο. Το πιο πάνω πάντως παραμένει εικασία μέχρι την αναίρεση της από το επόμενο exception (Φτου, φτου, φτου...)!
Γι αυτό, οιεσδήποτε άλλες εισηγήσεις ή παρατηρήσεις ευπρόσδεκτες!