Replies: 2 comments 12 replies
-
BTW: if test above code without use transaction, instead, i just use https://gist.github.com/56c95fa75d22a6d134730485a0b0f08a anyway, i switch from database_cleaner to use Thank you. |
Beta Was this translation helpful? Give feedback.
-
When you create a new thread, database queries inside it will use a new database connection. Since the database connection assigned to the main thread hasn't yet committed the insertion of the insider record (that happens at the end of the The Active Record example works, because Active Record uses a single shared connection in tests, which is used by all threads (including the web server thread running in the background during system tests). To prevent race conditions in situations where two threads try to use the connection at the same time, Active Record internally adds mutex locking around any code that uses the connection. With Sequel you could use the single-threaded connection pool, but then you'd have to ensure that two threads don't access the shared connection at the same time. When I make the changes below to your example, it completes successfully. FWIW, there is some more discussion regarding this use case in this thread. changesdiff --git a/test.rb b/test.rb
index 6c457da..3c4e3dc 100644
--- a/test.rb
+++ b/test.rb
@@ -15,11 +15,10 @@ gemfile(true) do
gem 'minitest-hooks'
end
-system("sudo -u postgres dropdb --if-exists check_sequel_db")
-system("sudo -u postgres createdb check_sequel_db")
+system("dropdb --if-exists check_sequel_db")
+system("createdb check_sequel_db")
-DB_URL="postgres://postgres:postgres@localhost:5432/check_sequel_db"
-DB = Sequel.connect(DB_URL)
+DB = Sequel.postgres("check_sequel_db", single_threaded: true)
DB.create_table(:insiders, :ignore_index_errors=>true) do
primary_key :id
@@ -52,23 +51,28 @@ DB.loggers << LOGGER
describe 'insider' do
it 'test postgres read committed mode default lock' do
Insider.create(number_of_shares: 200)
+ mutex = Mutex.new
puts "Insider count outer thread: #{Insider.count}"
thread1 = Thread.new do
sleep rand(0.1..0.2)
- DB.transaction do
- puts "Insider count inner first thread: #{Insider.count}"
- insider_1 = Insider.last
- insider_1.update(number_of_shares: insider_1.number_of_shares - 10)
+ mutex.synchronize do
+ DB.transaction do
+ puts "Insider count inner first thread: #{Insider.count}"
+ insider_1 = Insider.last
+ insider_1.update(number_of_shares: insider_1.number_of_shares - 10)
+ end
end
end
thread2 = Thread.new do
sleep rand(0.1..0.2)
- DB.transaction do
- insider_2 = Insider.last
- insider_2.update(number_of_shares: insider_2.number_of_shares - 10)
+ mutex.synchronize do
+ DB.transaction do
+ insider_2 = Insider.last
+ insider_2.update(number_of_shares: insider_2.number_of_shares - 10)
+ end
end
end |
Beta Was this translation helpful? Give feedback.
-
I consider this is not a issue, so create discuss here.
I want to test following feature works with Sequel.
https://www.postgresql.org/docs/11/transaction-iso.html#XACT-READ-COMMITTED
Following one file runner is a attempt, but get raise error.
https://gist.github.com/4bacc4500f25cd2723c024d03d5faef6
Following is error output.
As you can see, i even can't saw the created Insider object in the new created thread, because transaction? i guess.
What i want is just want to ensure the same effect as following test which run on ActiveRecord 6 is works on Sequel too.
above test works on rails 6.1, and run in a transaction too, because i can check this use
self.use_transactional_tests?
method like this:So, following is my question:
Thank you.
Beta Was this translation helpful? Give feedback.
All reactions