zoukankan      html  css  js  c++  java
  • Transaction And Lock--唯一索引下INSERT导致的死锁

    背景:

    曾经的一位同事问我:"数据库只有并发INSERT 操作,会造成死锁么?",我没有太多思考地回答"不会",但真的不会吗?

    测试:

    --=================================
    --创建测试表
    CREATE TABLE TB3
    (
        ID INT PRIMARY KEY
    )
    GO
    --===================================
    --新开回话1
    BEGIN TRAN 
    INSERT INTO TB3
    SELECT 2
    WAITFOR DELAY '0:0:10'
    INSERT INTO TB3
    SELECT 1
    --===================================
    --新开回话2
    BEGIN TRAN 
    INSERT INTO TB3
    SELECT 1
    
    WAITFOR DELAY '0:0:10'
    INSERT INTO TB3
    SELECT 2

    在上面的两个回话中,由于主键(唯一约束)的限制,相同的key对应相同的lock Resource,导致需要等待对方所获取的lock Resource,从而引发死锁

    而如果将主键修改为非唯一索引,则不会引发死锁,相同的key对应不相同的lock Resource,因此不会造成相互等待也不引发死锁。

    --====================================================================

    --华丽的PS

    对于最常见的死锁场景:

    事务1 获取表TB1上的资源,请求表TB2上的资源

    事务2 获取表TB2上的资源,请求表TB1上的资源

    很多开发人员都会有意识保证各个事务访问不同表的顺序,从而避免此类死锁的发生,但很少会考虑对相同表的访问顺序,尤其在输入值被参数化的情况,如在下面的情况下:

    BEGIN TRAN
    UPDATE TB1
    SET C2=@P2
    WHERE C1=@P1
    
    UPDATE TB1
    SET C2=@P3
    WHERE C1=@P3

    COMMIT

    在考虑是否会引发死锁时,我们除了分析当前语句外,还得检查这些语句所涉及到的表相关对象:触发器+外键+索引,还需分析其他业务场景的潜在影响。

    PS:很多我们自认为正确的小结论,洗洗(细细)分析下,根本就是错误,而这些西奥结论,可能造成很恶劣影响。

    --========================================================

    照例妹子镇贴

    图片来源于一豆瓣友邻

  • 相关阅读:
    dp P1103 书本整理 洛谷
    dp 洛谷P1977 出租车拼车 线性dp
    Layui 在新标签中打开页面 / 模拟点击菜单
    布局 基础知识
    SpreadJS 生成报表
    ABP abp zreo 老版本 支持dotnet framework 4.0
    IIS 加载字体
    IIS 登录失败 该登陆名来自不受信任的域,不能与windows身份认证一起使用
    C# WebForm 打开默认页
    IIS 报错 Cannot open database "test4" requested by the login. The login failed. Login failed for user 'IIS APPPOOL est1'.
  • 原文地址:https://www.cnblogs.com/TeyGao/p/3582487.html
Copyright © 2011-2022 走看看