1
xlzyxxn 335 天前
sql_safe_updates 设置为 1 ,不用 duplicate key update 还会出现吗
|
2
shidakang0 335 天前
死锁通常在多个事务同时尝试以不兼容的方式锁定资源时发生。在您提供的信息中,两个事务都尝试对同一资源进行替换操作,这涉及到删除旧记录和插入新记录的过程。由于 REPLACE INTO 实质上是一个删除后跟着一个插入的操作组合,两个事务都试图获取同样的锁,从而导致死锁。
在 REPEATABLE-READ 隔离级别下,InnoDB 存储引擎为表中的索引记录保持行锁,直到事务结束。这意味着一旦事务获得了某个记录的锁,它将在事务结束前保持该锁定状态。如果另一个事务尝试执行与已锁定的记录相关的操作,则该事务将进入等待状态,直到第一个事务完成。如果两个事务互相等待对方释放锁,就会发生死锁。 在您的案例中,两个事务都在尝试执行 REPLACE INTO 操作,并且因为涉及到删除操作,它们都需要 X (排他锁)。第一个事务等待释放因为第二个事务持有的旧记录的锁,而第二个事务等待释放第一个事务尝试插入的新记录相同位置的锁。这就是为什么发生死锁的原因。 当改用 INSERT ... ON DUPLICATE KEY UPDATE 时,如果尝试插入的记录的唯一键已经存在,则不会删除旧记录,而是更新它。这意味着只需要一次索引记录的锁,减少了锁的复杂性和冲突的可能性,因此不再出现死锁错误。 为了避免死锁,可以考虑以下策略: 重新考虑索引策略,确保索引尽可能高效,这样可以降低锁定的需求。 尽可能减少事务大小,执行更多的小事务而不是少数几个大事务。 对于可能会导致死锁的操作,可以使用排他锁( SELECT ... FOR UPDATE ),或者在应用逻辑中实现重试机制。 确保应用程序中的事务按照相同的顺序访问数据库对象,以减少锁冲突的可能性。 |
3
alexfarm 321 天前
@shidakang0 大佬你好,能麻烦看下我的一个帖子吗,是关于 ON DUPLICATE KEY UPDATE 引发的死锁问题,https://cn.v2ex.com/t/1008054
|