Sha256: e62f153197954f30127639f72639267c3a0b10e0c18a4404daa26716be519d8c

Contents?: true

Size: 1.95 KB

Versions: 1

Compression:

Stored size: 1.95 KB

Contents

#
#  Copyright (c) 2011, SoundCloud Ltd., Rany Keddo, Tobias Bielohlawek, Tobias
#  Schmidt
#
#  Switches origin with destination table with a write lock. Use this as a safe
#  alternative to rename, which can cause slave inconsistencies:
#
#    http://bugs.mysql.com/bug.php?id=39675
#
#  LockedSwitcher adopts the Facebook strategy, with the following caveat:
#
#    "Since alter table causes an implicit commit in innodb, innodb locks get
#    released after the first alter table. So any transaction that sneaks in
#    after the first alter table and before the second alter table gets
#    a 'table not found' error. The second alter table is expected to be very
#    fast though because copytable is not visible to other transactions and so
#    there is no need to wait."
#

require 'lhm/command'
require 'lhm/migration'

module Lhm
  class LockedSwitcher
    include Command

    def initialize(migration, connection = nil)
      @migration = migration
      @connection = connection
      @origin = migration.origin
      @destination = migration.destination
    end

    def statements
      uncommitted { switch }
    end

    def switch
      [
        "lock table `#{ @origin.name }` write, `#{ @destination.name }` write",
        "alter table `#{ @origin.name }` rename `#{ @migration.archive_name }`",
        "alter table `#{ @destination.name }` rename `#{ @origin.name }`",
        "commit",
        "unlock tables"
      ]
    end

    def uncommitted(&block)
      [
        "set @lhm_auto_commit = @@session.autocommit",
        "set session autocommit = 0",
        *yield,
        "set session autocommit = @lhm_auto_commit"
      ]
    end

    #
    # Command interface
    #

    def validate
      unless table?(@origin.name) && table?(@destination.name)
        error "`#{ @origin.name }` and `#{ @destination.name }` must exist"
      end
    end

    def revert
      sql "unlock tables"
    end

  private

    def execute
      sql statements
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
lhm-1.0.0.rc.1 lib/lhm/locked_switcher.rb