1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #28726 from matthewd/transaction-locking

Add comprehensive locking around DB transactions
This commit is contained in:
Matthew Draper 2017-04-13 05:37:38 +09:30 committed by GitHub
commit 92ba89dbcc
3 changed files with 70 additions and 52 deletions

View file

@ -149,6 +149,7 @@ module ActiveRecord
end
def begin_transaction(options = {})
@connection.lock.synchronize do
run_commit_callbacks = !current_transaction.joinable?
transaction =
if @stack.empty?
@ -161,8 +162,10 @@ module ActiveRecord
@stack.push(transaction)
transaction
end
end
def commit_transaction
@connection.lock.synchronize do
transaction = @stack.last
begin
@ -174,14 +177,19 @@ module ActiveRecord
transaction.commit
transaction.commit_records
end
end
def rollback_transaction(transaction = nil)
@connection.lock.synchronize do
transaction ||= @stack.pop
transaction.rollback
transaction.rollback_records
end
end
def within_new_transaction(options = {})
@connection.lock.synchronize do
begin
transaction = begin_transaction options
yield
rescue Exception => error
@ -204,6 +212,8 @@ module ActiveRecord
end
end
end
end
end
def open_transactions
@stack.size

View file

@ -74,7 +74,7 @@ module ActiveRecord
SIMPLE_INT = /\A\d+\z/
attr_accessor :visitor, :pool
attr_reader :schema_cache, :owner, :logger, :prepared_statements
attr_reader :schema_cache, :owner, :logger, :prepared_statements, :lock
alias :in_use? :owner
def self.type_cast_config_to_integer(config)

View file

@ -239,7 +239,9 @@ module ActiveRecord
# Is this connection alive and ready for queries?
def active?
@lock.synchronize do
@connection.query "SELECT 1"
end
true
rescue PG::Error
false
@ -247,12 +249,15 @@ module ActiveRecord
# Close then reopen the connection.
def reconnect!
@lock.synchronize do
super
@connection.reset
configure_connection
end
end
def reset!
@lock.synchronize do
clear_cache!
reset_transaction
unless @connection.transaction_status == ::PG::PQTRANS_IDLE
@ -261,13 +266,16 @@ module ActiveRecord
@connection.query "DISCARD ALL"
configure_connection
end
end
# Disconnects from the database if already connected. Otherwise, this
# method does nothing.
def disconnect!
@lock.synchronize do
super
@connection.close rescue nil
end
end
def native_database_types #:nodoc:
NATIVE_DATABASE_TYPES