• 读/写死锁


    我喜欢写死锁这个话题,因为在你写代码的时候,如果不考虑仔细,会有太多不同的方法和情况造成死锁。在今天的文章里,我想向你展示下,从同个表,用不同的顺序来读写记录时,会发生死锁的情况。

    读/写死锁

    下列代码展示了简单的表定义,这里我也插入2条记录。 

    -- Create a new table
    CREATE TABLE Foo
    (
        Col1 INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
        Col2 INT,
        Col3 INT
    )
    GO
    
    -- Insert 2 records
    INSERT INTO Foo VALUES (1, 1), (2, 2)
    GO
    
    SELECT * FROM Foo
    GO

    现在假设下列情况:你有2个查询,用来读写访问记录,但你用不同的顺序访问记录。第1个事务进行下列操作

    • UPDATE第1条记录
    • SELECT第2条记录

    第2个事务用相反的顺序访问同样的记录:

    • UPDATE第2条记录
    • SELECT第1条记录

    下列代码展示了这2个事务:

    -- UPDATE 1st record
    -- SELECT 2nd record
    BEGIN TRANSACTION
    
    UPDATE Foo SET Col3 = 3
    WHERE Col1 = 1
    
    SELECT * FROM Foo
    WHERE Col1 = 2
    
    ROLLBACK
    GO
    
    -- UPDATE 2nd record
    -- SELECT 1st record
    BEGIN TRANSACTION
    
    UPDATE Foo SET Col3 = 3
    WHERE Col1 = 2
    
    SELECT * FROM Foo
    WHERE Col1 = 1
    
    ROLLBACK
    GO

    如果时机合适的话,这里很容易触发死锁。因为2个事务都要在第1条和第2条记录上获得排它锁(X),然后他们不能在另一条记录上获得共享锁(S)——死锁发生!

    你如何解决这个死锁呢?有很多方法:

    • 在你整个事务里按同样的顺序访问记录(第1条,然后第2条)
    • 在事务外进行SELECT语句
    • 在SELECT语句期间,启用提交读快照隔离级别( Read Committed Snapshot Isolation )来避免共享锁

    小结

    在今天的文章里,我向你展示了,SQL Server里,当你在一个表,在不同的顺序访问的事务里,是很容易触发死锁的。当你写你的查询时,你必须要认真考虑,按实际情况实现你的查询。经常有其他人可以阻塞你。

    原文链接:

    https://www.sqlpassion.at/archive/2016/12/19/writeread-deadlocks 

  • 相关阅读:
    输出 n 层的三角形,倒三角和叠在一起的沙漏
    求构成给定自然数的平方数的最小个数
    求一正整数约数的个数
    第一个符合要求的元素
    树枝节点之和是否等于给定值
    安装gcc
    杭电1004 ac code
    rabbitmq 笔记
    国行 lg g3 D858 刷 lg g3 D858hk 教程(备忘)
    MySQL存储过程错误No data
  • 原文地址:https://www.cnblogs.com/woodytu/p/6202539.html
Copyright © 2020-2023  润新知