最近在工作中,用Spring的Quartz处理数据,由于数据量过大,就基于一个时间戳处理,但在部署时部署两个instance时,就出现了漏处理数据的问题。
分析发现,取数过程是一个事务,由于数据量比较大,数据取完后就交给另个Service处理。进一步分析,取数前获得时间戳,数据查询后,再将记录的最后一条记录提时间戳更新回时间戳(当然,实现应用比这复杂),因为获取数据的查询语句加了for update skip locked,所以之前一直相信,即使是多个instance也不会出现漏处理数据。
后来进一步分析,发现确实就是对for update skip locked理解有误导致的。
测试过程如下:
create table bj_test(id number not null); insert into bj_test values(1); insert into bj_test values(2); insert into bj_test values(3); commit;
实验一:连续两次执行同一个如下SQL语句:
select * from bj_test where rownum <= 1 for update skip locked;
结果如下:
实验二:再开启另一个SESSION窗口执行,却发现没有查询出任何数据。
分析如下:
因为同一个SESSION的锁定可以重复获取,所以实验一的第二条语句仍然能查询出同样的数据。而对于实验二的结果,我再做一个测试,即在另一个SESSION窗口执行:select * from bj_test for update skip locked;如下:
可以发现后面两条记录并没有被第一个SESSION锁定。那为何 select * from t where rownum <= 1 for update skip locked; 这个就 no rows 呢?其实是因为 for update 执行情况我们误解了。对于存在 for update 的SQL语句,Oracle首先在没有for Update的情况下选取出满足条件的记录。然后对选取出的记录进行lock。如果后skip locked,那么在锁定记录的时候对于满足条件的记录中已经被锁定的将会再次被筛选掉。
如下是for update skip locked 的执行过程:第一个SESSION 中锁定了第一条记录(Rownum <=1 ), 第二个SESSION 中依然按照 (Rownum<=1) 取到第一条ID=1的记录,在后继执行for update skip locked 的时候发现记录被锁定,则被筛选掉,那么最终结果就是no rows了。
总结:skip locked 是在SQL查询结果集的基础上进行二次筛选。
另外,增加一个知识点:使用了 For Update 查询的表上会放置一个MODE=3 的TM锁定,而不管该查询是否查询到数据。
解决问题及本文资料来源:http://www.itpub.net/thread-1060874-1-1.html
相关推荐
SELECT * FROM Table1 WHERE pkid = 1 FOR UPDATE SKIP LOCKED; ``` 如果`pkid=1`的行已被锁定,则此查询将不返回任何结果,而不会等待或报错。 #### 三、实际应用案例分析 假设我们有两个会话A和B,在会话A中...
避免这种死锁的一种方法是在设计事务时遵循一定的顺序规则,例如,确保所有事务按照相同的顺序访问和修改数据,或者使用`FOR UPDATE SKIP LOCKED`(Oracle支持,但MySQL不直接支持)来跳过已锁定的行。另外,可以...
1级锁主要应用于SELECT查询,通常不会出现在`v$locked_object`视图中,除非进行了特殊的SELECT操作,如`SELECT FOR UPDATE`。 2级锁包括`SELECT FOR UPDATE`、`LOCK TABLE ... FOR UPDATE`和`LOCK ROW SHARE SELECT...
解析oracle对select加锁的方法以及锁的查询一、oracle对select加锁方法 代码如下:create table...—session 1 模拟选中一个号码SQL> select * from test where a =1 for update skip locked; A B———- ———- 1
SELECT * FROM seats WHERE seat_no IN (2,3) AND booked = 'NO' FOR UPDATE SKIP LOCKED; -- 如果查询成功,更新座位状态 UPDATE seats SET booked = 'YES' WHERE seat_no IN (2,3); COMMIT; ``` 或者使用 `NOWAIT...
pg队列 ...pg-queue使用SELECT FOR UPDATE SKIP LOCKED来获取maxProcessingConcurrency作业,这样就不会阻止并发工作程序 如果需要FIFO处理,则只需要一个消耗实例PgQueue和maxProcessingConcurrenc
4. `FOR UPDATE SKIP LOCKED`则允许事务不等待被锁定的行,直接处理其他未被锁定的行。 行级锁的应用场景广泛,尤其在多用户同时访问大型数据库时,它可以有效地提高并发性能,同时保证数据的一致性和完整性。需要...
FOR UPDATE`支持`NOWAIT`和`SKIP LOCKED`选项,`NOWAIT`在遇到锁定时立即返回,而`SKIP LOCKED`则从结果集中排除被锁定的行。 5. **JSON处理增强**:引入了内联路径操作符`->>`,它等同于对`JSON_EXTRACT()`的结果...
// This would paint the TWPRichText, too - but TWPRichText is locked for repaint during this event AdvOfficePager1.PaintTo(Canvas, -WPRichText1.Left, -WPRichText1.Top); end; - HighlightTextColor ...
[FOR {UPDATE | NO KEY UPDATE | SHARE | KEY SHARE} [OF table_name, ...] [NOWAIT | SKIP LOCKED]] ``` - `SELECT` 后面跟随你要检索的列名或表达式,可以使用 `*` 代表所有列。 - `FROM` 后指定数据源,即你要...
This specification was developed in response to a perceived need for a standardized programming inter-face to digitizing tablets, three dimensional position sensors, and other pointing devices by a ...