# File lib/active_record/connection_adapters/abstract/database_statements.rb, line 166
      def transaction(options = {})
        options.assert_valid_keys :requires_new, :joinable

        last_transaction_joinable = defined?(@transaction_joinable) ? @transaction_joinable : nil
        if options.has_key?(:joinable)
          @transaction_joinable = options[:joinable]
        else
          @transaction_joinable = true
        end
        requires_new = options[:requires_new] || !last_transaction_joinable

        transaction_open = false
        @_current_transaction_records ||= []

        begin
          if block_given?
            if requires_new || open_transactions == 0
              if open_transactions == 0
                begin_db_transaction
              elsif requires_new
                create_savepoint
              end
              increment_open_transactions
              transaction_open = true
              @_current_transaction_records.push([])
            end
            yield
          end
        rescue Exception => database_transaction_rollback
          if transaction_open && !outside_transaction?
            transaction_open = false
            decrement_open_transactions
            if open_transactions == 0
              rollback_db_transaction
              rollback_transaction_records(true)
            else
              rollback_to_savepoint
              rollback_transaction_records(false)
            end
          end
          raise unless database_transaction_rollback.is_a?(ActiveRecord::Rollback)
        end
      ensure
        @transaction_joinable = last_transaction_joinable

        if outside_transaction?
          @open_transactions = 0
        elsif transaction_open
          decrement_open_transactions
          begin
            if open_transactions == 0
              commit_db_transaction
              commit_transaction_records
            else
              release_savepoint
              save_point_records = @_current_transaction_records.pop
              unless save_point_records.blank?
                @_current_transaction_records.push([]) if @_current_transaction_records.empty?
                @_current_transaction_records.last.concat(save_point_records)
              end
            end
          rescue Exception => database_transaction_rollback
            if open_transactions == 0
              rollback_db_transaction
              rollback_transaction_records(true)
            else
              rollback_to_savepoint
              rollback_transaction_records(false)
            end
            raise
          end
        end
      end