Skip to content

Problem with inserting large binary data. TinyTds::Error: Write to the server failed #360

Open
@DarkSideF

Description

@DarkSideF

Hello!

I have I problem with inserting large binary data (varbinary(max)).

When I trying insert large binary data to a table row I get errors TinyTds::Error: Write to the server failed and TinyTds::Error: Read from the server failed depending on the file size.

Its sample code. In this example I use repeating binary chars instead of real file content, but I get exactly same errors with genuine file content obtained through 0x#{::File.read(input_file.path)

def create_binary_ct(filename, content)
  client = TinyTds::Client.new(
    { :adapter=>"sqlserver", :host=>"host", :port=>4444,
      :database=>"dbname", :username=>"sa", :password=>"pwd",
      :mode=>:dblib, timeout: 20000}
  )
  new_id = SystemHelper.generate_uuid
  sql = <<~SQL
    INSERT INTO [dvsys_binaries] ([ID], [Type], [Data])
    VALUES (
      '#{new_id}',
      '#{/\.[^\.]*$/.match(filename)}',
      #{content}
    )
  SQL
  client.execute(sql).each { |e| puts e }
end


# This example will result in an error `TinyTds::Error: Write to the server failed`
create_binary_ct('example_filename.iso', "0x#{'ac'*99000000}")

# This example will result in an error `TinyTds::Error: Read from the server failed`
create_binary_ct('example_filename.iso', "0x#{'ac'*67000000}")

# This example works fine
create_binary_ct('example_filename.iso', "0x#{'ac'*66000000}")

Initially, I got this problem with ActiveRecord using gem activerecord-sqlserver-adapter
When I upload file less than 70 Megabytes it works perfect, but file with size about 90 megabytes raises error

module DVCore
  class Binary < ApplicationRecord
    self.table_name = 'dvsys_binaries'
    self.primary_key = 'ID'

    before_create :assign_id

    def self.create_binary(filename, content)
      DVCore::Binary.create!(
        Type: /\.[^\.]*$/.match(filename).to_s,
        Data: content
      )
    end

    protected

    def assign_id
      self.ID ||= SystemHelper.generate_uuid
    end
  end
end

DVCore::Binary.create_binary('example_larger_than_90mb.zip', ::File.read(tempfile.path))

This code will result in an error

ActiveRecord::StatementInvalid: TinyTds::Error: DBPROCESS is dead or not enabled: IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-sqlserver-adapter-5.0.5/lib/active_record/connection_adapters/sqlserver/database_statements.rb:278:in `execute'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-sqlserver-adapter-5.0.5/lib/active_record/connection_adapters/sqlserver/database_statements.rb:278:in `raw_connection_do'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-sqlserver-adapter-5.0.5/lib/active_record/connection_adapters/sqlserver/database_statements.rb:219:in `block in do_execute'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:589:in `block in log'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:583:in `log'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-sqlserver-adapter-5.0.5/lib/active_record/connection_adapters/sqlserver/database_statements.rb:219:in `do_execute'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-sqlserver-adapter-5.0.5/lib/active_record/connection_adapters/sqlserver/database_statements.rb:66:in `exec_rollback_db_transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:285:in `rollback_db_transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:17:in `rollback_db_transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract/transaction.rb:138:in `rollback'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract/transaction.rb:183:in `rollback_transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract/transaction.rb:192:in `rescue in within_new_transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract/transaction.rb:209:in `within_new_transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:232:in `transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/transactions.rb:211:in `transaction'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/transactions.rb:392:in `with_transaction_returning_status'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/transactions.rb:324:in `save!'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/suppressor.rb:45:in `save!'
	from /home/darksidef/.rvm/gems/ruby-2.4.0/gems/activerecord-5.0.2/lib/active_record/persistence.rb:51:in `create!'
	from /home/darksidef/SuperApp/app/models/dv_core/dv_core/binary.rb:9:in `create_binary'
	from (irb):3

Code of table definition from schema.rb

  create_table "dvsys_binaries", primary_key: "ID", id: :uuid, default: -> { "newsequentialid()" }, force: :cascade do |t|
    t.ss_timestamp "FullTextTimeStamp",                                 null: false
    t.nchar        "Type",              limit: 10,                      null: false
    t.binary       "Data",              limit: 2147483647, default: ""
    t.binary       "StreamData",        limit: 2147483647
    t.index ["FullTextTimeStamp"], name: "dvsys_binaries_fulltexttimestamp"
  end

  add_foreign_key "dvsys_files", "dvsys_binaries", column: "BinaryID", primary_key: "ID", name: "dvsys_files_fk_binaryid"

I already tried change some SQLServer congfigs like network packed size but it didn't help

App runned on Ubuntu using Rails 5.0.2, Ruby 2.4.0, TinyTDS version 1.1.0 and connected to SQLServer 2014 database
I tried update to Rails 5.1 and TinyTDS 1.3.0 but it does not help

Can you help me figure out how to fix this problem please?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions