精华内容
下载资源
问答
  • 【数据库】数据库的锁机制及原理

    万次阅读 多人点赞 2018-03-08 18:06:13
    数据库的锁机制,今天彻底理清楚。文章中有参考整理其他一些有价值的博客以及mysql官方文档的内容,如有侵权请联系删除。 数据库锁 先看一张图自己整理的数据库锁的树形图 概要 数据库锁一般可以分为两...

    数据库的锁机制,今天彻底理清楚。文章中有参考整理其他一些有价值的博客以及mysql官方文档的内容,如有侵权请联系删除。

    数据库锁

    先看一张图自己整理的数据库锁的树形图

    概要

    数据库锁一般可以分为两类,一个是悲观锁,一个是乐观锁。

    • 乐观锁一般是指用户自己实现的一种锁机制,假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。乐观锁的实现方式一般包括使用版本号和时间戳。

    • 悲观锁一般就是我们通常说的数据库锁机制,以下讨论都是基于悲观锁。

      悲观锁主要表锁、行锁、页锁。在MyISAM中只用到表锁,不会有死锁的问题,锁的开销也很小,但是相应的并发能力很差。innodb实现了行级锁和表锁,锁的粒度变小了,并发能力变强,但是相应的锁的开销变大,很有可能出现死锁。同时inodb需要协调这两种锁,算法也变得复杂。InnoDB行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

      表锁和行锁都分为共享锁和排他锁(独占锁),而更新锁是为了解决行锁升级(共享锁升级为独占锁)的死锁问题。

      innodb中表锁和行锁一起用,所以为了提高效率才会有意向锁(意向共享锁和意向排他锁)。

    为了表锁和行锁而存在的意向锁

    官方文档中是这么描述的,

    Intention locks are table-level locks that indicate which type of lock (shared or exclusive) a transaction requires later for a row in a table

    知乎上有个解释十分形象,如下:

    1. 在mysql中有表锁,读锁锁表,会阻塞其他事务修改表数据。写锁锁表,会阻塞其他事务读和写。
    2. Innodb引擎又支持行锁,行锁分为共享锁,一个事务对一行的共享只读锁。排它锁,一个事务对一行的排他读写锁。
    3. 这两中类型的锁共存的问题考虑这个例子:事务A锁住了表中的一行,让这一行只能读,不能写。之后,事务B申请整个表的写锁。如果事务B申请成功,那么理论上它就能修改表中的任意一行,这与A持有的行锁是冲突的。数据库需要避免这种冲突,就是说要让B的申请被阻塞,直到A释放了行锁。

    数据库要怎么判断这个冲突呢?

    • step1:判断表是否已被其他事务用表锁锁表
    • step2:判断表中的每一行是否已被行锁锁住。

    注意step2,这样的判断方法效率实在不高,因为需要遍历整个表。于是就有了意向锁。在意向锁存在的情况下,事务A必须先申请表的意向共享锁,成功后再申请一行的行锁。

    在意向锁存在的情况下,上面的判断可以改成

    • step1:不变
    • step2:发现表上有意向共享锁,说明表中有些行被共享行锁锁住了,因此,事务B申请表的写锁会被阻塞。

    注意:申请意向锁的动作是数据库完成的,就是说,事务A申请一行的行锁的时候,数据库会自动先开始申请表的意向锁,不需要我们程序员使用代码来申请。

    行锁的细分

    • 共享锁

      1. 加锁与解锁:当一个事务执行select语句时,数据库系统会为这个事务分配一把共享锁,来锁定被查询的数据。在默认情况下,数据被读取后,数据库系统立即解除共享锁。例如,当一个事务执行查询“SELECT * FROM accounts”语句时,数据库系统首先锁定第一行,读取之后,解除对第一行的锁定,然后锁定第二行。这样,在一个事务读操作过程中,允许其他事务同时更新accounts表中未锁定的行。

      2. 兼容性:如果数据资源上放置了共享锁,还能再放置共享锁和更新锁。

      3. 并发性能:具有良好的并发性能,当数据被放置共享锁后,还可以再放置共享锁或更新锁。所以并发性能很好。

    • 排他锁

      1. 加锁与解锁:当一个事务执行insert、update或delete语句时,数据库系统会自动对SQL语句操纵的数据资源使用独占锁。如果该数据资源已经有其他锁(任何锁)存在时,就无法对其再放置独占锁了。

      2. 兼容性:独占锁不能和其他锁兼容,如果数据资源上已经加了独占锁,就不能再放置其他的锁了。同样,如果数据资源上已经放置了其他锁,那么也就不能再放置独占锁了。

      3. 并发性能:最差。只允许一个事务访问锁定的数据,如果其他事务也需要访问该数据,就必须等待。

    • 更新锁

      更新锁在的初始化阶段用来锁定可能要被修改的资源,这可以避免使用共享锁造成的死锁现象。例如,对于以下的update语句:

      UPDATE accounts SET balance=900 WHERE id=1

      更新操作需要分两步:读取accounts表中id为1的记录 –> 执行更新操作。

      如果在第一步使用共享锁,再第二步把锁升级为独占锁,就可能出现死锁现象。例如:两个事务都获取了同一数据资源的共享锁,然后都要把锁升级为独占锁,但需要等待另一个事务解除共享锁才能升级为独占锁,这就造成了死锁。

      更新锁有如下特征:

      1. 加锁与解锁:当一个事务执行update语句时,数据库系统会先为事务分配一把更新锁。当读取数据完毕,执行更新操作时,会把更新锁升级为独占锁。

      2. 兼容性:更新锁与共享锁是兼容的,也就是说,一个资源可以同时放置更新锁和共享锁,但是最多放置一把更新锁。这样,当多个事务更新相同的数据时,只有一个事务能获得更新锁,然后再把更新锁升级为独占锁,其他事务必须等到前一个事务结束后,才能获取得更新锁,这就避免了死锁。

      3. 并发性能:允许多个事务同时读锁定的资源,但不允许其他事务修改它。

    数据库隔离级别

    了解了数据的锁机制,数据库的隔离级别也就好理解多了。每一种隔离级别满足不同的数据要求,使用不同程度的锁。

    Read Uncommitted,读写均不使用锁,数据的一致性最差,也会出现许多逻辑错误。

    Read Committed,使用写锁,但是读会出现不一致,不可重复读。

    Repeatable Read, 使用读锁和写锁,解决不可重复读的问题,但会有幻读。

    Serializable, 使用事务串形化调度,避免出现因为插入数据没法加锁导致的不一致的情况。

    • 读不提交,造成脏读(Read Uncommitted)

      一个事务中的读操作可能读到另一个事务中未提交修改的数据,如果事务发生回滚就可能造成错误。

      例子:A打100块给B,B看账户,这是两个操作,针对同一个数据库,两个事物,如果B读到了A事务中的100块,认为钱打过来了,但是A的事务最后回滚了,造成损失。

      避免这些事情的发生就需要我们在写操作的时候加锁,使读写分离,保证读数据的时候,数据不被修改,写数据的时候,数据不被读取。从而保证写的同时不能被另个事务写和读。

    • 读提交(Read Committed)

      我们加了写锁,就可以保证不出现脏读,也就是保证读的都是提交之后的数据,但是会造成不可重读,即读的时候不加锁,一个读的事务过程中,如果读取数据两次,在两次之间有写事务修改了数据,将会导致两次读取的结果不一致,从而导致逻辑错误。

    • 可重读(Repeatable Read)

      解决不可重复读问题,一个事务中如果有多次读取操作,读取结果需要一致(指的是固定一条数据的一致,幻读指的是查询出的数量不一致)。 这就牵涉到事务中是否加读锁,并且读操作加锁后是否在事务commit之前持有锁的问题,如果不加读锁,必然出现不可重复读,如果加锁读完立即释放,不持有,那么就可能在其他事务中被修改,若其他事务已经执行完成,此时该事务中再次读取就会出现不可重复读,

      所以读锁在事务中持有可以保证不出现不可重复读,写的时候必须加锁且持有,这是必须的了,不然就会出现脏读。Repeatable Read(可重读)也是MySql的默认事务隔离级别,上面的意思是读的时候需要加锁并且保持

    • 可串行化(Serializable)

      解决幻读问题,在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。
      这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争

    参考文献: https://www.cnblogs.com/luyucheng/p/6297752.html
    https://www.zhihu.com/question/51513268
    https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html

    展开全文
  • 数据库的锁

    2007-06-14 09:22:00
    使数据库数据实现互斥读取:查询窗口1:begin transelect top 2 * from table with(updlock,readpast)查询窗口2:begin tanselect * from table with(updlock,readpast) 可以使用 SELECT、INSERT、UPDATE 和 ...

    使数据库中的数据实现互斥读取:

    查询窗口1:

    begin tran

    select top 2 * from table with(updlock,readpast)

    查询窗口2:

    begin tan

    select * from table with(updlock,readpast) 

     

    可以使用 SELECT、INSERT、UPDATE 和 DELETE 语句指定表级锁定提示的范围,以引导 Microsoft  SQL Server 2000 使用所需的锁类型。当需要对对象所获得锁类型进行更精细控制时,使用表级锁定提示更改默认的锁定行为。
    所指定的表级锁定提示有如下几种:   
    1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。    
    2. NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或“脏数据”,这个选项仅仅应用于SELECT语句。    
    3. PAGLOCK:指定添加页锁(否则通常可能添加表锁)。  
    4. READCOMMITTED用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL Server 2000 在此隔离级别上操作。。  
    5. READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁,READPAST仅仅应用于READ COMMITTED隔离性级别下事务操作中的SELECT语句操作。   
    6. READUNCOMMITTED:等同于NOLOCK。    
    7. REPEATABLEREAD:设置事务为可重复读隔离性级别。  
    8. ROWLOCK:使用行级锁,而不使用粒度更粗的页级锁和表级锁。   
    9. SERIALIZABLE:用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。 
    10. TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。    
    11. TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。  
    12. UPDLOCK :指定在读表中数据时设置更新 锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改。   
    死锁问题
    在数据库系统中,死锁是指多个用户(进程)分别锁定了一个资源,并又试图请求锁定对方已经锁定的资源,这就产生了一个锁定请求环,导致多个用户(进程)都处于等待对方释放所锁定资源的状态。这种死锁是最典型的死锁形式, 例如在同一时间内有两个事务A和B,事务A有两个操作:锁定表part和请求访问表supplier;事务B也有两个操作:锁定表supplier和请求访问表part。结果,事务A和事务B之间发生了死锁。

    http://cache.baidu.com/c?word=sqlserver%2C%CB%F8%3B%C0%E0%D0%CD&url=http%3A//www%2E123ku%2Ecom/html/database/sqlserver/2006%2D6/21/00%5F20%5F17%5F307%5F5%2Eshtml&p=9a708b15d9c543dd1cbe9b7e0c5391&user=baidu

    展开全文
  • 数据库的锁机制

    2017-10-02 13:54:03
    为了保证事务的隔离性与一致性,就有了数据库的锁机制。在数据库中,存在着很多种类的锁:共享锁、排他锁、悲观锁、乐观锁、行级锁、表级锁等。基本的锁类型锁有两种基本的类型:共享锁、排他锁 共享锁(Share ...

    为什么需要锁机制

    事务是并发控制的基本单位,保证事务ACID原则是事务处理的重要任务,但是当多个事务对数据库进行并发操作时,就有可能破坏事务的ACID特性。

    为了保证事务的隔离性与一致性,就有了数据库的锁机制。

    在数据库中,存在着很多种类的锁:共享锁、排他锁、悲观锁、乐观锁、行级锁、表级锁等。

    基本的锁类型

    锁有两种基本的类型:共享锁、排他锁

    共享锁(Share Locks,简称S锁,也叫读锁)

    若事务T对数据对象A加上S锁,则事务T只能读取A而不能修改A,其他事务也只能对该数据对象A加上S锁,而不能加上X锁,直到事务T释放A上的S锁。

    即是说,共享锁只允许多个事务读取数据,而不允许修改数据。

    排他锁(Exclusive Locks,简称X锁,也叫写锁)

    若事务T对数据对象A加上X锁,则只允许事务T对A进行读取和修改,其他事务都不能对A加上任何类型的锁,直到事务T释放A上的X锁。

    即是说,排他锁只允许一个事务读取和修改被锁定的数据。

    锁会带来什么问题

    给数据加锁可能会引起活锁和死锁的问题。

    活锁

    如果事务T1封锁了数据对象R,事务T2也请求封锁R,于是T2等待。T3也请求封锁R,当T1释放了R上的锁后系统首先批准了T3的请求,于是T2仍然等待。然后T4也请求封锁R,当T3释放了R上的锁后系统又批准了T4的请求,于是T2仍然等待……

    在这个过程中,T2可能会永远在等待,这就是活锁。

    避免活锁的简单方法就是采用先来先到的策略,当多个事务请求封锁同一数据对象的时候,封锁子系统按请求封锁的先后次序对事务进行排队,数据对象上的锁一旦释放,就批准申请队列中第一个事务获得锁。

    死锁

    如果事务T1封锁了数据R1,事务T2封锁了数据R2,然后T1请求封锁R2,由于R2已经被T2封锁,所以T1等待T2释放R2上的锁;接着T2也请求封锁R1,由于R1已经被T1封锁,所以T2等待T1释放R1上的锁。

    这样就出现了两个事务互相等待的局面,这两个事务永远也不能结束,形成了死锁。

    数据库一般允许发生死锁,并采用一定手段定期诊断系统中有无死锁,若有则解除之。一般采用超时法或事务等待图法来诊断死锁。

    • 超时法

    如果一个事务等待的时间超过了规定的时限,就认为发生了死锁。超时法实现简单,但有可能发生误判死锁,事务因为其他原因使等待时间超过了时限导致被系统误认为发生了死锁;如果时限设置得太长,也可能无法及时发现死锁。

    • 事务等待图法

    事物等待图是一个有向图G=(T,U)。T为结点的集合,每个结点表示正运行的事务;U为边的集合,每条边表示事务等待的情况。若T1等待T2,则T1、T2之间画一条有向边,从T1指向T2。

    事务等待图动态地反映了所有事务的等待情况,并发控制子系统周期性地生成事务等待图,并进行检测。如果发现图中存在回路,则表示系统中发生了死锁。

    死锁的情况可以多种多样,如下图所示,在大回路中又有小回路。

    事物等待图

    如何解除死锁

    当DBMS检测到系统中存在死锁,就要设法解除。通常采用的做法是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的锁,使其他事务得以运行下去。解除死锁之后,被撤销的事务所执行的数据操作必须加以恢复。

    锁的粒度

    锁的粒度就是锁的作用范围,一般分为行级锁、表级锁。行级锁锁定记录行,表级锁锁定整个表。

    行级锁

    系统开销大,加锁慢,锁定粒度最小,会发生死锁,但是发生冲突的概率最低,并发性最高

    表级锁

    系统开销小,加锁快,锁定粒度最大,不会发生死锁,但是发生冲突的概率最高,并发性最低

    总结

    • 共享锁只用于表级,排它锁用于行级或表级。
    • 加了共享锁的对象,可以继续加共享锁,不能再加排他锁。
    • 加了排他锁的对象,不能再加任何锁。

    悲观锁(Pessimistic Lock)

    顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

    它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。

    悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

    乐观锁(Optimistic Lock)

    顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据。

    乐观锁适用于多读的应用类型,即冲突真的很少发生的时候,这样可以提高吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒会降低性能,所以这种情况下用悲观锁就比较合适。

    乐观锁与悲观锁不同的是,它是一种逻辑上的锁,而不需要数据库提供锁机制来支持,它需要我们自己在程序中实现。乐观锁的实现,一般是通过数据版本version或者时间戳来实现。

    数据版本version(版本戳)

    在需要乐观锁的表中添加一个version字段,每修改一次数据就将version+1。每次对数据进行操作时先读出当前的数据版本,如果要对数据进行修改就先判断此时的version是否与之前查询到的version一致,如果version一样说明在这期间没有其他人修改这条数据,则可以执行此次更新操作并更新版本号;如果version不一致,则意味着冲突,不执行此次更新。

    代码实现例子:

    查询当前商品信息:
    select name,num,version from products where id = #{id};

    执行更新商品操作:
    update products set num = num - 1, version = version + 1 where id = #{id} and version = #{version};

    时间戳timestamp

    和version类似,每操作一次数据就修改时间戳;在进行更新操作时需要先判断当前时间戳是否与之前查询到的时间戳一致。

    总结

    通常情况下,写操作较少时,使用乐观锁,写操作较多时,使用悲观锁。除了自己手动实现乐观锁之外,有的持久层框架已经封装好了乐观锁的实现。比如Hibernate就提供了以数据版本实现的乐观锁机制。

    展开全文
  • Mysql 数据库的锁机制分析

    万次阅读 2019-09-04 20:10:51
    文章目录Mysql 数据库的锁机制分析一、问题背景1. 为什么要加锁?2.要解决的问题二、锁是什么三、锁的分类1.行级锁2.表级锁3.页级锁四、MySQL常用存储引擎的锁机制1. **`MyISAM`和`MEMORY`采用表级锁(table-level ...

    Mysql 数据库的锁机制分析

    一、问题背景

    1. 为什么要加锁?

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

    2.要解决的问题

    • 多用户环境下保证数据库完整性和一致性

    二、锁是什么

    • 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足。
    • 加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。

    三、锁的分类

    1.行级锁

    • 行级锁
    • 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。
    • 特点
    • 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

    2.表级锁

    • 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
    • 特点
    • 开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

    3.页级锁

    • 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁
    • 特点
    • 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

    四、MySQL常用存储引擎的锁机制

    1. MyISAMMEMORY采用表级锁(table-level locking)

    2. BDB采用页面锁(page-level locking)或表级锁,默认为页面锁

    3. InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁

    • InnoDB行锁是通过给索引上的索引项加锁来实现的,InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!

    在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。

    行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁。行级锁的缺点是:由于需要请求大量的锁资源,所以速度慢,内存消耗大。

    实例说明

    • MySQL InnoDB引擎默认的修改数据语句:update,delete,insert都会自动给涉及到的数据加上排他锁。

    • select语句默认不会加任何锁类型,如果加排他锁可以使用select …for update语句,加共享锁可以使用select … lock in share mode语句。

    • 所以加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过for updatelock in share mode锁的方式查询数据,但可以直接通过select …from…查询数据,因为普通查询没有任何锁机制。

    4. 行级锁与死锁

    • MyISAM中是不会产生死锁的,因为MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。而在InnoDB中,锁是逐步获得的,就造成了死锁的可能。

    • 在MySQL中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引非主键索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。在UPDATE、DELETE操作时,MySQL不仅锁定WHERE条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的next-key locking

    • 当两个事务同时执行,一个锁住了主键索引,在等待其他相关索引。另一个锁定了非主键索引,在等待主键索引。这样就会发生死锁

    • 发生死锁后,InnoDB一般都可以检测到,并使一个事务释放锁回退,另一个获取锁完成事务。

    5. 共享锁与排它锁

    共享锁(Share Lock)

    • 共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。

    • 如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。

    • 用法 SELECT ... LOCK IN SHARE MODE

    • 在查询语句后面增加LOCK IN SHARE MODE,Mysql会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。

    排它锁(eXclusive Lock)

    • 排他锁又称写锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。

    用法 SELECT … FOR UPDATE;

    在查询语句后面增加FOR UPDATE,Mysql会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。

    6. 乐观锁(Optimistic Lock)

    是什么

    • 假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。

    相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。

    数据版本,为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。

    实现数据版本有两种方式,** 第一种是使用版本号,第二种是使用时间戳 **。

    使用版本号实现乐观锁

    • 使用版本号时,可以在数据初始化时指定一个版本号,每次对数据的更新操作都对版本号执行+1操作。并判断当前版本号是不是该数据的最新的版本号。
    1.查询出商品信息
    select (status,status,version) from t_goods where id=#{id}
    2.根据商品信息生成订单
    3.修改商品status为2
    update t_goods
    set status=2,version=version+1
    where id=#{id} and version=#{version};
    

    优点与不足

    • 乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。但如果直接简单这么做,还是有可能会遇到不可预期的结果,例如两个事务都读取了数据库的某一行,经过修改以后写回数据库,这时就遇到了问题

    7. 悲观锁(Pessimistic Lock)

    是什么

    • 在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制 (也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)

    悲观锁的流程

    • 在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
    • 如果加锁失败,说明该记录正在被修改,那么当前查询可能要等待或者抛出异常。具体响应方式由开发者根据实际需要决定。
    • 如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
    • 其间如果有其他对该记录做修改或加排他锁的操作,都会等待我们解锁或直接抛出异常。

    MySQL InnoDB中使用悲观锁

    • 要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。set autocommit=0;
    //0.开始事务
    begin;
    //1.查询出商品信息
    select status from t_goods where id=1 for update;
    //2.根据商品信息生成订单
    insert into t_orders (id,goods_id) values (null,1);
    //3.修改商品status为2
    update t_goods set status=2;
    //4.提交事务
    commit;
    

    上面的查询语句中,我们使用了select…for update的方式,这样就通过开启排他锁的方式实现了悲观锁。此时在t_goods表中,id为1的 那条数据就被我们锁定了,其它的事务必须等本次事务提交之后才能执行。这样我们可以保证当前的数据不会被其它事务修改。

    python相关具体实现

    感谢作者!

    展开全文
  • 数据库的锁是什么,有哪几种锁,代表什么?请大神解答,谢谢谢谢谢谢谢谢
  • SQLite数据库的锁机制

    2016-03-17 15:08:53
    SQLite数据库的锁机制包括四种锁,共享锁(Shared lock)、预留锁(Reserved lock)和未决锁(Pending lock)、排他锁(Exclusive lock) 其中读操作,用的是Shared lock,所以并发的多个读数据库。如果有一个...
  • Oracle数据库的锁

    2013-01-25 16:15:39
    Oracle数据库的锁    数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的...
  • Java中的锁和数据库的锁

    千次阅读 2019-04-05 10:33:15
    面试中经常被问到锁,Java中有锁,数据库中也有锁,这两个中的锁都是怎么分类的呢?有两篇博客关于这个问题讲的特别好,详见下文~ Java中的锁 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇...
  • 数据库的锁---让你面试不再害怕

    千次阅读 2020-07-13 12:04:00
    数据库的锁 InnoDB,是MySQL的数据库引擎之一,在5.5后为MySQL的默认存储引擎,另外一种是MyISAM 简单介绍区别: 1、MyISAM是非事务安全的,而InnoDB是事务安全的 2、InnoDB 支持外键,而 MyISAM 不支持。对一个包含...
  • 详谈数据库的锁

    2015-08-07 19:32:48
    数据库大并发操作要考虑死锁和锁的性能问题。看到网上大多语焉不详(尤其更新),所以这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为一个线程,T2 为另一...
  • 一、数据库的锁(就讲讲主要的那几个,拿去面试用就够了)也就是 行锁,表锁,悲观锁,乐观锁。 【首先一个很重要的问题 : 为什么要锁?】  就是为了防止并发操作的过程中,会发生多个事务对数据进行存取修改等...
  • MySQL数据库的锁机制

    2018-10-09 10:33:34
    引言:MySQL数据库的引擎分为三种,MyISAM(ISAM)、InnoDB以及MEMORY,具体的引擎类型性能比较可以baidu到,这里就不多说了,本文中所说的锁机制基于InnoDB引擎,那为啥说基于InnoDB引擎说锁呢?因为InnoDB支持事务...
  • Informix数据库的锁技术 INFORMIX使用锁技术解决在多用户访问数据库情况下,对同一对象访问的并发控制问题。INFORMIX 支持复杂的、可伸缩性的锁技术。 锁的类型 INFORMIX有三种不同类型的锁。它们在不同的情况下使用...
  • 关于数据库的锁粒度

    2019-01-13 15:41:37
    一种提高共享资源并发性方式就是让锁定对象更具有选择性。尽量只锁定需要修改...锁的各种操作,包括获得,检查是否已经消除,释放等,都会增加系统开销。 所谓策略,就是在锁的开销和数据安全性之间...
  • 在博文《数据库并发事务控制四:postgresql数据库的锁机制 》 http://blog.csdn.net/beiigang/article/details/43302947 中后面提到: 常规锁机制可以参考pg的官方手册,章节和内容见下面 13.3. Explicit ...
  • 对于informix数据库的锁: 查看被锁的表: select * from sysmaster:syslocks where tabname = jtfx_TMP_CALL_TODAY1 解锁: 只要把 owner 查出来,然后在后台使用 onmode -z owner 的方式释放锁 对于Oracle...
  • Sqlite数据库的锁

    千次阅读 2011-12-24 15:10:05
    数据库锁 在SQLite中,锁和事务是紧密联系的。为了有效地使用事务,需要了解一些关于如何加锁的知识。 SQLite采用粗放型的锁。当一个连接要写数据库,所有其它的连接被锁住,直到写连接结束...SQLite有5个不同的锁
  • 数据库锁出现原因是为了处理并发问题,因为数据库是一个多用户共享资源,当出现并发时候,就会导致出现各种各样奇怪问题,就像程序代码一样,出现多线程并发时候,如果不做特殊控制话,就会出现意外...
  • 数据库的锁表和解锁操作

    千次阅读 2017-09-05 12:36:05
    SqlServer 查询被表和解锁表 --1.查看被表 SELECT request_session_id as spid,OBJECT_NAME(resource_associated_entity_id) as tableName FROM sys.dm_tran_locks WHERE resource_type='OBJECT' --spid ...
  • 数据库的锁机制定义中有乐观锁(或积极锁,optimistic locking)和悲观锁(或消极锁,pessimistic locking)两种分类。乐观锁,顾名思义,对发生并发的情况估计比较乐观,所以对锁的控制比较宽松,只有
  • MySQL基础之数据库的锁机制

    千次阅读 2018-01-02 14:44:02
    为了更好应对高并发,封锁、时间戳、乐观并发控制(乐观)、悲观并发控制(悲观)都是并发控制采用主要技术方式。分类①、按操作划分:DML,DDL ②、按锁粒度划分:表级、行级、页级 ③、按锁...
  • 需要我们手动释放数据库表记录! 一、表场景介绍 这边,我讲述一种我遇到过的数据库锁表场景!在项目中我使用mybatis框架做项目持久成植入!在使用过程中,在同一个service中,...
  • JPA Hibernate 和数据库 机制

    千次阅读 2016-02-24 22:00:15
    本文总结Java中有关数据库保存持久数据的锁机制,不只是纯粹数据库自身的锁,本文主要就Java持久层三个技术数据库、JPA和Hibernate的锁应用进行了总结。  在并发理论中,锁是用于保护可变的共享数据,以保证数据...
  • 是计算机协调多个进程或线程并发访问某一个资源机制,在数据库中,除传统计算资源(CPU、RAM、I/O)争用以外,数据也是一种供许多用户共享资源。如何保证数据并发访问一致性、有效性是所在有数据库必须...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 37,152
精华内容 14,860
关键字:

数据库的锁