Oracle锁定策略的总结
以下是对Oracle锁定策略的总结: · Oracle只在修改时才对数据加行级锁。正常情况下不会升级到块级锁或表级锁。 · 如果只是读数据,Oracle 绝不会对数据锁定。不会因为简单的读操作在数据行上锁定。 · 写入器(writer)不会阻塞读取器(reader)。换种说法
以下是对Oracle锁定策略的总结:
· Oracle只在修改时才对数据加行级锁。正常情况下不会升级到块级锁或表级锁。
· 如果只是读数据,Oracle 绝不会对数据锁定。不会因为简单的读操作在数据行上锁定。
· 写入器(writer)不会阻塞读取器(reader)。换种说法:读(read)不会被写(write)阻塞。这一点几乎与其他所有数据库都不一样。在其他数据库中,读往往会被写阻塞。
· 写入器想写某行数据,但另一个写入器已经锁定了这行数据,此时该写入器才会被阻塞。读取器绝对不会阻塞写入器。
需要了解以下内容:
· 事务是每个数据库的核心。
· 必要时才提交事务。事务的大小只应该根据业务逻辑来定。
· 只要需要,就应该尽可能长时间地保持对数据所加的锁。锁不是稀有资源。
· 在Oracle中,行级锁没有相关的开销,对1 000 000行锁定所需的资源数与对1行锁定所需的资源数完全相同,这是一个固定的常量。
· 不要以为锁升级“对系统更好”(例如,使用表锁而不是行锁)。在Oracle中,锁升级(lock escalate)对系统没有任何好处,不会节省任何资源。
· 可以同时得到并发性和一致性。
Oracle中主要有3类锁,具体是:
· DML锁(DML lock):DML代表数据操纵语言(Data Manipulation Language)。如SELECT、INSERT、UPDATE、MERGE和DELETE语句。DML锁机制允许并发执行数据修改。
· DDL锁(DDL lock):DDL代表数据定义语言(Data Definition Language),如CREATE和ALTER语句等。DDL锁可以保护对象结构定义。
· 内部锁和闩:Oracle 使用这些锁来保护其内部数据结构。
具体介绍-〉http://www.linuxidc.com/Linux/2012-01/51267.htm
锁
Oracle中的锁定一行的过程如下:
(1) 找到想锁定的那一行的地址。
(2) 到达那一行。
(3) 锁定这一行(如果这一行已经锁定,则等待锁住它的事务结束,除非使用了NOWAIT选项)。
仅此而已。由于闩为数据的一个属性,Oracle不需要传统的锁管理器。事务只是找到数据,如果数据还没有被锁定,则对其锁定。
需要注意,找到数据时,它可能看上去被锁住了,但实际上并非如此。在Oracle中对数据行锁定时,行指向事务ID的一个副本,事务ID存储在包含数据的块中,释放锁时,事务ID却会保留下来。这个事务ID是事务所独有的,表示了回滚段号、槽和序列号。事务ID留在包含数据行的块上,可以告诉其他会话:你“拥有”这个数据(并非块上的所有数据都是你的,只是你修改的那一行“归你所有”)。
另一个会话到来时,它会看到锁ID,由于锁ID表示一个事务,所以可以很快地查看持有这个锁的事务是否还是活动的。如果锁不活动,则允许会话访问这个数据。如果锁还是活动的,会话就会要求一旦释放锁就得到通知。因此,这就有了一个排队机制:请求锁的会话会排队,等待目前拥有锁的事务执行,然后得到数据。
如何用数据本身来管理锁定和事务信息?这是块开销的一部分。数据库块的最前面有一个“开销”空间(overhead),这里会存放该块的一个事务表,对于锁定了该块中某些数据的各个“实际”事务,在这个事务表中都有一个相应的条目。这个结构的大小由创建对象时CREATE语句上的两个物理属性参数决定:
· INITRANS:这个结构初始的预分配大小。对于索引和表,这个大小默认为2
· MAXTRANS:这个结构可以扩大到的最大大小。Oracle 10之后中,这个设置已经废弃了,MAXTRANS 总是255。
默认情况下,每个块最开始都有两个事务槽。一个块上同时的活动事务数受MAXTRANS值的约束,另外也受块上空间可用性的限制。
如果没有足够的空间来扩大这个结构,块上就无法得到255个并发事务,这时候就会等待,产生阻塞。
因此在频繁修改的表上就可能要增加INITRANS 设置,或者更常见的是,对于频繁修改的索引也可能需要这么做,因为索引块中的行一般比表中的行多。你可能需要增加PCTFREE或INITRANS,从而在块上提前预留足够的空间以应付可能的并发事务数。尤其是,如果你预料到块开始时几乎是满的(这说明块上没有空间来动态扩缩事务结构),则更需要增加PCTFREE或INITRANS。
可以做一个测试:
创建1个表,里面包含很多行,而且都存入一个块,使这个块一开始就比较满,只留下很少的空间,会限制事务表的增长。
[sql]
- create table t
- ( x int primary key,
- y varchar2(4000)
- );
- insert into t (x,y)
- select rownum, rpad('*',148,'*')
- from dual
- connect by level
可以通过以下语句,可以看到表中有46行,都在同一个块上。之所以选择148个字符,是因为再多一个字符,就需要2个块才能放下这46行。
如果你的Oracle当前的块大小是8K,就能得到同下面的测试相同的结果。
[sql]
- select length(y),
- dbms_rowid.rowid_block_number(rowid) blk,
- count(*), min(x), max(x)
- from t
- group by length(y), dbms_rowid.rowid_block_number(rowid);
- LENGTH(Y) BLK COUNT(*) MIN(X) MAX(X)
- ---------- ---------- ---------- ---------- ----------
- 148 291 46 1 46
下面通过让多个事务通过select ... for update nowait语句同时锁定这个块上的数据,第一个事务锁定第一行,第二个事务锁定第二行,以此类推。
如果需要等待,则会产生1个ORA-54 resource busy的错误,这说明已经用完了这个块上的事务表。
通过使用自治事务(AUTONOMOUS_TRANSACTION),可以使用一个会话就完成这个测试,不需要运行大量SQL*PLUS会话。
[sql]
- create or replace procedure do_update( p_n in number )
- as
- pragma autonomous_transaction;
- l_rec t%rowtype;
- resource_busy exception;
- pragma exception_init( resource_busy, -54 );
- begin
- select *
- into l_rec
- from t
- where x = p_n
- for update NOWAIT;
- do_update( p_n+1 );
- commit;
- exception
- when resource_busy
- then
- dbms_output.put_line( 'locked out trying to select row ' || p_n );
- commit;
- when no_data_found
- then
- dbms_output.put_line( 'we finished - no problems' );
- commit;
- end;
- /
执行这个过程,可以得到如下结果:
[sql]
- tony@ORA11GR2> exec do_update(1);
- locked out trying to select row 38
- PL/SQL 过程已成功完成。
阻塞
有5条常见的DML语句会产生阻塞::INSERT、UPDATE、DELETE、MERGE 和SELECT FOR UPDATE。
对于一个阻塞的SELECT FOR UPDATE,只需增加NOWAIT 子句,它就不会阻塞,会报告一个ORA-00054:Resource Busy的错误。
1)阻塞的Insert
最常见的情况是,有一个带主键的表,或者表上有惟一的约束,但有两个会话试图用同样的值插入一行。如果是这样,其中一个会话就会阻塞。
此外,如果使用外键,对子表的插入可能会阻塞,因为它所依赖的父表正在创建或删除。
2)阻塞的Update 和Delete
如果有未提交的事务在这一行上执行了Update或者Delete操作,那么就会产生阻塞。
3)阻塞的Merge
Merge只是Insert和UPDATE(10g之后还有Delete)的组合。因此结果同上。
死锁
如果两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁(deadlock)。
根据经验,导致死锁的头号原因是外键未加索引(第二号原因是表上的位图索引遭到并发更新)。
在以下两种情况下,Oracle在修改父表后会对子表加一个全表锁:
· 如果更新了父表的主键,由于外键上没有索引,所以子表会被锁住。
· 如果删除了父表中的一行,由于外键上没有索引,整个子表也会被锁住。
在 Oracle9i 及以上版本中,这些全表锁都是短期的,这意味着它们仅在DML 操作期间存在,而不是在整个事务期间都存在。即便如此,这些全表锁还是会导致很严重的锁定问题。
除了全表锁外,在下面情况下,未加索引的外键还可能带来性能问题。
· 如果有ON DELETE CASCADE,而且没有对子表加索引
例如,EMP是DEPT的子表,DELETE DEPTNO = 10 应该CASCADE(级联)至EMP[4]。如果EMP中的DEPTNO没有索引,那么删除DEPT表中的每一行时都会对EMP做一个全表扫描。这个全表扫描可能是不必要的,而且如果从父表删除多行,父表中每删除一行就要扫描一次子表。
· 从父表查询子表
例如利用DEPTNO查询EMP表是相当常见的。如果频繁地运行以下查询,没有索引会使查询速度变慢:
select * from dept, emp where emp.deptno = dept.deptno and dept.deptno = :X;
一般来说,仅当满足以下条件时不需要给外键加索引:
· 没有从父表删除行。
· 没有更新父表的惟一键/主键值(当心工具有时会无意地更新主键!)。
· 没有从父表联结子表
可以利用下面的脚本来查找没有加索引的外键。
[sql]
- column columns format a30 word_wrapped
- column tablename format a15 word_wrapped
- column constraint_name format a15 word_wrapped
- select table_name, constraint_name,
- cname1 || nvl2(cname2,','||cname2,null) ||
- nvl2(cname3,','||cname3,null) || nvl2(cname4,','||cname4,null) ||
- nvl2(cname5,','||cname5,null) || nvl2(cname6,','||cname6,null) ||
- nvl2(cname7,','||cname7,null) || nvl2(cname8,','||cname8,null)
- columns
- from ( select b.table_name,
- b.constraint_name,
- max(decode( position, 1, column_name, null )) cname1,
- max(decode( position, 2, column_name, null )) cname2,
- max(decode( position, 3, column_name, null )) cname3,
- max(decode( position, 4, column_name, null )) cname4,
- max(decode( position, 5, column_name, null )) cname5,
- max(decode( position, 6, column_name, null )) cname6,
- max(decode( position, 7, column_name, null )) cname7,
- max(decode( position, 8, column_name, null )) cname8,
- count(*) col_cnt
- from (select substr(table_name,1,30) table_name,
- substr(constraint_name,1,30) constraint_name,
- substr(column_name,1,30) column_name,
- position
- from user_cons_columns ) a,
- user_constraints b
- where a.constraint_name = b.constraint_name
- and b.constraint_type = 'R'
- group by b.table_name, b.constraint_name
- ) cons
- where col_cnt > ALL
- ( select count(*)
- from user_ind_columns i
- where i.table_name = cons.table_name
- and i.column_name in (cname1, cname2, cname3, cname4,
- cname5, cname6, cname7, cname8 )
- and i.column_position
- group by i.index_name
- )
- /
有一个办法可以快速定位导致子表被锁住的代码段。可以发出以下命令:
ALTER TABLE
现在,对父表的可能导致子表被锁住的任何UPDATE或DELETE都会接收到以下错误:
ERROR at line 1:
ORA-00069: cannot acquire lock -- table locks disabled for
这有助于跟踪到有问题的代码段,(比如,你认为并没有对父表的主键执行UPDATE或DELETE)。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Oracle データベース ログの保存期間は、次のようなログのタイプと構成によって異なります。 REDO ログ: 「LOG_ARCHIVE_DEST」パラメータで構成された最大サイズによって決定されます。アーカイブ REDO ログ: 「DB_RECOVERY_FILE_DEST_SIZE」パラメータで構成された最大サイズによって決まります。オンライン REDO ログ: アーカイブされず、データベースの再起動時に失われます。保持期間はインスタンスの実行時間と一致します。監査ログ: 「AUDIT_TRAIL」パラメータによって構成され、デフォルトで 30 日間保持されます。

Oracle データベースの起動シーケンスは次のとおりです。 1. 前提条件を確認します。 3. データベース インスタンスを起動します。 5. データベースに接続します。サービスを有効にします (必要な場合)。 8. 接続をテストします。

Oracle が必要とするメモリーの量は、データベースのサイズ、アクティビティー・レベル、および必要なパフォーマンス・レベル (データ・バッファー、索引バッファーの保管、SQL ステートメントの実行、およびデータ・ディクショナリー・キャッシュの管理) によって異なります。正確な量は、データベースのサイズ、アクティビティ レベル、および必要なパフォーマンス レベルによって影響されます。ベスト プラクティスには、適切な SGA サイズの設定、SGA コンポーネントのサイズ設定、AMM の使用、メモリ使用量の監視などが含まれます。

Oracle データベース サーバーのハードウェア構成要件: プロセッサ: マルチコア、少なくとも 2.5 GHz のメイン周波数 大規模なデータベースの場合は、32 コア以上が推奨されます。メモリ: 小規模データベースの場合は少なくとも 8 GB、中規模のデータベースの場合は 16 ~ 64 GB、大規模なデータベースまたは重いワークロードの場合は最大 512 GB 以上。ストレージ: SSD または NVMe ディスク、冗長性とパフォーマンスのための RAID アレイ。ネットワーク: 高速ネットワーク (10GbE 以上)、専用ネットワーク カード、低遅延ネットワーク。その他: 安定した電源、冗長コンポーネント、互換性のあるオペレーティング システムとソフトウェア、放熱と冷却システム。

Oracle は、次の手順で dbf ファイルを読み取ることができます。外部テーブルを作成し、その dbf ファイルを参照し、データを Oracle テーブルにインポートします。

Oracle データベースに必要なメモリの量は、データベースのサイズ、ワークロードの種類、同時ユーザーの数によって異なります。一般的な推奨事項: 小規模データベース: 16 ~ 32 GB、中規模データベース: 32 ~ 64 GB、大規模データベース: 64 GB 以上。考慮すべきその他の要素には、データベースのバージョン、メモリ最適化オプション、仮想化、ベスト プラクティス (メモリ使用量の監視、割り当ての調整) などがあります。

Oracle で 1 日に 1 回実行されるスケジュールされたタスクを作成するには、次の 3 つの手順を実行する必要があります。 ジョブを作成します。ジョブにサブジョブを追加し、そのスケジュール式を「INTERVAL 1 DAY」に設定します。ジョブを有効にします。

Oracle Databaseのメモリー要件は、データベースのサイズ、アクティブ・ユーザーの数、同時問合せ、有効な機能、およびシステム・ハードウェア構成の要素によって異なります。メモリ要件を決定する手順には、データベース サイズの決定、アクティブ ユーザー数の推定、同時クエリの理解、有効な機能の検討、システム ハードウェア構成の調査が含まれます。
