`
loookto
  • 浏览: 14227 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
最近访客 更多访客>>
社区版块
存档分类
最新评论

转:Select For Update行级锁定

阅读更多
Oracle的Select For Update语句可以实现在读取数据后马上锁定相关资源,防止被其他session修改数据的目的。也就是我们常常谈到的“悲观锁定”(现实应用开发中,使用悲观锁定的情况少之又少,也许是因为乐观锁定的实现更加灵活和便捷的缘故)。
这个小文儿做一个小小的实验,来看看Select For Update语句实现的行级锁定

1.创建实验表table_sfu,并初始化三条数据
sec@ora10g> create table table_sfu (a number);

Table created.

sec@ora10g> insert into table_sfu values (1);

1 row created.

sec@ora10g> insert into table_sfu values (2);

1 row created.

sec@ora10g> insert into table_sfu values (3);

1 row created.

sec@ora10g> commit;

Commit complete.

sec@ora10g> select * from table_sfu;

         A
----------
         1
         2
         3

2.使用Select For Update语句得到第一条数据
sec@ora10g> select * from table_sfu where a = 1 for update;

         A
----------
         1

3.查看一下现在系统中的锁定情况,152会话(即上面语句所在的会话)获得了一个TX锁和一个TM锁了,锁定的表就是TABLE_SFU
sec@ora10g> @lock

lock        lock
holder    holder         lock             lock request       blocked
username  sessid SERIAL# type    id1  id2 mode    mode BLOCK  sessid
-------- ------- ------- ---- ------ ---- ---- ------- ----- -------
SEC          152   14985 TM    15396    0    3       0     0
SEC          152   14985 TX   327722 1790    6       0     0
             164       1 TS        3    1    3       0     0
             165       1 CF        0    0    2       0     0
             165       1 RS       25    1    2       0     0
             165       1 XR        4    0    1       0     0
             166       1 RT        1    0    6       0     0

7 rows selected.

sec@ora10g> col OWNER for a6
sec@ora10g> col OBJECT_NAME for a10
sec@ora10g> select OWNER,OBJECT_NAME,OBJECT_ID,OBJECT_TYPE from dba_objects where object_id = '15396';

OWNER  OBJECT_NAM  OBJECT_ID OBJECT_TYPE
------ ---------- ---------- -------------------
SEC    TABLE_SFU       15396 TABLE

4.另外新打开一个session,执行以下修改任务
sec@ora10g> update table_sfu set a = 100 where a = 1;
OK,效果出现了,这里出现了“锁等待”现象,原因就是因为在第一个session中使用Select For Update语句锁定了第一行数据,不允许其他的session对它修改。

5.这时系统中锁定情况如下,可以看到第一个session(session id是152)会话锁定了第二个session(session id是145)会话的事务
sec@ora10g> @lock

lock        lock
holder    holder         lock             lock request       blocked
username  sessid SERIAL# type    id1  id2 mode    mode BLOCK  sessid
-------- ------- ------- ---- ------ ---- ---- ------- ----- -------
SEC          145   11388 TM    15396    0    3       0     0
SEC          152   14985 TM    15396    0    3       0     0
SEC          152   14985 TX   327722 1790    6       0     1     145
             164       1 TS        3    1    3       0     0
             165       1 CF        0    0    2       0     0
             165       1 RS       25    1    2       0     0
             165       1 XR        4    0    1       0     0
             166       1 RT        1    0    6       0     0

8 rows selected.

6.因为仅仅是锁定了第一条数据,所以其他记录可以顺利的进行修改,如下
sec@ora10g> update table_sfu set a = 200 where a = 2;

1 row updated.

sec@ora10g> commit;

Commit complete.

7.解锁方式:commit或rollback后即完成锁定的接触

8.反过来思考一下,如果Select For Update与要锁定的行已经在其他session中完成了修改,再执行回出现什么效果呢?这个很显然,同样的会出现“锁等待”的现象,不过我想强调的是,这里可以使用nowait和wait选项来进行“探测”待锁定行是否可被锁定
实验效果如下:
第一个session:
sec@ora10g> update table_sfu set a = 100 where a = 1;

1 row updated.

第二个session:
sec@ora10g> select * from table_sfu where a = 1 for update;
此处是“锁等待”效果

sec@ora10g> select * from table_sfu where a = 1 for update nowait;
select * from table_sfu where a = 1 for update nowait
              *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified
这里提示了错误,原因就是已经“探测”到该行已经被别的事务锁定,这里无法对其进行锁定操作。

sec@ora10g> select * from table_sfu where a = 1 for update wait 3;
select * from table_sfu where a = 1 for update wait 3
              *
ERROR at line 1:
ORA-30006: resource busy; acquire with WAIT timeout expired
这里提示的错误内容与上面的一样,不过这里wait 3表示,我等你三秒的时间,如果三秒过后还无法锁定资源,就报错。

9.更进一步,请参考Oracle官方文档中相关的描述
《for_update_clause ::=》
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#i2126016
语法格式:
FOR UPDATE
[ OF [ [ schema. ]
       { table | view } . ]column
       [, [ [ schema. ]
            { table | view } . ]column
       ]...
]
[ NOWAIT | WAIT integer ]

同上述连接,搜索关键字“for_update_clause”可以得到每个选项的解释信息

《Using the FOR UPDATE Clause: Examples 》
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#i2130052

10.小结
上面的小实验展示了一下Select For Update行级锁定的效果,Oracle的锁定机制还是非常的灵活的,基于这个锁定可以实现“悲观锁定”。
分享到:
评论

相关推荐

    for_update_和_for_update_nowait_的区别

    `FOR UPDATE`是Oracle中用于实现行级锁定的一种机制。当执行包含`FOR UPDATE`子句的`SELECT`语句时,Oracle会在所选择的行上放置排他锁(exclusive lock),即X锁,这种锁允许持有者读写数据,但阻止其他事务读写...

    mysql SELECT FOR UPDATE语句使用示例

    FOR UPDATE`: 对查询结果进行行级锁定,直到事务提交。 - `UPDATE`: 更新数据。 - `COMMIT`: 提交事务,解锁被锁定的行。 - `ROLLBACK`: 回滚事务,释放锁定。 2. **行级锁定与表级锁定**: - **行级锁定(Row...

    Mysql 数据库死锁过程分析(select for update)

    FOR UPDATE`锁定的行,那么它将等待锁被释放,而`SELECT ... FOR UPDATE`的事务在等待`UPDATE`事务完成,从而形成死锁。 在提供的示例中,通过设置不同的`IsSuccess`值,展示了如何通过索引锁定导致死锁。当`...

    MySQL锁类型以及子查询锁表问题、解锁1

    FOR UPDATE`语句就是一种行级锁的用法,用于在更新数据前锁定选定的行,防止其他事务在此期间对这些行进行修改。当在查询条件中明确指定了主键,并且查询能够匹配到具体行时,InnoDB会实施行锁。例如: ```sql ...

    mysql事务select for update及数据的一致性处理讲解

    如果不使用事务和`FOR UPDATE`,可能存在如下风险:在`SELECT`之后到`UPDATE`之前,其他事务可能已经将库存减少到0,但我们的事务仍然错误地更新了数量。为了解决这个问题,可以使用如下事务: 1. `SET AUTOCOMMIT=...

    MySQL中的行级锁定示例详解

    MySQL中的行级锁定是数据库管理并发事务的一种策略,它允许多个事务同时访问同一表的不同行,从而提高了系统并发性能。行级锁定主要分为两种类型:共享锁(Shared Locks)和排他锁(Exclusive Locks)。 共享锁,...

    你真的懂for update?(面试必备)

    **保证线程安全的新方法:For Update** For Update是一种行级锁,它允许当前事务在查询并锁定数据行后,其他事务只能读取,而不能进行更新操作,直到当前事务提交或回滚。这种方式避免了并发事务间的冲突,确保了...

    ORACLE锁定机制

    1. 行级锁:Oracle主要使用行级锁定来最小化锁定范围,提高并发性能。行级锁分为共享锁(S锁)和独占锁(X锁)。共享锁允许其他事务读取行,但阻止写入;独占锁则阻止其他事务读取或写入。 2. 表级锁:在特定情况下...

    检测并解决冲突检测并解决冲突检测并解决冲突

    要解决这种冲突,我们可以使用 Oracle 的并发控制机制,例如使用 SELECT FOR UPDATE 语句来锁定记录,或者使用乐观锁机制来解决冲突。我们也可以使用 Oracle 的事务隔离级别来控制事务之间的交互。 在实际应用中,...

    SQLITE数据库 UPDATE慢

    5. **锁竞争**:SQLite采用行级锁定,但在某些情况下仍可能出现锁竞争。当多用户同时更新同一数据时,会引发等待和锁冲突。合理规划并发访问,或者在设计数据库时考虑并发控制,有助于减轻锁竞争。 6. **查询优化**...

    MySQL中SELECT+UPDATE处理并发更新问题解决方案分享

    为了防止这种情况,我们可以使用InnoDB的行级锁定机制。 InnoDB支持两种锁:读共享锁(Read Shared Lock)和写独占锁(Write Exclusive Lock)。读共享锁允许其他事务读取数据,但不允许修改;写独占锁则阻止其他...

    老二牛车第三章理论课锁和表分区.pdf

    - `SELECT...FOR UPDATE`语句允许用户锁定多条记录进行更新,并且只有发起该查询的用户可以编辑这些记录,直至事务提交或回滚。 2. **表级锁**(Table-Level Locks) - **定义**:锁定整个表,限制其他用户对该表...

    Oracle行级锁的特殊用法简析

    同时,SELECT...FOR UPDATE语句会为选定的行施加排他锁,使得只有发起查询的事务可以修改这些行,其他事务则被阻止进行修改,但仍然可以读取。 SELECT...FOR UPDATE语句的使用具有一定的灵活性。例如,你可以通过OF...

    ORACLE游标中的多表UPDATE行锁讨论.pdf

    Oracle数据库在处理并发操作时,行级锁定机制起到了至关重要的作用,特别是在涉及多表更新的场景下。本文主要探讨了Oracle游标中的多表UPDATE行锁及其解决方案。 Oracle的锁定机制主要包括共享封锁、独占封锁和共享...

    Oracle事务、锁表查询及相关实用查询SQL语句

    SELECT * FROM table_name WHERE condition FOR UPDATE; ``` - **表级锁定**: ```sql LOCK TABLE table_name IN EXCLUSIVE MODE; ``` #### 三、实用查询SQL语句 下面是一些常用的Oracle查询SQL语句,可以...

    大型数据库触发器介绍

    - **读的不可重复性**:SELECT FOR UPDATE语句用于锁定预期要修改的记录,防止其他事务在同一时间进行修改,常用于读-修改-写操作。 - **锁的相互作用**:不同类型的锁有不同的兼容性,例如,更新操作会加RX锁和X锁...

    oracle解锁

    SELECT * FROM TEST WHERE ID = 10 FOR UPDATE NOWAIT; ``` 则会话A将立即获得锁定,否则将报错ORA-00054,表明没有立即获得锁定。 #### 六、更新锁定 假设会话A已经锁定了ID为10的记录,此时如果会话B尝试执行...

Global site tag (gtag.js) - Google Analytics