数据库中Select For update语句的解析
——————————— Oracle —————————————————–
Oracle 的for update行锁
键字: oracle 的for update行锁
SELECT…FOR UPDATE 语句的语法如下:
SELECT … FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED];
其中:
OF 子句用于指定即将更新的列,即锁定行上的特定列。
WAIT 子句指定等待其他用户释放锁的秒数,防止无限期的等待。
“使用FOR UPDATE WAIT”子句的优点如下:
1防止无限期地等待被锁定的行;
2允许应用程序中对锁的等待时间进行更多的控制。
3对于交互式应用程序非常有用,因为这些用户不能等待不确定
4 若使用了skip locked,则可以越过锁定的行,不会报告由wait n 引发的‘资源忙’异常报告
示例1:
create table t(a varchar2(20),b varchar2(20));
insert into t values(‘1’,’1’);
insert into t values(‘2’,’2’);
insert into t values(‘3’,’3’);
insert into t values(‘4’,’4’);
现在执行如下操作:
在plsql develope中打开两个sql窗口,
在1窗口中运行sql
select * from t where a=’1’ for update;
在2窗口中运行sql1
1. select * from t where a=’1’; 这一点问题也没有,因为行级锁不会影响纯粹的select语句
再运行sql2
2. select * from t where a=’1’ for update; 则这一句sql在执行时,永远处于等待状态,除非窗口1中sql被提交或回滚。
如何才能让sql2不等待或等待指定的时间呢? 我们再运行sql3
3. select * from t where a=’1’ for update nowait; 则在执行此sql时,直接报资源忙的异常。
若执行 select * from t where a=’1’ for update wait 6; 则在等待6秒后,报 资源忙的异常。
如果我们执行sql4
4. select * from t where a=’1’ for update nowait skip Locked; 则执行sql时,即不等待,也不报资源忙异常。
现在我们看看执行如下操作将会发生什么呢?
在窗口1中执行:
select * from t where rownum<=3 nowait skip Locked;
在窗口2中执行:
select * from t where rownum<=6 nowait skip Locked;
select for update 也就如此了吧,insert、update、delete操作默认加行级锁,其原理和操作与select for update并无两样。
select for update of,这个of子句在牵连到多个表时,具有较大作用,如不使用of指定锁定的表的列,则所有表的相关行均被锁定,若在of中指定了需修改的列,则只有与这些列相关的表的行才会被锁定。
实例2
elect * from t for update 会等待行锁释放之后,返回查询结果。
select * from t for update nowait 不等待行锁释放,提示锁冲突,不返回结果
select * from t for update wait 5 等待5秒,若行锁仍未释放,则提示锁冲突,不返回结果
select * from t for update skip locked 查询返回查询结果,但忽略有行锁的记录
——————————— MySQL —————————————————–
MySQL中select * for update锁表的问题
页级:引擎 BDB。
表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行
行级:引擎 INNODB , 单独的一行记录加锁
表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作。如果你是写锁,则其它进程则读也不允许
行级,,仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作。
页级,表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。
MySQL 5.1支持对MyISAM和MEMORY表进行表级锁定,对BDB表进行页级锁定,对InnoDB表进行行级锁定。
对WRITE,MySQL使用的表锁定方法原理如下:
如果在表上没有锁,在它上面放一个写锁。
否则,把锁定请求放在写锁定队列中。
对READ,MySQL使用的锁定方法原理如下:
如果在表上没有写锁定,把一个读锁定放在它上面
否则,把锁请求放在读锁定队列中。
InnoDB使用行锁定,BDB使用页锁定。对于这两种存储引擎,都可能存在死锁。这是因为,在SQL语句处理期间,InnoDB自动获得行锁定和BDB获得页锁定,而不是在事务启动时获得。
MySQL中select * for update锁表的问题
由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料表单给锁住)。
举个例子:
假设有个表单products ,里面有id跟name二个栏位,id是主键。
例1: (明确指定主键,并且有此笔资料,row lock)
SELECT * FROM products WHERE id=’3’ FOR UPDATE;
SELECT * FROM products WHERE id=’3’ and type=1 FOR UPDATE;
例2: (明确指定主键,若查无此笔资料,无lock)
SELECT * FROM products WHERE id=’-1’ FOR UPDATE;
例2: (无主键,table lock)
SELECT * FROM products WHERE name=’Mouse’ FOR UPDATE;
例3: (主键不明确,table lock)
SELECT * FROM products WHERE id<>’3’ FOR UPDATE;
例4: (主键不明确,table lock)
SELECT * FROM products WHERE id LIKE ‘3’ FOR UPDATE;
注1: FOR UPDATE仅适用于InnoDB,且必须在交易区块(BEGIN/COMMIT)中才能生效。
注2: 要测试锁定的状况,可以利用MySQL的Command Mode ,开二个视窗来做测试。
在MySql 5.0中测试确实是这样的
另外:MyAsim 只支持表级锁,InnerDB支持行级锁
添加了(行级锁/表级锁)锁的数据不能被其它事务再锁定,也不被其它事务修改(修改、删除)
是表级锁时,不管是否查询到记录,都会锁定表
关于Oracle中for update的补充说明:
分成两类:加锁范围子句和加锁行为子句
加锁范围子句:
在select…for update之后,可以使用of子句选择对select的特定数据表进行加锁操作。默认情况下,不使用of子句表示在select所有的数据表中加锁
加锁行为子句:
当我们进行for update的操作时,与普通select存在很大不同。一般select是不需要考虑数据是否被锁定,最多根据多版本一致读的特性读取之前的版本。加入for update之后,Oracle就要求启动一个新事务,尝试对数据进行加锁。如果当前已经被加锁,默认的行为必然是block等待。使用nowait子句的作用就是避免进行等待,当发现请求加锁资源被锁定未释放的时候,直接报错返回。
在日常中,我们对for update的使用还是比较普遍的,特别是在如pl/sql developer中手工修改数据。此时只是觉得方便,而对for update真正的含义缺乏理解。
For update是Oracle提供的手工提高锁级别和范围的特例语句。Oracle的锁机制是目前各类型数据库锁机制中比较优秀的。所以,Oracle认为一般不需要用户和应用直接进行锁的控制和提升。甚至认为死锁这类锁相关问题的出现场景,大都与手工提升锁有关。所以,Oracle并不推荐使用for update作为日常开发使用。而且,在平时开发和运维中,使用了for update却忘记提交,会引起很多锁表故障。
那么,什么时候需要使用for update?就是那些需要业务层面数据独占时,可以考虑使用for update。场景上,比如火车票订票,在屏幕上显示邮票,而真正进行出票时,需要重新确定一下这个数据没有被其他客户端修改。所以,在这个确认过程中,可以使用for update。这是统一的解决方案方案问题,需要前期有所准备。
数据库中Select For update语句的解析相关推荐
- 如何找出MySQL数据库中的低效SQL语句
面对业务的迅猛发展,DBA的一项重要工作就是及时发现数据库中的低效SQL语句,有的可以立刻着手解决(比如缺少合适的索引),有的需要尽快反馈给开发人员进行修改. MySQL数据库有几个配置选项可以帮助我 ...
- 【转】MySQL中select * for update锁表的问题
MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例 ...
- oracle nvarchar2问题,Oracle数据库中,使用case语句,遇到VARCHAR2与NVARCHAR2问题
问题: 在有sqlserver数据库迁移至Oracle数据库时,遇到将VARCHAR2付给NVARCHAR2问题 原sql CASE A .kindCode WHEN '2321034' THEN'0 ...
- sql server中同时执行select和update语句死锁问题
原始出处 http://oecpby.blog.51cto.com/2203338/457054 最近在项目中使用SqlServer的时候发现在高并发情况下,频繁更新和频繁查询引发死锁.通常我们知道如 ...
- mysql begin end 用法_数据库:Mysql中“select ... for update”排他锁分析
作者:志波同学来源:https://mp.weixin.qq.com/s/8uH-7TD9ZRG4NCya80mOHg Mysql InnoDB 排他锁 用法:select - for update; ...
- mysql update 排他锁_数据库:Mysql中“select ... for update”排他锁分析
Mysql InnoDB 排他锁 用法: select - for update; 例如:select * from goods where id = 1 for update; 排他锁的申请前提:没 ...
- 数据库:Mysql中“select ... for update”排他锁分析
Mysql InnoDB 排他锁 用法: select - for update; 例如:select * from goods where id = 1 for update; 排他锁的申请前提:没 ...
- Select For update语句浅析
Select -forupdate语句是我们经常使用手工加锁语句.通常情况下,select语句是不会对数据加锁,妨碍影响其他的DML和DDL操作.同时,在多版本一致读机制的支持下,select语句也不 ...
- php mysql update语句_mysql SELECT FOR UPDATE 语句
MySQL 使用SELECT - FOR UPDATE 做事务写入前的确认 以MySQL 的InnoDB 为例,预设的Tansaction isolation level 为REPEATABLE R ...
最新文章
- iOS base64 MD5
- Spring教程--IOC(控制反转)详解
- 美团点评数据产品专家冷戈:如何利用数据提高用户体验
- Mongodb 笔记04 特殊索引和集合、聚合、应用程序设计
- tcp 服务端如何判断客户端断开连接
- MySQL源码包编译安装
- android webview测速,学习分享,echarts模拟宽带测速效果 附Demo演示地址!!
- 分析师:Apple不会在2022年发布OLED iPad Air
- DL_C1_week4_2(build a deep neural network 2)
- APP测试——经典面试题分享
- 移动硬盘提示格式化的处理
- win2008安装mysql8.0
- 青龙脚本合集(不定期更新版)
- 在Edge浏览器中设置编码方式
- 电脑微软商店消失解决办法
- 程序猿段子:程序员崩溃很简单,改三次需求即可
- 韩顺平老师B站MySQL
- 导入Android 项目,按钮点击事件,添加okhttp三合一,android动态修改标题
- 五一影视圈的神仙打架,揭开了内容市场暗自角力的真相
- C# System.Data.Sqlite.dll 的注意事项
热门文章
- JQuery语法 JQuery对象与原生对象互转 文档就绪函数与window.onload的区别
- 理解基本包装类型Number,String,Boolean
- 预告:公共语言运行库(CLR)开发系列课程(4):COM Interop进阶
- VS2010配置清单
- 大数据之-Hadoop_环境搭建_JDK安装---大数据之hadoop工作笔记0017
- STM32工作笔记0094---音乐播放器实验
- C#.Net工作笔记014---C#中internal的意思
- java面试要点---oracle,mysql,DB2数据库的分页
- vc 2010 下打包dll 的问题
- SuSe防火墙iptables配置