【问题标题】:how do I perform transactions with ruby mysql2如何使用 ruby​​ mysql2 执行事务
【发布时间】:2012-03-06 12:17:12
【问题描述】:

我已经开始使用mysql2 gem。我试图弄清楚一些基本的事情——其中之一是如何显式地执行事务(对于批处理操作,比如多个 INSERT/UPDATE 查询)。

在旧的ruby-mysql 中,这是我的做法:

client  = Mysql.real_connect(...)
inserts = [
  "INSERT INTO ...",
  "UPDATE .. WHERE id=..",
  # etc
]

client.autocommit(false)
inserts.each do |ins|  
  begin
    client.query(ins)
  rescue
    # handle errors or abort entirely
  end
end
client.commit

我在文档中找不到太多内容 - mysql2 怎么能做到这一点?

【问题讨论】:

    标签: ruby transactions batch-processing mysql2


    【解决方案1】:

    这个问题让我很好奇,于是追查了Ruby on Rails是如何处理事务的,发现this code

    def begin_db_transaction
      execute "BEGIN"
    rescue Exception
      # Transactions aren't supported
    end
    
    def commit_db_transaction #:nodoc:
      execute "COMMIT"
    rescue Exception
      # Transactions aren't supported
    end
    
    def rollback_db_transaction #:nodoc:
      execute "ROLLBACK"
    rescue Exception
      # Transactions aren't supported
    end
    

    您是否尝试过在其他语句周围执行begincommit 语句?

    client.query('begin')
    
    inserts.each do |ins|  
      begin
        client.query(ins)
      rescue
        client.query('rollback')
        return
      end
    end
    
    client.query('commit')
    

    【讨论】:

      【解决方案2】:

      我刚刚做了一个实现:

      class DBConnector
        def transaction(&block)
          raise ArgumentError, "No block was given" unless block_given?
          begin
            client.query("BEGIN")
            yield
            client.query("COMMIT")
          rescue
            client.query("ROLLBACK")
          end
        end
      end
      

      所以你可以这样使用:

      DBConnector.transaction do
        # your db queries here
      end
      

      【讨论】:

        【解决方案3】:

        使用 Bruno 的模板,然后添加交易状态指示器:

        def transaction(&block)
            raise ArgumentError, "No block was given" unless block_given?
            begin
              raw_query("BEGIN")
              yield
              raw_query("COMMIT")
              return true # Successful Transaction
            rescue
              raw_query("ROLLBACK")
              return false # Failed Transaction
            end
        end
        

        与#transaction交互:

        def run_queries(queries)
            raise ArgumentError, "Invalid Queries Argument: #{queries}" unless queries.respond_to?(:each)
            success = transaction do
                queries.each do |q|
                    raw_query(q)
                end
            end
            raise RuntimeError, "Transaction Failed for Queries: #{queries}" unless success
        end
        

        【讨论】:

          猜你喜欢
          • 2014-03-23
          • 2011-12-25
          • 1970-01-01
          • 2013-09-27
          • 1970-01-01
          • 1970-01-01
          • 2016-05-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多