Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Commit

Permalink
RDS uses a different query for killing transactions.
Browse files Browse the repository at this point in the history
  • Loading branch information
Phan Le and Ryan Tang committed May 3, 2013
1 parent 397e78b commit bfdcfa9
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 9 deletions.
23 changes: 15 additions & 8 deletions ng/mysql/lib/mysql_service/node.rb
Expand Up @@ -9,6 +9,7 @@
require "open3"
require "thread"


module VCAP
module Services
module Mysql
Expand All @@ -27,6 +28,7 @@ class WardenProvisionedService < VCAP::Services::Base::Warden::Service
require "mysql_service/util"
require "mysql_service/storage_quota"
require "mysql_service/mysql_error"
require "mysql_service/transaction_killer"

class VCAP::Services::Mysql::Node

Expand Down Expand Up @@ -85,6 +87,7 @@ def initialize(options)
Mysql2::Client.logger = @logger
@supported_versions = options[:supported_versions]
mysqlProvisionedService.init(options)
@transaction_killer = VCAP::Services::Mysql::TransactionKiller.build(options[:mysql_provider])
end

def service_instances
Expand Down Expand Up @@ -248,21 +251,25 @@ def kill_long_queries
def kill_long_transaction
acquired = @kill_long_transaction_lock.try_lock
return unless acquired
query_str = "SELECT * from ("+
" SELECT trx_started, id, user, db, trx_query, TIME_TO_SEC(TIMEDIFF(NOW() , trx_started )) as active_time" +
" FROM information_schema.INNODB_TRX t inner join information_schema.PROCESSLIST p " +
" ON t.trx_mysql_thread_id = p.ID " +
" WHERE trx_state='RUNNING' and user!='root' " +
") as inner_table " +
"WHERE inner_table.active_time > #{@max_long_tx}"

query_str = <<-QUERY
SELECT * from (
SELECT trx_started, id, user, db, trx_query, TIME_TO_SEC(TIMEDIFF(NOW() , trx_started )) as active_time
FROM information_schema.INNODB_TRX t inner join information_schema.PROCESSLIST p
ON t.trx_mysql_thread_id = p.ID
WHERE trx_state='RUNNING' and user!='root'
) as inner_table
WHERE inner_table.active_time > #{@max_long_tx}
QUERY

each_connection_with_key do |connection, key|
result = connection.query(query_str)
current_long_tx_ids = []
@long_tx_ids[key] = [] if @long_tx_ids[key].nil?
result.each do |trx|
trx_started, id, user, db, trx_query, active_time = %w(trx_started id user db trx_query active_time).map { |o| trx[o] }
if @kill_long_tx
connection.query("KILL #{id}")
@transaction_killer.kill(id, connection)
@logger.warn("Kill long transaction: user:#{user} db:#{db} thread:#{id} trx_query:#{trx_query} active_time:#{active_time}")
@long_tx_killed += 1
else
Expand Down
7 changes: 7 additions & 0 deletions ng/mysql/lib/mysql_service/rds/transaction_killer.rb
@@ -0,0 +1,7 @@
module VCAP::Services::Mysql::RDS
class TransactionKiller
def kill(thread_id, connection)
connection.query("CALL rds.kill(#{thread_id})")
end
end
end
7 changes: 7 additions & 0 deletions ng/mysql/lib/mysql_service/standard/transaction_killer.rb
@@ -0,0 +1,7 @@
module VCAP::Services::Mysql::Standard
class TransactionKiller
def kill(id, connection)
connection.query("KILL #{id}")
end
end
end
14 changes: 14 additions & 0 deletions ng/mysql/lib/mysql_service/transaction_killer.rb
@@ -0,0 +1,14 @@
require_relative 'rds/transaction_killer'
require_relative 'standard/transaction_killer'

module VCAP::Services::Mysql
class TransactionKiller
def self.build(provider)
if provider == "rds"
RDS::TransactionKiller.new
else
Standard::TransactionKiller.new
end
end
end
end
2 changes: 1 addition & 1 deletion ng/mysql/spec/mysql_node_spec.rb
Expand Up @@ -60,13 +60,13 @@ class MysqlError
@default_plan = "free"
@default_version = @opts[:default_version]
@default_opts = "default"
@tmpfiles = []

# Setup code must be wrapped in EM.run
EM.run do
@node = VCAP::Services::Mysql::Node.new(@opts)
EM.add_timer(1) { EM.stop }
end
@tmpfiles = []
end

before :each do
Expand Down
12 changes: 12 additions & 0 deletions ng/mysql/spec/mysql_service/rds/transaction_killer_spec.rb
@@ -0,0 +1,12 @@
require 'spec_helper'
require 'mysql_service/rds/transaction_killer'

describe VCAP::Services::Mysql::RDS::TransactionKiller do
describe "killing transaction" do
it "should use the connection to kill" do
connection = stub
connection.should_receive(:query).with('CALL rds.kill(1)')
subject.kill(1, connection)
end
end
end
12 changes: 12 additions & 0 deletions ng/mysql/spec/mysql_service/standard/transaction_killer_spec.rb
@@ -0,0 +1,12 @@
require 'spec_helper'
require 'mysql_service/standard/transaction_killer'

describe VCAP::Services::Mysql::Standard::TransactionKiller do
describe "killing transaction" do
it "should use the connection to kill" do
connection = stub
connection.should_receive(:query).with('KILL 1')
subject.kill(1, connection)
end
end
end
18 changes: 18 additions & 0 deletions ng/mysql/spec/mysql_service/transaction_killer_spec.rb
@@ -0,0 +1,18 @@
require 'spec_helper'
require 'mysql_service/transaction_killer'

describe VCAP::Services::Mysql::TransactionKiller do
context "provider is RDS" do
it "returns a rds killer" do
described_class.build('rds').
should be_a(VCAP::Services::Mysql::RDS::TransactionKiller)
end
end

context "provider is not specified" do
it "returns the standard killer" do
described_class.build(nil).
should be_a(VCAP::Services::Mysql::Standard::TransactionKiller)
end
end
end

0 comments on commit bfdcfa9

Please sign in to comment.