{"action":"created","issue":{"url":"https://api.github.com/repos/rails/rails/issues/23407","labels_url":"https://api.github.com/repos/rails/rails/issues/23407/labels{/name}","comments_url":"https://api.github.com/repos/rails/rails/issues/23407/comments","events_url":"https://api.github.com/repos/rails/rails/issues/23407/events","html_url":"https://github.com/rails/rails/pull/23407","id":130468679,"number":23407,"title":"Fix corrupt transaction state caused by `before_commit` exceptions","user":{"login":"jeremy","id":199,"avatar_url":"https://avatars.githubusercontent.com/u/199?v=3","gravatar_id":"","url":"https://api.github.com/users/jeremy","html_url":"https://github.com/jeremy","followers_url":"https://api.github.com/users/jeremy/followers","following_url":"https://api.github.com/users/jeremy/following{/other_user}","gists_url":"https://api.github.com/users/jeremy/gists{/gist_id}","starred_url":"https://api.github.com/users/jeremy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeremy/subscriptions","organizations_url":"https://api.github.com/users/jeremy/orgs","repos_url":"https://api.github.com/users/jeremy/repos","events_url":"https://api.github.com/users/jeremy/events{/privacy}","received_events_url":"https://api.github.com/users/jeremy/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-02-01T20:06:22Z","updated_at":"2016-02-01T20:29:42Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/rails/rails/pulls/23407","html_url":"https://github.com/rails/rails/pull/23407","diff_url":"https://github.com/rails/rails/pull/23407.diff","patch_url":"https://github.com/rails/rails/pull/23407.patch"},"body":"When a `before_commit` callback raises, the database is rolled back but\r\nAR's record of the current transaction is not, leaving the connection in\r\na perpetually broken state that affects all future users of the\r\nconnection: subsequent requests, jobs, etc. They'll think a transaction\r\nis active when none is, so they won't BEGIN on their own. This manifests\r\nas missing `after_commit` callbacks and broken ROLLBACKs.\r\n\r\nThis happens because `before_commit` callbacks fire before the current\r\ntransaction is popped from the stack, but the exception-handling path\r\nthey hit assumes that the current transaction was already popped. So the\r\ndatabase ROLLBACK is issued, but the transaction stack is left intact.\r\n\r\nCommon cause: deadlocked `#touch`, which is now implemented with\r\n`before_commit` callbacks.\r\n\r\nWhat's next:\r\n* We shouldn't allow active transaction state when checking in or out\r\n  from the connection pool. Verify that conns are clean.\r\n* Closer review of txn manager sad paths. Are we missing other spots\r\n  where we'd end up with incorrect txn state? What's the worst that can\r\n  happen if txn state drifts? How can we guarantee it doesn't and\r\n  contain the fallout if it does?\r\n\r\nThanks for @tomafro for expert diagnosis!"},"comment":{"url":"https://api.github.com/repos/rails/rails/issues/comments/178172390","html_url":"https://github.com/rails/rails/pull/23407#issuecomment-178172390","issue_url":"https://api.github.com/repos/rails/rails/issues/23407","id":178172390,"user":{"login":"tomafro","id":1287,"avatar_url":"https://avatars.githubusercontent.com/u/1287?v=3","gravatar_id":"","url":"https://api.github.com/users/tomafro","html_url":"https://github.com/tomafro","followers_url":"https://api.github.com/users/tomafro/followers","following_url":"https://api.github.com/users/tomafro/following{/other_user}","gists_url":"https://api.github.com/users/tomafro/gists{/gist_id}","starred_url":"https://api.github.com/users/tomafro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tomafro/subscriptions","organizations_url":"https://api.github.com/users/tomafro/orgs","repos_url":"https://api.github.com/users/tomafro/repos","events_url":"https://api.github.com/users/tomafro/events{/privacy}","received_events_url":"https://api.github.com/users/tomafro/received_events","type":"User","site_admin":false},"created_at":"2016-02-01T20:29:42Z","updated_at":"2016-02-01T20:29:42Z","body":"Just double-double-checked this fixes my reproducible case and it does. Thanks @jeremy."}}