[elephant-devel] Re: Updated version of last Postmodern patch bundle

Robert L. Read read at robertlread.net
Mon Mar 17 02:44:28 UTC 2008


Dear Alex,

	Thank you very much for taking the time to deal with this.  I
personally don't have much of an opinion about how it should be
done---except that it sure seems like a good idea to make it
configurable, which ought to keep everybody happy, and prevents me
having to make a decision I am poorly-qualified to make.

	Could you make this configurable?  I would be happy to document it and
commit it if it were configurable (and if we can get to a proven green
state, which might be a little tricky right at the moment---but we can
save the patch for when we get it ironed out.)

On Sun, 2008-03-16 at 23:26 +0200, Alex Mizrahi wrote:
>  LPP> It's a performance decision...
> 
> as far as i know with MVCC higher isolation level does not cause performance 
> penalties unless you really have conflicts.
> at least some postgresql experts said me this.
> 
>  LPP> go, but the rest of the code should try hard not to expose any
>  LPP> avoidable errors if the user decides to switch to another isolation
>  LPP> level...
> 
> switching to another isolation level user gets concurrent conflicts. why 
> should we try to detect them in our code when DB can handle them in 
> centralized fashion?
> this sounds like an "ugly workaround" for me.
> 
>  LPP> In any case, can you send a patch for the change of the default
>  LPP> isolation level, and probably a public convenience function/sc arg to
>  LPP> change it?
> 
> changing isolation level is dead simple, but it requires dealing with 
> consequences. this was pretty hard for application i'm working with, so i 
> had to make extensions like retry-cleanup-fn.
> and stuff is not configurable because i thought serializable would be good 
> for everybody, but if you insist we should have "read committed" too, i'll 
> make it for you.
> below is work-in-progress patch:
> 
> --- old-elephant/src/db-postmodern/pm-transaction.lisp Wed Jan 16 23:07:43 
> 2008
> +++ new-elephant/src/db-postmodern/pm-transaction.lisp Fri Mar 14 15:00:02 
> 2008
> @@ -26,30 +26,70 @@
>  (defun txn-cache-clear-value (bt key)
>    (cache-clear-value *txn-value-cache* bt key))
> 
> +(defun execute-transaction-one-try (sc txn-fn always-rollback)
> +  (let (tran commited
> + (*txn-value-cache* (make-value-cache sc)))
> +    (incf (tran-count-of sc))
> +    (setf tran (controller-start-transaction sc))
> +    (unwind-protect
> +  (multiple-value-prog1
> +      (funcall txn-fn)
> +    (unless always-rollback ; automatically commit unless always-rollback 
> is on
> +      (controller-commit-transaction sc tran)
> +      (setf commited t)))
> +      (unless commited (controller-abort-transaction sc tran))
> +      (decf (tran-count-of sc)))))
> +
> +(defmacro with-concurrency-errors-handler (&body body)
> +  "execute body with a handler catching postgres concurrency errors
> +   and invoking restart-transaction restart automatically"
> +  `(handler-bind
> +    ((cl-postgres:database-error
> +      (lambda (c)
> + (let ((err-code (cl-postgres:database-error-code c)))
> +   (when (or (string= err-code "40001") ; SERIALIZATION FAILURE
> +      (string= err-code "40P01")); DEADLOCK DETECTED
> +     (invoke-restart 'retry-transaction c))))))
> +    , at body))
> +
>  (defmethod execute-transaction ((sc postmodern-store-controller) txn-fn
> -    &key (always-rollback nil) &allow-other-keys)
> -  ;; SQL doesn't support nested transaction
> +    &key (always-rollback nil)
> +    (retry-cleanup-fn nil)
> +    (retries 10) &allow-other-keys)
>    (with-postmodern-conn ((controller-connection-for-thread sc))
>      (if (> (tran-count-of sc) 0)
> -        (funcall txn-fn)
> -        (let (tran
> -       commited
> -       (*txn-value-cache* (make-value-cache sc)))
> -          (incf (tran-count-of sc))
> -          (unwind-protect
> -        (prog2
> -     (setf tran (controller-start-transaction sc))
> -     (funcall txn-fn) ;;this gets returned
> -   (unless always-rollback ;;automatically commit unless always rollback
> -     (controller-commit-transaction sc tran)
> -     (setf commited t)))
> -     (unless commited (controller-abort-transaction sc tran))
> -     (decf (tran-count-of sc)))))))
> +
> + ;; SQL doesn't support nested transaction
> + ;; TODO: perhaps it's worth detecting abnormal exit here
> + ;; and abort parent transaction too.
> + (with-concurrency-errors-handler (funcall txn-fn))
> +
> + (loop named txn-retry-loop
> +   ;; NB: it does (1+ retries) attempts, 1 try + retries.
> +   for try from retries downto 0
> +   do (block txn-block
> +        (restart-bind ((retry-transaction
> +          (lambda (&optional condition)
> +     (when (and retry-cleanup-fn
> +         (not (= try 0))) ; cleanup is skipped when we are exiting
> +       (funcall retry-cleanup-fn condition sc))
> +     (return-from txn-block))
> +          :report-function (lambda (s) (princ "retry db-postmodern 
> transaction" s)))
> +         (abort-transaction
> +          (lambda () (return-from txn-retry-loop))))
> +        (with-concurrency-errors-handler
> +          (return-from txn-retry-loop
> +     (execute-transaction-one-try sc txn-fn always-rollback)))))
> +   finally (error 'transaction-retry-count-exceeded
> +    :format-control "Transaction exceeded the ~A retries limit"
> +    :format-arguments (list retries)
> +    :count retries)))))
> +
> 
>  (defmethod controller-start-transaction ((sc postmodern-store-controller) 
> &key &allow-other-keys)
>    (with-postmodern-conn ((controller-connection-for-thread sc))
>      (let ((transaction (make-instance 'postmodern::transaction-handle)))
> -      (postmodern:execute "BEGIN")
> +      (postmodern:execute "BEGIN ISOLATION LEVEL SERIALIZABLE")
>        transaction)))
> 
>  (defmethod controller-commit-transaction ((sc postmodern-store-controller) 
> transaction &key &allow-other-keys)
> 
> 
> 
> 
> 
> 
> _______________________________________________
> elephant-devel site list
> elephant-devel at common-lisp.net
> http://common-lisp.net/mailman/listinfo/elephant-devel




More information about the elephant-devel mailing list