Mysql2:: 오류: 잠금을 시도할 때 교착 상태가 발견되었습니다. 트랜잭션을 다시 시작해 보십시오(Ruby on Rails).
Ruby on Rails 애플리케이션에 문제가 있습니다.그래서, 다른 토끼를 듣고 있는 노동자들이 있습니다.MQ 주제.각 작업자는 DB(mariaDB) 테이블을 약간 변경하고 공통 개체 '장치'의 업데이트 종료 'last_connection' 필드에서 문제가 발생합니다.
이 직원은 한 명입니다.
include Sneakers::Worker
# This worker will connect to "queue" queue
# env is set to nil since by default the actuall queue name would be
# "queue_development"
from_queue "sensor_log"
# work method receives message payload in raw format
def work(raw_message)
logger.info ("sensor_log " + raw_message)
msg = JSON.parse(raw_message)
# msg = {"deviceId" => 102,"timestamp" => 1487318555,"sensor" => 5, "values" => [1,2,3,4,5,6,7,8], "isNewSensor" => false, "logDelayed" => false}
begin
@device = Device.find(msg["deviceId"])
ActiveRecord::Base.transaction do
# Initialize
timestamp = Time.at(msg["timestamp"])
MiddlewareLog.create(
device_id: msg["deviceId"],
message: JSON.pretty_generate(msg),
queue: MiddlewareLog.queues[:sensor_log]
)
if(msg["ext_brd_type"] == 6)
logger.info ("Logging external sensors lm2, lm4, lm4")
# Logging external sensors lm2, lm4, lm4
Sensors::SENSORS_EXT.map do |code|
SensorLog.create(
device_id: msg["deviceId"],
sensor: code,
state: msg[code],
value: msg[code],
is_delayed: msg["logDelayed"],
created_at: timestamp
)
end
else
logger.info ("Logging native sensors")
# Logging native
device_sensors = @device.new_version? ? Sensors::SENSORS_CODES_NEW : Sensors::SENSORS_CODES
@sensors = device_sensors.reject{|code, sensor| code & msg["sensor"] == 0}
@sensors.map do |code, sensor|
SensorLog.create(
device_id: msg["deviceId"],
sensor: sensor[:name],
state: sensor[:state],
value: msg["values"][sensor[:bit_position]],
is_delayed: msg["logDelayed"],
created_at: timestamp
)
end
Rollbar.warning("Unknown device sensor", :message => msg, :sensor => msg["sensor"]) if @sensors.empty?
@device.update_sensors_state(msg["values"]) if @sensors.any?
end
# Avoid updated_at deadlock
@device.save!(touch: false)
end
# Touch updated_at and last_connection_at
@device.touch(:last_connection_at)
ack! # we need to let queue know that message was received
rescue => exception
logger.error ("sensors_log exception:")
logger.error exception
Rollbar.error(exception, :message => msg)
requeue!
end
end
end
두 번째는 다음과 같습니다.
class SystemLogsWorker
include Sneakers::Worker
# This worker will connect to "queue" queue
# env is set to nil since by default the actuall queue name would be
# "queue_development"
from_queue "system_log"
# @logger = Logger.new(STDOUT)
# @logger.level = Logger::INFO
# work method receives message payload in raw format
def work(raw_message)
# @logger.info raw_message
logger.info ("system_log " + raw_message)
msg = JSON.parse(raw_message)
# msg = {"deviceId":102,"timestamp":1487318555,"system":2069,"logDelayed":false,"fault_code":1}
begin
@device = Device.find(msg["deviceId"])
ActiveRecord::Base.transaction do
# Initialize
timestamp = Time.at(msg["timestamp"])
MiddlewareLog.create(
device_id: msg["deviceId"],
message: JSON.pretty_generate(msg),
queue: MiddlewareLog.queues[:system_log]
)
@system = Systems::EVENTS_CODES[msg["system"]]
# @logger.warn("Unknown device system", :message => msg, :system => msg[:system]) unless @system
# logger.warn("Unknown device system", :message => msg, :system => msg["system"]) unless @system
# Rollbar.warning("Unknown device system", :message => msg, :system => msg["system"]) unless @system
logger.warn("Unknown device system. Message:" + raw_message) unless @system
Rollbar.warning("Unknown device system. Message:" + raw_message) unless @system
# Loggin
system_log = SystemLog.create(
device_id: msg["deviceId"],
system: @system[:name],
state: @system[:state],
is_delayed: msg["logDelayed"],
fault_code: msg["fault_code"],
created_at: timestamp
) if @system
@device.update_systems_state(system_log) if @system
# Avoid updated_at deadlock
@device.save!(touch: false)
end
# Touch updated_at and last_connection_at
@device.touch(:last_connection_at)
ack! # we need to let queue know that message was received
rescue => exception
logger.error ("system_log exception:")
logger.error exception
Rollbar.error(exception, :message => msg)
requeue!
end
end
end
런타임에 다음 메시지가 나타납니다.
2020-06-18T11:09:08Z p-13299 t-gmvtsrzac ERROR : sensors_log 예외 : 2020-06-18T11:09:08Z p-13299 t-gmvtsrzac ERROR : Mysql2 ::오류:잠금을 시도할 때 교착 상태가 발견되었습니다. 트랜잭션을 다시 시작해 보십시오.
devices
세트devices
.updated_at
= '2020-06-18 11:09:08',devices
.last_connection_at
= '2020-06-18 11:09:08' WHEREdevices
.id
= 30242020-06-18T11:09:08Z p-13299 t-gmvtsq74w 오류: system_log 예외: 2020-06-18T11:09:08Z p-13299 t-gmvtsq74w 오류: Mysql2::오류:잠금을 시도할 때 교착 상태가 발견되었습니다. 트랜잭션을 다시 시작해 보십시오.
devices
세트devices
.updated_at
= '2020-06-18 11:09:08',devices
.last_connection_at
= '2020-06-18 11:09:08' WHEREdevices
.id
= 3024
제 생각에 문제는.@device.touch(:last_connection_at)
, 한 번에 두 작업자 모두 테이블 행 하나를 업데이트하려고 하기 때문입니다.저는 루비를 잘 못해서 어떤 도움이라도 주시면 감사하겠습니다.
데이터베이스 데이터를 업데이트하기 전에 트랜잭션 내에서 잠금을 사용해 본 적이 있습니까?
@device.lock!
@device.save!(touch: false)
@device.touch(:last_connection_at)
with_lock:을 사용하여 잠금과 트랜잭션을 동시에 시작할 수도 있습니다.
@device = Device.find(msg["deviceId"])
@device.with_lock do
# your block here
end
https://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html 에 설명된 바와 같이
언급URL : https://stackoverflow.com/questions/62449458/mysql2error-deadlock-found-when-trying-to-get-lock-try-restarting-transactio
'bestsource' 카테고리의 다른 글
숫자(0-9)와 NO 문자만 사용할 수 있는 정규식 (0) | 2023.09.06 |
---|---|
스프링 MVC - 스프링 보안을 통해 사용자가 이미 로그인되어 있는지 확인? (0) | 2023.09.06 |
E: 'mysql-client' 패키지에 도커 구성을 사용하는 php-fpm 이미지 빌드에 설치 후보가 없습니다. (0) | 2023.09.06 |
스프링 세션 범위 콩(컨트롤러) 및 서비스에 대한 언급, 직렬화 측면 (0) | 2023.09.06 |
스프링 또는 EJB3 또는 이들 모두를 함께 사용하는 것이 언제 필요하거나 편리합니까? (0) | 2023.09.06 |