• 数据库系列(三)之 锁


    锁的意义

         数据库中有很多‘锁’的使用。怎么合理并灵活的应用是一个值得讨论深究的问题。

         锁为何而存在?为了在同一时间内,只能处理一种请求。而避免导致的数据错乱。例如商城中,库存的扣减;金融系统中金钱的转账。

         在耳熟能详的商城中,库存扣减有很多种方法来处理,其中数据库锁是很大众的一种方式。在应用程序中,存在着多个用户同一时间购买商品的可能。这时候就要扣减库存。怎么保证库存扣减的正确性呢?答案就是用锁来做限制。

         例如商品只剩下库存数量为1。这时候商品有多人在抢,那么只能有一个人购买成功。否则扣减过多而导致业务销售的‘售后’问题。

     

    乐观锁与悲观锁

    悲观锁                                                                                              

         悲观锁是指同时只有一个才能处理锁的内容,其它都需要等待排队。悲观锁是建议在数据库层面。

         在数据库层面,实现锁可以有表锁、页锁、行锁。它们各自有优缺点。

    表锁                        

         表锁顾名思义,锁住整张表。

         表锁的特点:开销小,加锁快;不会出现死锁;锁冲突概率高,并发度低。

    SqlServer

         sqlsever中加表锁很简单,在select最后加相应的语句即可:

    共享锁:SELECT * FROM table WITH (HOLDLOCK)

    排他锁:SELECT * FROM table WITH (TABLOCKX)

    Postgresql

         使用表锁的格式为:LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]

    页锁                        

         页锁一般比较少用。

         页锁的特点:开销、加锁速度、并发度在于表锁与行锁之间;会出现死锁。

    行锁                        

         行锁是使用较多的一种。

         行锁的特点:开销大,加锁慢;会出现死锁;锁定粒度小;索冲突概率低,并发度高。

         在大部分的数据库中,执行delete、insert、update语句都会加锁,delete、insert一般都是行锁。update时看是否存在索引为查询条件,如果存在则行锁,不存在则表锁。

    Mysql

         在Mysql中,不同的引擎支持的表锁是不同的。最广泛使用的引擎是InnoDB,也是作为各大云厂商的默认使用。InnoDB是支持行锁、表锁。MyISAM引擎支持表锁。BDB引擎支持表锁、页锁。

         这里只介绍InnoDB引擎,这也是使用最多的引擎。

         在mysql中,表锁的语句如下:

    共享锁:SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。

    排他锁:SELECT * FROM table_name WHERE ... FOR UPDATE。

         共享锁与排他锁这里不介绍,后面会详细说明。

         表锁没有固定的语句,使用的时候会根据索引来确定使用表锁还是行锁。这意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

    SqlServer

         sqlserver的行级锁比较简单,在表名后面加ROWLOCK即可:

    SELECT * FROM table ROWLOCK WHERE id=xxx

    Postgresql

         因Json的原因,Postgresql越来越流行。其使用行锁的关键字为:FOR UPDATE、FOR NO KEY UPDATE、FOR SHARE、FOR KEY SHARE。

    乐观锁                                                                                               

         在悲观锁中,之所以成为悲观,因为都需要等待的操作。有没有一种无需等待、相互争抢的锁呢?答案是有的,与之相反,称为乐观锁。

         乐观锁不是在数据库层面做的,在程序上写。怎么实现乐观锁呢?通常在表中加个字段,版本号version或当期时间date都可以。

         举个version版本号的例子,例如当期的version=1。

         语句一般为:update table set inventory=1, version=version+1 where version=1 and id=xxx

         这样就实现了乐观锁的模式。因为他们都互相争抢,谁抢到了就返回修改条数为1,没有抢到为0。其实其中也使用到了数据库中的悲观锁。因为在update时,使用了索引,是锁行的。但是这种明显是比全悲观锁的形式是快的。

         乐观锁的特点:速度快、但增加数据库CPU。

     

    排它锁与共享锁

         排他锁及共享锁其实很简单。

         排它锁是指在锁住期间,不能对相应的数据做查询、增加、修改、删除操作。排他锁保证了其他事物不能读,用于行级。

         共享锁是指在锁住期间,能对相应的数据做查询操作,不能做增加、修改、删除操作。保证了其他事务不能写,用于表级。

     

    可以关注本人的公众号,多年经验的原创文章共享给大家。

  • 相关阅读:
    通过连接池和字段索引,提升单点登录cas的性能
    crc16.c
    modbus.c
    sciencesoftware科学软件
    C++ ASSERT() 断言机制
    sessionKey
    main函数中argc理解
    compile,build和execute的区别
    Linux vi 中移动光标 命令
    OCP读书笔记(2)
  • 原文地址:https://www.cnblogs.com/alunchen/p/11276218.html
Copyright © 2020-2023  润新知