Mariadb 从更新的表中更新引用字段是否会导致死锁?

Mariadb 从更新的表中更新引用字段是否会导致死锁?,mariadb,locking,deadlock,Mariadb,Locking,Deadlock,我有这样一个问题: wait_started wait_age wait_age_secs locked_table locked_index locked_type waiting_trx_id waiting_trx_started waiting_trx_age waiting_trx_rows_locked waiting_trx_rows_modified waiting_pid waiting_query

我有这样一个问题:

wait_started    wait_age        wait_age_secs   locked_table    locked_index    locked_type     waiting_trx_id  waiting_trx_started     waiting_trx_age waiting_trx_rows_locked waiting_trx_rows_modified       waiting_pid     waiting_query   waiting_lock_id waiting_lock_mode       blocking_trx_id blocking_pid    blocking_query  blocking_lock_id        blocking_lock_mode      blocking_trx_started    blocking_trx_age        blocking_trx_rows_locked        blocking_trx_rows_modified      sql_kill_blocking_query sql_kill_blocking_connection
2020-12-27 07:43:32     00:00:04        4       `db`.`loginlogs`   PRIMARY RECORD  37075679818     2020-12-27 07:43:32     00:00:04        1       0       19194139        UPDATE loginlogs SET  ... HERE logid = 64634225227638257       37075679818:921:15944673:61     X       37075617021     19191704        UPDATE loginlogs SET ... HERE logid = 64634225227638257       37075617021:921:15944673:61     X       2020-12-27 07:43:07     00:00:29        1       0       KILL QUERY 19191704     KILL 19191704
更新登录日志集rxbytes=rxbytes+,txbytes=txbytes+?其中logid=?

有时,my DB会陷入死锁,并且
SELECT*from sys.innodb_lock_waits
会显示如下挂起的锁:

wait_started    wait_age        wait_age_secs   locked_table    locked_index    locked_type     waiting_trx_id  waiting_trx_started     waiting_trx_age waiting_trx_rows_locked waiting_trx_rows_modified       waiting_pid     waiting_query   waiting_lock_id waiting_lock_mode       blocking_trx_id blocking_pid    blocking_query  blocking_lock_id        blocking_lock_mode      blocking_trx_started    blocking_trx_age        blocking_trx_rows_locked        blocking_trx_rows_modified      sql_kill_blocking_query sql_kill_blocking_connection
2020-12-27 07:43:32     00:00:04        4       `db`.`loginlogs`   PRIMARY RECORD  37075679818     2020-12-27 07:43:32     00:00:04        1       0       19194139        UPDATE loginlogs SET  ... HERE logid = 64634225227638257       37075679818:921:15944673:61     X       37075617021     19191704        UPDATE loginlogs SET ... HERE logid = 64634225227638257       37075617021:921:15944673:61     X       2020-12-27 07:43:07     00:00:29        1       0       KILL QUERY 19191704     KILL 19191704
如您所见,两个相同的查询似乎同时运行。第二个正在等待第一个完成

我认为MySQL应该处理像这样的简单更新查询。我是否需要先选择字节,然后在不引用新值中的
rxbytes
txbytes
的情况下进行更新

顺便说一句,这是在从MariaDB 10.4.2更新到10.4.17之后发生的,因此我也怀疑MariaDB有错误,我打开了一个。

锁等待不是死锁! 我经常看到这种误解

您显示的是一个锁等待。也就是说,一个事务正在等待另一个事务。每次更新都会锁定它检查的行,任何并发更新都必须等待第一次提交才能释放这些行锁。那是锁等等。这很正常,很普通

僵局是不同的。这是两个事务进入相互锁等待的地方。UPDATE1锁定一些行,但尚未提交。然后UPDATE2尝试更新相同的行,并开始等待。然后,UPDATE1事务尝试另一个锁定语句,该语句需要锁定UPDATE2事务已经持有的某些行,可能来自它运行的前一个语句。因此,两个事务都在等待另一个事务,并且不会承诺释放它们所持有的锁,因为它们正在等待。死锁之所以这样命名是因为无法解决相互等待

说:

死锁是一种不同事务无法继续进行的情况,因为每个事务都持有另一个事务所需的锁。因为两个事务都在等待资源可用,所以它们都不会释放它所持有的锁

您不会经历真正的死锁带来的延迟。MySQL监视这些循环锁等待,并强制其中一个回滚其事务。这几乎是瞬间发生的,因此几乎不需要等待

那么,当您从10.4.2升级到10.4.17时,为什么会发生这种情况呢。显然,某些更改会影响锁定的行数或事务的持续时间,从而使并发事务更有可能以这种方式发生冲突

或者,该软件没有改变任何与锁定或事务相关的内容,但巧合的是,当您升级到新版本的MariaDB时,是您的流量发生了变化。

锁定等待不是死锁! 我经常看到这种误解

您显示的是一个锁等待。也就是说,一个事务正在等待另一个事务。每次更新都会锁定它检查的行,任何并发更新都必须等待第一次提交才能释放这些行锁。那是锁等等。这很正常,很普通

僵局是不同的。这是两个事务进入相互锁等待的地方。UPDATE1锁定一些行,但尚未提交。然后UPDATE2尝试更新相同的行,并开始等待。然后,UPDATE1事务尝试另一个锁定语句,该语句需要锁定UPDATE2事务已经持有的某些行,可能来自它运行的前一个语句。因此,两个事务都在等待另一个事务,并且不会承诺释放它们所持有的锁,因为它们正在等待。死锁之所以这样命名是因为无法解决相互等待

说:

死锁是一种不同事务无法继续进行的情况,因为每个事务都持有另一个事务所需的锁。因为两个事务都在等待资源可用,所以它们都不会释放它所持有的锁

您不会经历真正的死锁带来的延迟。MySQL监视这些循环锁等待,并强制其中一个回滚其事务。这几乎是瞬间发生的,因此几乎不需要等待

那么,当您从10.4.2升级到10.4.17时,为什么会发生这种情况呢。显然,某些更改会影响锁定的行数或事务的持续时间,从而使并发事务更有可能以这种方式发生冲突


或者,软件没有改变与锁定或事务相关的任何内容,但在您升级到新版本的MariaDB时,恰好是您的流量发生了变化。

您执行此更新的事务需要尽可能短(如果您希望避免死锁)。这里没有给出这种背景。我可以假设您在一个长事务中执行此更新吗?@luk此更新是事务中唯一的查询。我只是有多个地方从不同的服务器调用这个更新查询。有时,我会遇到一个死锁,日志中显示一个更新正在等待另一个具有相同logid的更新完成(因为这个原始更新持有X锁)。不知道如何找到原始更新正在等待的内容。多个更新具有相同的logid是否正确?(这似乎很奇怪)@Luuk No,logid是主键,如果有两个语句具有相同的logid,那么获取/确定logid时会出错。如果您正在获取(最后一个)logid,并且一段时间后另一个进程也在获取(最后一个)logid,则它们不应(=永远)获取相同的logid。您执行此更新的事务需要尽可能短(如果您希望避免死锁)。这里没有给出这种背景。我可以假设您在一个长事务中执行此更新吗?@luk此更新是事务中唯一的查询。我只是有多个地方从不同的服务器调用这个更新查询。有时,我会遇到一个死锁,日志显示