转自:http://hi.baidu.com/mcj0127/blog/item/111a900777db06c87b89473c.html
SELECT FOR UPDATE 相关的知识
一个邮件发送的应用会每过一定的时间片去数据库中取未发的邮件然后发送邮件,成功后将数据库中邮件标识未发改为已发。
这个应用部署在websphere上,websphere采用是垂直克隆,有4个server,当4个server都开启的时候,就出现同时发4封相同的邮件给同一个用户。
这时,for update锁就可以解决这个问题!
1 状态解释
statement: 一个SQL语句。
session: 一个由ORACLE用户产生的连接,一个用户可以产生多个SESSION ,但相互之间是独立的。
transaction:所有的改变都可以划分到transaction里,一个transaction包含一个或多个SQL。当一个SESSION建立的时候就是一个TRANSACTION开始的时刻,此后 transaction的开始和结束由DCL控制,也就是每个COMMIT/ROLLBACK都标示着一个transaction的结束。
consistency:是对于statement级别而不是transaction级别来说的。sql statement 得到的数据都是以sql statement开始的IMAGE。
2 sql解释
LOCK的基本情况: update, insert ,delete, select ... for update会LOCK相应的ROW 。
只有一个TRANSACTION可以LOCK相应的行,也就是说如果一个ROW已经LOCKED了,那就不能被其他TRANSACTION所LOCK了。
LOCK由statement产生但却由TRANSACTION(commit,rollback)结尾,也就是说一个SQL完成后LOCK还会存在,只有在COMMIT/ROLLBACK后LOCK才会RELEASE。
SELECT.... FOR UPDATE [OF cols] [NOWAIT];
OF cols: SELECT cols FROM tables [WHERE...] FOR UPDATE [OF cols] [NOWAIT];
3 sql说明
a:关于OF
transaction A运行
select a.object_name,a.object_id from wwm2 a,wwm3 b where b.status='VALID' and a.object_id=b.object_id for update of a.status
则transaction B可以对b表wwm3的相应行进行DML操作,但不能对a表wwm2相应行进行DML操作.
反一下看看
transaction A运行
select a.object_name,a.object_id from wwm2 a,wwm3 b where b.status='VALID' and a.object_id=b.object_id for update of b.status
则transaction B可以对a表wwm2的相应行进行DML操作,但不能对b表wwm3相应行进行DML操作.
也就是说LOCK的是行,只是如果不加OF的话会对所有涉及的表LOCK的,加了OF后只会LOCK OF 字句所在的TABLE.
b:关于NOWAIT(如果一定要用FOR UPDATE,我更建议加上NOWAIT)
当有LOCK冲突时会提示错误并结束STATEMENT而不是在那里等待(比如:要查的行已经被其它事务锁了,当前的锁事务与之冲突,加上nowait,当前的事务会结束会提示错误并 立即结束 STATEMENT而不再等待).返回错误是"ORA-00054: resource busy and acquire with NOWAIT pecified"
注另外如下用法也值得推荐,应该酌情考虑使用。
1:FOR UPDATE WAIT 5
5秒后会提示ORA-30006: resource busy; acquire with WAIT timeout expired
2:FOR UPDATE NOWAIT SKIP LOCKED;
会提示no rows selected
3:TABLE LOCKS
LOCK TABLE table(s) IN EXCLUSIVE MODE [NOWAIT];
同样也是在transaction结束时才会释放lock。
4:DEADLOCK
transaction a lock rowA , then transaction b lock rowB
then transaction a tries to lock rowB, and transaction b tries to lock rowA
也就是说两个transaction都相互试图去lock对方已经lock的ROW,都在等待对方释放自己的lock,这样就使死锁。
deadlock也会有600提示。
分享到:
相关推荐
本文主要探讨了Oracle游标中的多表UPDATE行锁及其解决方案。 Oracle的锁定机制主要包括共享封锁、独占封锁和共享更新封锁。共享更新封锁是一种行级封锁,它允许用户在获取锁定的数据行上进行读取和更新,但阻止其他...
避免这种死锁的一种方法是在设计事务时遵循一定的顺序规则,例如,确保所有事务按照相同的顺序访问和修改数据,或者使用`FOR UPDATE SKIP LOCKED`(Oracle支持,但MySQL不直接支持)来跳过已锁定的行。另外,可以...
FOR UPDATE`语句产生,用于锁定查询到的行,防止其他用户修改。S锁允许共享读取,不允许修改。SX锁允许读取和独占写入,但不允许其他事务的X锁。X锁则是完全独占的,不允许其他任何事务访问。 锁定查询与处理: ...
首先,Oracle提供了一个SQL语句修饰符`FOR UPDATE`,用于在`SELECT`语句中锁定所选的行,以便在后续的事务中对这些行进行更新。这正是我们在标题和描述中提到的行锁实现方法。 1. **开启事务**:在对数据库进行任何...
FOR UPDATE`语句就是一种行级锁的用法,用于在更新数据前锁定选定的行,防止其他事务在此期间对这些行进行修改。当在查询条件中明确指定了主键,并且查询能够匹配到具体行时,InnoDB会实施行锁。例如: ```sql ...
- **TM锁**(表锁):在执行插入、更新、删除操作或`SELECT FOR UPDATE`时触发,目的是确保这些操作可以正常进行,同时阻止其他用户对表执行数据定义语言(DDL)操作。 - **TX锁**(事务锁/行锁):针对正在被修改的...
- 读操作一般不会阻塞写操作,除非使用`SELECT FOR UPDATE`。 #### 七、Oracle锁的具体类型 - **TM锁**:表级锁,用于保护表免受DDL操作的影响。 - **TX锁**:事务锁,用于保护正在修改的数据免受其他会话的干扰。...
ALWAYS表示在更新时总是获取行锁,INTENT仅在SELECT FOR UPDATE时获取行锁,但在更新时获取表锁。默认值为ALWAYS。 4. **shared_servers**: 这个参数定义了启动数据库实例后,用于共享服务器环境的服务器进程数量。...
SELECT * FROM stu_account t WHERE t.count_id=2 FOR UPDATE; ``` 这条语句锁定了 stu_account 表中 count_id 为 2 的行,以便其他会话不能对其进行操作。 ### 外键约束 在 Oracle 中,外键约束需要使用 ALTER ...
SELECT * FROM stu_account t WHERE t.count_id=2 FOR UPDATE; ``` #### 五、约束操作 约束是确保数据完整性和正确性的关键机制。 **1. 添加外键约束** **语法:** ```sql ALTER TABLE <table_name> ADD ...
6. **表锁和行锁**:TM锁在INSERT、UPDATE、DELETE和SELECT FOR UPDATE时触发,防止并发的DDL操作。TX锁则在修改数据时出现,阻止其他会话的修改。了解这些锁的模式(如Row Share、Row Exclusive等)有助于解决阻塞...
ALWAYS表示在更新后立即获取行锁,INTENT则只在执行SELECT FOR UPDATE时获取行锁,但在更新时获取表锁。默认值为ALWAYS,意味着在大多数情况下会进行行级锁定。 4. **shared_servers**: 指定了启动时为共享服务器...
示例代码展示了在没有锁定的情况下,可能存在的并发问题,以及如何通过`FOR UPDATE`子句获取行锁,确保在锁定状态下进行流水号的生成和更新,从而避免并发冲突。 综上所述,Oracle SQL培训讲义主要涵盖了SQL的优化...
删除HKDY_LOCAL_MACHINE/SOFTWARE/ODBC/ODBCINST.INI中除Microsoft ODBC for Oracle注册表键以外的所有含有Oracle的键。 删除环境变量中的PATHT CLASSPATH中包含Oracle的值。 删除“开始”/“程序”中所有...
如果设置为`INTENT`,则只在执行`SELECT FOR UPDATE`时获取行锁,但在实际更新时会获取表锁。 - **值范围**:`ALWAYS` | `DEFAULT` | `INTENT` - **默认值**:`ALWAYS` 4. **shared_servers** - **说明**:指定...
- **示例**: `SELECT * FROM stu_account tw WHERE tw.count_id = 2 FOR UPDATE;` - **解释**: 对`stu_account`表中`count_id`为2的记录施加行级锁,阻止其他事务对该记录进行修改直到当前事务结束。 #### 五、...
SELECT * FROM stu_account tw WHERE tw.count_id=2 FOR UPDATE; ``` - **说明**:此命令用于获取`stu_account`表中`count_id`为2的记录的行锁。当执行此命令时,其他用户或会话将无法修改该行直到当前会话释放锁...
TX锁代表事务锁,当一个事务首次执行数据更改(如INSERT、UPDATE、DELETE操作)或使用`SELECT...FOR UPDATE`语句进行查询时,该事务会获得一个TX锁,并且这个锁将持续到该事务结束(通过执行COMMIT或ROLLBACK操作...
如果设置为 INTENT,只有行锁将用于 SELECT FOR UPDATE,但在更新时将获取表锁。默认值为 ALWAYS。 Shared_servers 参数:该参数指定在启动例程后,要为共享服务器环境创建的服务器进程的数量。默认值为 1。 ...