数据库的 基本分为 共享锁和排它锁
排它锁顾名思义,不能和其他任何所共存。
以SqlServer中某一行数据为例,
特殊的,WithNoLock 这个是不给数据加上任何锁,所以根本和锁没关系
再说update,update的过程是给这条数据加上排它锁,所以当另外事物过来要求修改这条数据的时候,会由于排它锁的互斥,导致无法申请到排它锁,从而实现同一时间只有一个事物对同一条数据进行修改。同样当该条数据正在修改中但其所属的事物还未提交的时候,查询需要在这条数据上加上共享锁的过程也由于排它锁的存在导致被阻塞。只有当修改的操作完成并且其所在事物提交以后,其他需要在该数据上加锁的操作才能进行下去。
最后说 select ,一般的select 是直接给数据加上一个共享锁,其他的事物中的select 由于这条数据将是存在共享锁的原因,所以可以在多个事物中查询同一条数据。
说到锁自然要提到数据库事物隔离级别
各种隔离级别就是通过锁来实现,
以sqlserver为例,
read uncommited
直接可以当作WithNoLock 理解了
read commited
事物1 select该数据时加上共享锁,读完该共享锁立即释放。此时事物2中的update操作可以正常给该条数据加上排它锁并执行,若此时事物1再次select 该数据会发现该数据已经改变(由于事物2已经改变了该数据) ,这也就是所谓的脏读。所以 read commited 有脏读的风险。
repeatable read
事物1 select该数据时加上共享锁,但是直到事物完成该共享锁才释放,所以在事物1执行过程中,事物2过来想要update该条数据,都由于update需要加上排它锁,而和事物1的共享锁冲突,导致update被阻塞。这就避免了脏读的问题。但是如果事物2仅仅是select 且 事物1 没有update,那么是可以被读取的。且如果事物2新增一条数据。那么事物1的select 有可能读到的数据比原来多。这种情况被称为幻读,所以 repeatable read 有幻读的风险。
serializable
为了解决幻读的情况,把整个表都锁住,在事物1执行的时候,事物2连新增删除都不允许。
再说说delete 首先update 的过程其实是先新增再删除,这点可以从触发器中看出来。所以update是独占锁也就是说明了delete 也是独占锁。所以delete 的情况可以当作update 来理解。