📜  SQL 中的脏读

📅  最后修改于: 2021-09-09 11:41:06             🧑  作者: Mango

先决条件 – DBMS 中的计划类型、事务隔离级别
常见的并发问题主要有四种:脏读、丢失读、不可重复读和幻读。

脏读——
当允许事务读取已被另一个尚未提交的事务修改的行时,发生脏读。它主要是由于一次未提交的多个事务而发生的。

例子 –

表 –记录

ID Cus_Name Balance
1 S Adam 100
2 Zee Young 150

交易 –
从 S Adam 账户转账 10 到 Zee Young 账户:

Input:
BEGIN TRY
  BEGIN TRANSACTION
    UPDATE Table SET Balance = Balance - 10 WHERE ID=1;
    UPDATE Table SET Balance = Balance + 10 WHERE ID='C';
  COMMIT TRANSACTION
  PRINT 'Committed'
END TRY
BEGIN CATCH
  ROLLBACK TRANSACTION
  PRINT 'Not Committed'
END CATCH

Output:
Not committed 

通过执行上述查询,输出将是“未提交”,因为存在错误,没有 ID=C。所以那时如果我们想用该行执行另一个事务,那么就会发生脏读。如果两个 UPDATE 查询都成功,则没有部分承诺,只有这样输出才会“已提交”。

执行前:

表 –记录

ID Cus_Name Balance
1 S Adam 100
2 Zee Young 150

执行后:

Input: 
        BEGIN TRY
          BEGIN TRANSACTION
            UPDATE Table SET Balance = Balance - 10 WHERE ID=1;
            UPDATE Table SET Balance = Balance + 10 WHERE ID='C';
          COMMIT TRANSACTION
          PRINT 'Committed'
        END TRY
        BEGIN CATCH
          ROLLBACK TRANSACTION
          PRINT 'Not Committed'
        END CATCH

Output: 
        (1row affected)
        (0row affected)
      Not Committed 

请注意,如果我们输入有效 ID,第一个事务结果将作为已提交或 1 行生效,但第二个不会受到影响。

解释 –
如果我们有一个订票系统,并且一个客户正在尝试预订机票,当时可用的票数为 10,则在完成付款之前,第二个客户想要预订机票,第二次交易将显示第二个客户可用票的数量是 9。如果第一个客户的借记卡或钱包中没有足够的资金,那么第一个交易将回滚,此时 9 个可用座位由第二个交易读取是脏读

例子:
可用票:第一个客户

  • 第一步——
    Input:
    -- Transaction 1
    Select *from Bus_ticket; 

    输出:

    ID Bus_Name Available_Seat
    1 KA0017 10
  • 第二步——
    第一位顾客的预约时间
    Input:  
    --Transaction 1
            BEING Transaction
            UPDATE Bus_Ticket set Available_Seat=9
            WHERE ID=1
            
            --Payment for Transaction 1
            Waitfor Delay '00.00.30'
            Rollback transaction 

    可用票:适用于第 2 位客户,第 1 位客户需支付票款。

  • 第三步——
    Input:  
    -- Transaction 1
    
    set transaction isolation level read uncommitted
    Select *from Bus_ticket where ID=1; 

    输出:

    ID Bus_Name Available_Seat
    1 KA0017 9

请注意,在第 1 个客户的付款期间,第 2 个交易读取它 9 个席位可用,如果某些第 1 个交易回滚然后可用席位 9 是脏读取数据。第一笔交易回滚后,可用席位再次变为 10。第 2 步和第 3 步同时发生。

事务1回滚后实际可用座位:

ID Bus_Name Available_Seat
1 KA0017 10