共享锁(读锁)和排他锁(写锁)

 

共享锁(S锁):共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。

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

排他锁(X锁):用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。

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

我们在操作数据库的时候,可能会由于并发问题而引起的数据的不一致性(数据冲突)

乐观锁
乐观锁不是数据库自带的,需要我们自己去实现。乐观锁是指操作数据库时(更新操作),想法很乐观,认为这次的操作不会导致冲突,在操作数据时,并不进行任何其他的特殊处理(也就是不加锁),而在进行更新后,再去判断是否有冲突了。

通常实现是这样的:在表中的数据进行操作时(更新),先给数据表加一个版本(version)字段,每操作一次,将那条记录的版本号加1。也就是先查询出那条记录,获取出version字段,如果要对那条记录进行操作(更新),则先判断此刻version的值是否与刚刚查询出来时的version的值相等,如果相等,则说明这段期间,没有其他程序对其进行操作,则可以执行更新,将version字段的值加1;如果更新时发现此刻的version值与刚刚获取出来的version的值不相等,则说明这段期间已经有其他程序对其进行操作了,则不进行更新操作。

举例:

下单操作包括3步骤:

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};

除了自己手动实现乐观锁之外,现在网上许多框架已经封装好了乐观锁的实现,如hibernate,需要时,可能自行搜索"hiberate 乐观锁"试试看。

悲观锁
与乐观锁相对应的就是悲观锁了。悲观锁就是在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过获取锁才能进行对相同数据的操作,这点跟java中的synchronized很相似,所以悲观锁需要耗费较多的时间。另外与乐观锁相对应的,悲观锁是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了。

说到这里,由悲观锁涉及到的另外两个锁概念就出来了,它们就是共享锁与排它锁。共享锁和排它锁是悲观锁的不同的实现,它俩都属于悲观锁的范畴。

共享锁
共享锁指的就是对于多个不同的事务,对同一个资源共享同一个锁。相当于对于同一把门,它拥有多个钥匙一样。就像这样,你家有一个大门,大门的钥匙有好几把,你有一把,你女朋友有一把,你们都可能通过这把钥匙进入你们家,进去啪啪啪啥的,一下理解了哈,没错,这个就是所谓的共享锁。
刚刚说了,对于悲观锁,一般数据库已经实现了,共享锁也属于悲观锁的一种,那么共享锁在mysql中是通过什么命令来调用呢。通过查询资料,了解到通过在执行语句后面加上lock in share mode就代表对某些资源加上共享锁了。
比如,我这里通过mysql打开两个查询编辑器,在其中开启一个事务,并不执行commit语句
city表DDL如下:
CREATE TABLE `city` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`state` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

begin;
SELECT * from city where id = "1"  lock in share mode;

然后在另一个查询窗口中,对id为1的数据进行更新

update  city set name="666" where id ="1";
此时,操作界面进入了卡顿状态,过几秒后,也提示错误信息
[SQL]update  city set name="666" where id ="1";
[Err] 1205 - Lock wait timeout exceeded; try restarting transaction

那么证明,对于id=1的记录加锁成功了,在上一条记录还没有commit之前,这条id=1的记录被锁住了,只有在上一个事务释放掉锁后才能进行操作,或用共享锁才能对此数据进行操作。
再实验一下:

update city set name="666" where id ="1" lock in share mode;
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'lock in share mode' at line 1

加上共享锁后,也提示错误信息了,通过查询资料才知道,对于update,insert,delete语句会自动加排它锁的原因

于是,我又试了试SELECT * from city where id = "1" lock in share mode;

这下成功了。

排它锁
排它锁与共享锁相对应,就是指对于多个不同的事务,对同一个资源只能有一把锁。
与共享锁类型,在需要执行的语句后面加上for update就可以了

行锁
行锁,由字面意思理解,就是给某一行加上锁,也就是一条记录加上锁。

比如之前演示的共享锁语句

SELECT * from city where id = "1"  lock in share mode;

由于对于city表中,id字段为主键,就也相当于索引。执行加锁时,会将id这个索引为1的记录加上锁,那么这个锁就是行锁。

表锁
表锁,和行锁相对应,给这个表加上锁。

MyISAM引擎里有的,暂时研究了

-----------------------------------------------------------------------
sql查询的时候会加S锁,查询解锁后,会释放S锁。至于会不会形成阻塞,那要看你的select语句有没有执行完毕,阻塞多长时间要看你sql语句的执行效率
 
取决于你的隔离级别,默认是加S锁的。
select 持有的是表锁
更加会堵塞,这些可以依靠索引,事务,等调整锁的粒度 尽量减少堵塞的时间
----------------------------------------------------------------------
SQL Server提供了强大而完备的锁机制来帮助实现数据库系统的并发性和高性能。用户既能使用SQL Server的缺省设置也可以在select 语句中使用“加锁选项”来实现预期的效果。 本文介绍了SELECT语句中的各项“加锁选项”以及相应的功能说明。   

功能说明:    

NOLOCK(不加锁)   

此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到未完成事务(Uncommited Transaction)或回滚(Roll Back)中的数据, 即所谓的“脏数据”。   

HOLDLOCK(保持锁)   

此选项被选中时,SQL Server 会将此共享锁保持至整个事务结束,而不会在途中释放。      

UPDLOCK(修改锁)   此选项被选中时,SQL Server 在读取数据时使用修改锁来代替共享锁,并将此锁保持至整个事务或命令结束。使用此选项能够保证多个进程能同时读取数据但只有该进程能修改数据。   

TABLOCK(表锁)   此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。      

PAGLOCK(页锁)   此选项为默认选项, 当被选中时,SQL Server 使用共享页锁。      

 
  TABLOCKX(排它表锁)   此选项被选中时,SQL Server 将在整个表上置排它锁直至该命令或事务结束。这将防止其他进程读取或修改表中的数据。     
 
  使用这些选项将使系统忽略原先在SET语句设定的事务隔离级别(Transaction Isolation Level)。 请查阅SQL Server 联机手册获取更多信息。

例:

select * from tablename where ... with(nolock)

select * from tablename where ... with(holdlock)

select * from tablename with (rowlock) where id=3 注意: 锁定数据库的一个表的区别

SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除

SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除

SQL SERVER SELECT语句中加锁选项的详细说明的更多相关文章

  1. SQL SERVER SELECT语句中加锁选项的详细说明 [转]

    SQL Server提供了强大而完备的锁机制来帮助实现数据库系统的并发性和高性能.用户既能使用SQL Server的缺省设置也可以在select 语句中使用“加锁选项”来实现预期的效果. 本文介绍了S ...

  2. SQL Server - select语句练习

    创建表和输入数据 CREATE TABLE STUDENT(SNO VARCHAR(3) NOT NULL,   SNAME VARCHAR(4) NOT NULL,   SSEX VARCHAR(2 ...

  3. sql server 2008语句中的go有什么用?

    GO表示一个批处理的结束, SQLSERVER遇到Go以后就会将GO之前的语句作为一整批进行处理你在SSMS里执行的时候, 通常加不加都可以,但是如果实在SQLCMD下执行, GO就是一个执行命令了另 ...

  4. SQL server SELECT 语句的基本结构

    SELECT select_list [INTO new_table] [FROM table_source] [WHERE search_condition] [GROUP BY GROUP_BY_ ...

  5. SQL Server CASE语句中关于Null的处理

    问: 从数据表中选择一个字段“field”,如果“field”值是1或NULL就赋值为1,其它情况为0,该怎么写啊?这样写对不对啊?(CASE fieldWHEN '1' THEN '1'WHEN N ...

  6. SQL Server SELECT逻辑处理顺序

    SQL Server SELECT语句,逻辑处理顺序,虽然SELECT位于语句最前面,它在逻辑处理中,基本上是最后一个被执行的部分. 下面列出查询子句在逻辑上处理顺序: 1.  FROM 2.  WH ...

  7. 如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?

    如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36) 与这个问题具有相同性质的其他描述还包括:如何 ...

  8. 用sql的select语句从数据库中获取数据

    基本的select语句 select语句中的算数表达式和NULL值 列的别名 使用连接符操作,literal character strings,alternative quote operator, ...

  9. SQL SERVER 2005/2008 中关于架构的理解(二)

    本文上接SQL SERVER 2005/2008 中关于架构的理解(一)      架构的作用与示例 用户与架构(schema)分开,让数据库内各对象不再绑在某个用户账号上,可以解决SQL SERVE ...

随机推荐

  1. rabbitmq数据备份与还原

    一.场景 现在有服务器A和服务器B ,由于业务需要,要求把服务器A上mq的数据迁移到服务器B上,rabbitmq的数据包括元数据(RabbitMQ用户.vhost.队列.交换和绑定)和消息数据,而消息 ...

  2. linux网络编程之system v信号量(一)

    今天起,学习信号量相关的知识,下面开始: 关于信号量,在前面已经介绍过了,这里回顾一下: 通过上面的描述,很容易就能想到信号量的一上数据结构: 下面再来回顾一下P.V原语: 所谓的原语就是指这段代码是 ...

  3. WebService在ssm框架中的简单应用

    WebService的概念 Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配 ...

  4. el-input 只能输入数字并限制长度

    在上一个博客中,有关于限制长度的使用,本文介绍限制只能输入数字的方法 el-input 代码如下: <el-form-item label="账号" required> ...

  5. Redis的下载、安装及启动

    一.下载Redis 1. redis 的下载路径 https://pan.baidu.com/s/1tdMzOlcTlFC7Z3a3I_59hQ 提取码:5tgy 二.安装Redis cd到当前解压目 ...

  6. BZOJ 3601 一个人的数论 (拉格朗日插值+莫比乌斯反演)

    题意 略 题解 orz Freopen的博客 CODE #pragma GCC optimize (3) #include <bits/stdc++.h> using namespace ...

  7. Educational Codeforces Round 75 (Rated for Div. 2) C. Minimize The Integer

    链接: https://codeforces.com/contest/1251/problem/C 题意: You are given a huge integer a consisting of n ...

  8. java对象转换

    对象转换: 对象的分层涉及到各个层级之间的对象转换(Entity2DTO , DTO2VO, VO2DTO,DTO2Entity等),传统的采用set/get 方法硬编码实现写的代码比较多:或者采用B ...

  9. 百度静态资源库CDN库, cdnjs库,引入JS

    不适用本地引入js文件,而使用其他服务器引入JS文件,1,减轻服务器压力2,速度快3,可以缓存 cdnjs库,更新比较快https://cdnjs.com/ cdn库 引入JS文件如:jquerybo ...

  10. 中检测到有潜在危险的 Request.Form 值。”

    添加富文本时  如果出现" 中检测到有潜在危险的 Request.Form 值.”   却不知道怎么排错时,就在HTML   或Web表格头部添加   ValidateRequest=&qu ...