Skip to content

Instantly share code, notes, and snippets.

@rapimo
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rapimo/3c8c1b35270e5854c524 to your computer and use it in GitHub Desktop.
Save rapimo/3c8c1b35270e5854c524 to your computer and use it in GitHub Desktop.
postgres segfault
require 'active_record'
require 'parallel'
ActiveRecord::Base.establish_connection(adapter: 'postgresql', pool: 25, username: 'postgres', host: 'localhost', database: 'postgres')
ActiveRecord::Base.connection.execute "DROP DATABASE IF EXISTS segfault"
ActiveRecord::Base.connection.execute "CREATE DATABASE segfault"
ActiveRecord::Base.establish_connection(adapter: 'postgresql', pool: 25, username: 'postgres', host: 'localhost', database: 'segfault')
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE test_data(
tracker_id integer not null,
created_at timestamp,
processed boolean
);
SQL
(Date.new(2015,1,1) ..Date.new(2015,1,3)).each do |date|
s= Time.now
pref = date.to_s.gsub('-','_')
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE test_data_#{pref} (
CHECK ( date("created_at") = '#{date}')
)
INHERITS (test_data)
SQL
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO test_data_#{pref} (tracker_id, created_at, processed)
SELECT i%10000, '#{date}'::date + (i % 86400) * INTERVAL '1 s', false
FROM generate_series(1, 1e6::integer) i
SQL
ActiveRecord::Base.connection.execute <<-SQL
CREATE INDEX tracker_id_and_created_at#{pref} ON test_data_#{pref} (tracker_id, created_at)
SQL
puts "done #{date} in #{Time.now - s}"
end
puts "test starting waiting to segfault...."
tracker_up = 200
updates = (1..1e6).select{|i| i%10_00 == tracker_up}.map{|i| Date.new(2015,1,2) + (i%86400).seconds}
Parallel.each_with_index(updates, in_threads: 6) do |time, idx|
ActiveRecord::Base.connection_pool.with_connection do |con|
if idx == 0
con.execute <<-SQL
CREATE TEMPORARY TABLE outtbl ON COMMIT DROP AS
WITH affected AS (
UPDATE test_data t SET processed = true
WHERE tracker_id BETWEEN #{tracker_up - 100} AND #{tracker_up + 100}
AND NOT processed
RETURNING
date(t.created_at) as date, tracker_id, created_at
)
SELECT * FROM affected
SQL
end
con.execute <<-SQL
UPDATE test_data SET tracker_id = 400
WHERE tracker_id = #{tracker_up}
and created_at = '#{time}'
and date(created_at) = '#{time.to_date}'
SQL
end
end
@rapimo
Copy link
Author

rapimo commented Jan 15, 2015

run with

$ gem install activerecord
$ gem install pg
$ gem install parallel
$ ruby segfault.rb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment