gpt4 book ai didi

mysql - 运行多线程代码规范时锁定等待超时

转载 作者:行者123 更新时间:2023-11-29 17:24:34 24 4
gpt4 key购买 nike

我有以下类,它将许多线程中的所有用户名更改为 John

class Users::UpdateName
def call
User
.unscoped
.find_in_batches do |batch|
update_batch(batch)
end
end

def update_batch(users_batch)
users_batch
.each_slice(100)
.map { |users| Thread.new { update_all(users) } }
.each(&:join)
end

def update_all(users)
users.each { |u| u.update_columns(first_name: 'John') }
end
end

其中 User 类是具有默认范围的 Active Record 模型 default_scope { where(archived: false) }

我通过以下方式测试我的类(class):

describe Users::UpdateName

it 'should update first name of an archived user' do
user = User.create(first_name: 'Jane', archived: true)

Users::UpdateName.new.call

expect(user.reload.first_name).to eq 'John'
end

end

但是当我运行测试时它失败了

 ActiveRecord::StatementInvalid:
Mysql2::Error: Lock wait timeout exceeded; try restarting transaction: UPDATE `users` SET `users`.`first_name` = 'John' WHERE `users`.`id` = 10

当我使用 show engine innodb status; 检查数据库状态时,它给了我

TRANSACTIONS
------------
Trx id counter 4359880
Purge done for trx's n:o < 4359879 undo n:o < 0 state: running but idle
History list length 1034
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started
MySQL thread id 198, OS thread handle 0x700005048000, query id 43397 localhost root init
show engine innodb status
---TRANSACTION 4359879, ACTIVE 13 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 200, OS thread handle 0x700004f7c000, query id 43396 localhost root updating
UPDATE `users` SET `users`.`first_name` = 'John' WHERE `users`.`id` = 12
------- TRX HAS BEEN WAITING 13 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 173721 page no 3 n bits 72 index `PRIMARY` of table `mysql_lock_wait_timeout_problem_test`.`users` trx id 4359879 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 7; compact format; info bits 0
0: len 8; hex 800000000000000c; asc ;;
1: len 6; hex 0000004286c2; asc B ;;
2: len 7; hex d6000001510110; asc Q ;;
3: len 4; hex 4a616e65; asc Jane;;
4: len 1; hex 81; asc ;;
5: len 5; hex 99a034ac56; asc 4 V;;
6: len 5; hex 99a034ac56; asc 4 V;;

------------------
---TRANSACTION 4359874, ACTIVE 13 sec
2 lock struct(s), heap size 360, 1 row lock(s), undo log entries 1
MySQL thread id 199, OS thread handle 0x700004ef4000, query id 43393 localhost root
Trx read view will not see trx with id >= 4359879, sees < 4359879
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (read thread)
I/O thread 4 state: waiting for i/o request (read thread)
I/O thread 5 state: waiting for i/o request (read thread)
I/O thread 6 state: waiting for i/o request (write thread)
I/O thread 7 state: waiting for i/o request (write thread)
I/O thread 8 state: waiting for i/o request (write thread)
I/O thread 9 state: waiting for i/o request (write thread)
Pending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
1320 OS file reads, 89466 OS file writes, 79251 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.38 writes/s, 0.24 fsyncs/s
-------------------------------------

您知道为什么会发生上述锁定超时吗?

当我删除多线程代码时,规范通过:

  def update_batch(users_batch)
update_all(users_batch)
end

您可以在this gist中了解如何初始化应用程序以重现错误。 。您还可以找到所有源代码 in Github

最佳答案

我能够使用更简单的代码重现此错误:

ActiveRecord::Base.transaction do
user = User.create! first_name: 'Jane'

t = Thread.new do
user.update_columns first_name: 'John'
end

t.join
end

说明:

主线程在事务中创建一条记录,并将该记录标记为不可更新。与此同时,另一个线程尝试更新该记录并等待主事务。并且主事务无法完成,因为它正在等待另一个线程

where class User is an Active Record model with default scope default_scope { where(archived: false) }

用户类中的默认作用域在那里不起任何作用

关于mysql - 运行多线程代码规范时锁定等待超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51041492/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com