zoukankan      html  css  js  c++  java
  • SQL Server – Concurrency 并发控制

    前言

    以前写过相关的, 但这篇主要讲一下概念. 帮助理解

    Entity Framework with MySQL 学习笔记一(乐观并发)

    Asp.net core 学习笔记 ( ef core transaction scope & change level )

    sql server 学习笔记 (nested transaction 嵌套事务)

    SQL Server中锁与事务隔离级别 (深入浅出的文章, 以后写事务隔离级别可以参考, 借方这里先)

    并发与事务

    并发是指在同一个时间线上, 多人一起做事情. (比如我在修改一个文档, 你也在修改同一个文档) 

    在做信息处理的时候, 我们有一个"事务"的概念. 我们可以把它理解成一个信息处理的 "过程".

    比如: 

    在信息处理的时候, 最常见的情况是这样的.

    step1: 需要从数据库拿一些信息出来

    step2: 依据这些信息做逻辑判断, 逻辑计算, 结合新的 input, 得出最终要 insert/update 的数据

    step3: 把新的数据 insert/update to 数据库

    这 3 个 step 就是一个过程, 也就是一个事务. 

    并发的意思就是说, 在同一个时间上, 有很多人在做着许许多多的事务.

    数据库对事务有一个原子性规则, 在一个事务中, 可以读读写写多次, 如果间中发生任何问题, 事务会回滚, 测回所有写入的资料 (当然我们也可以在事务任何时候手到回滚.)

    并发诞生的问题

    在进行一个事务的时候, 我们希望不被任何其它事务"影响", 不然就乱了套了.

    比如,

    step 1: 从数据库拿出了数据.

    step 2: 通过数据做逻辑计算

    step 2.5: 这时另一个事务修改了我们 step 1 拿出来的数据. 

    这个我们 step 2 的逻辑计算就不准确了. 

    从而也导致了我们 step 3 update 进去的资料是错误的. 

    这就是并发导致的问题. 

    解决并发的问题

    为什么会乱? 因为没有规则, 所以需要制定规则

    一个最简单的规则, 单线程. 让每一个事务都排队. 一个一个处理. 

    这样就没有并发了咯. 但这当然不行, 太慢了丫. 所以 SQL Server 做了很多不同的 Lock 和 不同的 IsolationLevel 来适量的控制并发的情况.

    规则

    读了就不能写

    如果我们细看刚才的 step 1,2,3 

    它有 2 个点很重要, 第一就是读取出来的数据, 在事务结束以前都不可以被其它事务修改. 

    比如我 SELECT Name FROM Person WHERE Id = 1

    SQL Server 就会把这条 row 锁上, 不让其它事务 update/delete 它 (其它事务就排队, 等我完成了才能修改)

    如果我 SELECT Name FROM Person WHERE Age > 10 

    那么 SQL Server 会锁更大的范围, 同时也不能 insert Age > 10 的 row

    锁的范围越大, 受影响的事务就越多, 排队的事务多就以为着慢. 就回到了最初单线方案的问题. 

    所以这里就是一个我们需要自己控制的 trade-off.

    写了就不能读

    另外一个角度就是, 在一个事务过程中, 也许我们会多次读读写写. 

    而在我写入新数据后, 但事务还没有结束前, 这些新数据是不允许被其它事务读取的. 

    因为可能最终因为某些原因, 我想取消整个事务. 所以就有了一个反向, 写了就不能读的锁机制. 

    一样的道理, 锁的越多排队就越多就越慢. 

    死锁

    由于我们允许事务同时处理 (只是中间加了一些规则), 事务进行到一般的时候有可能会突然去排队.

    而这个排队会依赖另一个事务的结束, 好死不死遇到循环依赖...那么就死锁了. 

    我等你, 你等我. SQL Server 会发现这个死锁的情况, 然后自动干掉其中一个事务, 去解锁. 

    但是我们应该要尽可能在业务层级上去避免这种事情的诞生. 不然又影响数据库性能了. 

    总结 & 乐观并发

    并发的本质就是为了快, 缺乏管理, 导致了混乱. 

    快是我们追求的, 不要乱也是我们追求的, 鱼与熊掌不能兼得, 所以要懂得 trade-off.

    乐观并发

    上面我们说的各种锁的机制都是属于悲观并发.

    有一种叫乐观并发的规则. 它可以在不锁 (不用排队) 的情况下做到一定层度的管理规则 (解决乱的问题)

    举例, 我们想做一个事务处理

    step 1: 读取资料

    step 2: 做逻辑计算

    step 3: update 数据

    一般上我们需要用事务去完成上面 3 个步骤. 但是乐观并发不用.

    它就跑语句, 读, 然后计算, 然后 update.

    回到并发的问题, 如果间中有其它人对数据做了修改怎么办?

    它有一个前提, 读 1 row, update 同一个 row. 这种情况下才可以用乐观并发机制, 超出这个范围还是得用事务和锁.

    在 row 里面加入一个 row version column 做 version control.  每当 row update 的时候 row version 就修改

    然后在 udpate 的时候判断 row version 是否和上一次获取的一样. 

    如果一样就表示期间没有人修改过资料. 如果不一样就更新失败. 

    这是一个很聪明的机制, 因为这种场景是最多的. 用一个巧思来解决总比锁的成本小很多. 但是它也只能解决简单的情况, 遇到复杂一些的最终还是得锁的.

  • 相关阅读:
    sabaki and leelazero
    apply current folder view to all folders
    string operation in powershell
    wirte function in powershell
    add environment path to powershell
    Module in powershell
    sql prompt
    vmware中鼠标在部分区域不能使用
    调整多个控件的dock的顺序
    行为型模型 策略模式
  • 原文地址:https://www.cnblogs.com/keatkeat/p/15555764.html
Copyright © 2011-2022 走看看