S很多同学在学习数据库理论的时候对的概念不是太清楚,数据库中有很多锁的概念,本文试着站在初学者角度去讲解数据库锁的概念。

数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性

加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

首先列出数据锁的分类:

1.  乐观锁

以乐观的心态认为在数据读取的时候不会修改数据,数据库不做加锁处理,在数据修改的时候由用户自行实现

乐观锁的几种实现方式:  

 

  • 版本号

就是给数据增加一个版本标识,在数据库上就是表中增加一个version字段,每次更新把这个字段加1,读取数据的时候把version读出来,更新的时候比较version,如果还是开始读取的version就可以更新了,如果现在的version比老的version大,说明有其他事务更新了该数据,并增加了版本号,这时候得到一个无法更新的通知,用户自行根据这个通知来决定怎么处理,比如重新开始一遍。

  • 时间戳

类似于版本号方式,只是通过时间戳来判断而已,注意时间戳要使用数据库服务器的时间戳不能是业务系统的时间。

  • 待更新字段 

和版本号方式相似,只是不增加额外字段,直接使用有效数据字段做版本控制信息,因为有时候我们可能无法改变旧系统的数据库表结构。假设有个待更新字段叫u_balance,先去读取这个u_balance(假设值为999),更新的时候去比较数据库中u_balance的值是不是我们期望的值(一开始读取的那个值),如果是就把我修改的u_balance的值更新到该字段,否则更新失败。

  • 所有字段

使用所有字段做版本控制信息,只有所有字段都没变化才会执行更新。(很准确的检测,但是降低了程序运行的效率)

 2.  悲观锁

 

就如电话亭一样,为了保证数据的安全性,怀疑数据会被修改所有每次对数据的操作都会对数据上锁。

悲观锁有两种分类:

 

 

 

  •  共享锁(Share Lock):又称作S锁(读锁)

共享锁(S锁)是非独占的,用于所有的读操作,运行并发共享的资源。

SELECT … LOCK IN SHARE MODE sets a shared mode lock on any rows that are read. Other sessions can read the rows, but cannot modify them until your transaction commits. If any of these rows were changed by another transaction that has not yet committed, your query waits until that transaction ends and then uses the latest values.【mysql】

 当读取数据的时候mysql将行设置为共享锁模式,其它会话[Session]可以读取行数据,但是在事务没有提交之前不能修改数据。如果有任何行被修改但是事务没有提交,那么你的查询要等待事务提交拿到最新的数据。

  •  排他锁(Exclusive Lock):又称作X锁(写锁

 

 

         

如果一个事务对对象加了排他锁,其他事务就不能再给它加任何锁了【独占】。

For index records the search encounters, SELECT … FOR UPDATE locks the rows and any associated index entries, the same as if you issued an UPDATE statement for those rows. Other transactions are blocked from updating those rows, from doing SELECT … LOCK IN SHARE MODE, or from reading the data in certain transaction isolation levels. Consistent reads ignore any locks set on the records that exist in the read view. (Old versions of a record cannot be locked; they are reconstructed by applying undo logs on an in-memory copy of the record.)

All locks set by LOCK IN SHARE MODE and FOR UPDATE queries are released when the transaction is committed or rolled back.

Note 
Locking of rows for update using SELECT FOR UPDATE only applies when autocommit is disabled (either by beginning transaction with START TRANSACTION or by setting autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked.

 

 

        SELECT … FOR UPDATE 会锁住行及任何关联的索引条目,和你对那些行执行 update 语句相同。其他的事务会被阻塞在对这些行执行 update 操作,获取共享锁,或从某些事务隔离级别读取数据等操作。所有被共享锁和排他锁查询所设置的锁都会在事务提交或者回滚之后被释放。(使用 SELECT FOR UPDATE 为 update 操作锁定行,只适用于 autocommit 被禁用)

       

  •  更新锁(Update Lock):又称作U锁

 在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象。

 

 

按照作用范围来分,悲观锁可以划分为表级锁和行级锁

  • 表级锁 作用范围为整个表
  • 行级锁 作用范围为行级别

 

 

 

    

 

 

 

 

posted on 2019-09-11 16:27  点石成金e  阅读(1535)  评论(0编辑  收藏  举报