Oracleデータベースのトランザクションのリトルルーキー

Oracleデータベースのトランザクション

1.トランザクションとは何ですか

データベーストランザクション内の作業の論理ユニットは、トランザクションによって行われたSQL文のセットの動作を保証するために、トランザクション機構によって、SQLステートメントのセットの1つまたは複数の関連動作によって行われるいずれかの成功全体の作業単位を完了実行操作、またはnoneが実行されています。

以下のような:オンライン転送データの一貫性を確保するためのトランザクションを処理するための一般的な使用です。

2.トランザクションのプロパティ

SQL92標準では4つの特性のデータベーストランザクションを定義します。

・アトミック(原子性):トランザクション内のすべてのSQL文は、全体の実装に含まれ、不可分、いずれかを実行したりしません。

・一貫性(一貫性):トランザクションが開始され、データベース内のデータは一貫して、データベース内のトランザクションデータの末尾にも一致している必要があります。

・アイソレーション(絶縁):データベースを参照によりクロスのその一貫性のないデータ操作コマンド実行結果には、複数の同時トランザクションを可能にすると同時に、その中にデータを読み書きし、変更する機能、分離が同時にトランザクションを実行防止することができます状態。

・永続的な(耐久性):それは、システムが故障した場合に遭遇した場合でも、トランザクションの終了は、データベースへの影響は永久的である場合を指す、データが失われることはありません。

動作取引するSQL文のセットは、データベース管理システムは、これはACIDプロパティで、動作のこのセット(原子性)、一貫性(整合性)、分離(単離)および永続性(耐久性)のアトミック性を保証しなければなりません。

3.データの異常

Oracleは、複数のトランザクションの同時実行をサポートしているので、それは次のようなデータの異常を表示します。

3.1ダーティリード

トランザクションがデータを変更したときにデータが第2のトランザクションで読み取るデータベースのデータで元の状態に戻されるように、データは、他のトランザクション、最初のトランザクションではなく、何らかの理由でデータ変更の除去のために読み出されますダーティリードと呼ばれる一貫性のないデータ、。

以下のような:変更されたトランザクションデータはT1であるが、まだちょうどこのデータの変更後、読み取りトランザクションT2に提出されていない、トランザクションがこの時間T1にロールバックされ、T2は、データを読み込む時間がダーティデータです。

3.2非反復可能読み取り

これは、最初のトランザクションで再び読み込まれたデータは、あなたがデータが変更された、これは非反復可能読み取りであることがわかりますとき、後のデータベース内のデータを読み込み、トランザクションに他のトランザクションの更新データを参照します。非反復可能読み取り結果は、前と、データの読み出しが二度同じトランザクションではありません後に発生します。

T1は、トランザクションT1、T2に続いて、行を読み込み、トランザクションだけ読んでレコードを変更し、その後、T1のクエリは、再び最初の読み取りと異なるレコードを検索:など。

3.3マジック読書

取引条件に基づいてデータを読み込む場合は、他のトランザクションは、再度データを読み込む最初のトランザクションは、検索の条件に応じて異なる行に戻り、同じテーブル内のデータを更新するには、これは魔法です読み。

以下のような:条件文を指定した読み取りトランザクションT1、結果セットを返します。この場合、トランザクションT2の行では、新しいレコードを挿入するだけでどこT1の条件を満たすように。T1は、再び同じ条件を使用してクエリを実行、結果セットは、この新しいレコードはファントム読み取りで、T2がレコードを挿入見ることができます。

より多くの孤立した設定の業務に関連するトランザクションに遭遇したこれらのトランザクション分離設定の異常が、あまりそれは異常があらわれたが、下の同時効果は、以下のトランザクション分離を設定し、より多くの異常同時効果が高いです。

トランザクション分離レベル4

データを読み出す際の不整合が発生する可能性のために、それは、SQL92標準でトランザクション分離の4つのレベルを定義しています。

分離レベル

ダーティー読み取り

非反復可能読み取り

マジック読書

非コミット読み取り(コミットされていない読み取り)

それはあります

それはあります

それはあります

コミット読み取り(コミット読み取り)

ノー

それはあります

それはあります

反復可能読み取り(反復可能読み取り)

ノー

ノー

それはあります

直列化(シリアルリード)

ノー

ノー

ノー

Oracleのデフォルトの分離レベルは、コミット読み込まれます。

コミットと、シリアライズ読み:Oracleがされている4つの分離レベルのうちの2つをサポートしています。また、Oralceも読み取りのみ書き込みとの分離レベルを読んで定義されました。

読み取り専用:トランザクションは、任意のデータベース操作文でデータを変更することはできません、それはSerializableのサブセットです。

書き込みを読む:それはデフォルトの設定では、このオプションを使用すると、トランザクション内の文へのアクセス権を持っているステートメントを修正しますが、多くの場合、使用しないことを意味します。

分離レベルを設定します

トランザクション分離レベルを設定します:

・SET TRANSACTIONの分離レベルREAD COMMITTEDは、

· SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

· SET TRANSACTION READ ONLY;

· SET TRANSACTION READ WRITE;

注意:这些语句是互斥的,不能同时设置两个或两个以上的选项。

设置单个会话的隔离级别:

· ALTER SESSION SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

· ALTER SESSION SET TRANSACTION ISOLATION SERIALIZABLE;

5. 事务控制命令

5.1 提交事务

在执行使用COMMIT语句可以提交事务,当执行了COMMIT语句后,会确认事务的变化,结束事务,删除保存点,释放锁。当使用COMMIT语句结束事务之后,其他会话将可以查看到事务变化后的新数据。

5.2 回滚事务

保存点(savepoint):是事务中的一点,用于取消部分事务,当结束事务时,会自动的删除该事务所定义的所有保存点。当执行ROLLBACK时,通过指定保存点可以回退到指定的点。

设置保存点:

sql> Savepoint a;

删除保存点:

sql> Release Savepoint a;

回滚部分事务:

sql> Rollback To a;

回滚全部事务:

sql> Rollback;

6. 数据库锁

数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改;加了共享锁的数据对象可以被其他事务读取,但不能修改。

6.1 锁分类

根据保护对象的不同,Oracle数据库锁可分为:

· DML lock(data locks,数据锁):用于保护数据的完整性。

· DDL lock(dictionary locks,字典锁):用于保护数据库对象的结构(例如表、视图、索引的结构定义)。

· Internal locks 和latches(内部锁与闩):保护内部数据库结构。

· Distributed locks(分布式锁):用于OPS(并行服务器)中。

· PCM locks(并行高速缓存管理锁):用于OPS(并行服务器)中。

在Oracle中最主要的锁是DML锁,DML锁的目的在于保证并发情况下的数据完整性。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

锁出现在数据共享的场合,用来保证数据的一致性。当多个会话同时修改一个表时,需要对数据进行相应的锁定。

锁有“共享锁”、“排它锁”,“共享排它锁”等多种类型,而且每种类型又有“行级锁” (一次锁住一条记录),“页级锁” (一次锁住一页,即数据库中存储记录的最小可分配单元),“表级锁” (锁住整个表)。

6.2 共享锁(S锁)

可通过lock table in share mode命令添加该S锁。在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出select …from for update命令对表添加RS锁。

6.3 排他锁(X锁)

可通过lock table in exclusive mode命令添加X锁。在该锁定模式下,其他用户不能对表进行任何的DML和DDL操作,该表上只能进行查询。

6.4 行级共享锁(RS锁)

通常是通过select … from for update语句添加的,同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出rollback命令将锁定解除。当表上添加了RS锁定以后,不允许其他事务对相同的表添加排他锁,但是允许其他的事务通过DML语句或lock命令锁定相同表里的其他数据行。

6.5 行级排他锁(RX锁)

当进行DML操作时会自动在被更新的表上添加RX锁,或者也可以通过执行lock命令显式的在表上添加RX锁。在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,但是不允许其他事务对相同的表添加排他锁(X锁)。

6.6 共享行级排他锁(SRX锁)

通过lock table in share row exclusive mode命令添加SRX锁。该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行DML操作,也不能添加共享锁。

上述几种锁模式中,RS锁是限制最少的锁,X锁是限制最多的锁。它们的兼容关系如下:

wps26

基本上所有的锁都可以由Oracle内部自动创建和释放,但是其中的DDL和DML锁是可以通过命令进行管理的,命令语法:

LOCK table_name IN

[row share][row exclusive][share][share row exclusive][exclusive] MODE [NOWAIT];

下图列出产生锁定模式的SQL语句:

wps27

当程序对所做的修改进行提交(Commit)或回滚(Rollback)后,锁住的资源便会得到释放,从而允许其他用户进行操作。如果两个事务,分别锁定一部分数据,而都在等待对方释放锁才能完成事务操作,这种情况下就会发生死锁

7. 数据库事务实现机制

几乎所有的数据库管理系统中,事务管理的机制都是通过使用日志文件来实现的,我们来简单介绍一下日志的工作方式。

当用户执行一条修改数据库的DML语句时,DBMS自动在日志文件中写一条记录,显示被这条语句影响的每一条记录的两个副本。一个副本显示变化前的记录,另一个副本显示变化后的记录。当日志写完之后,DBMS才实际对磁盘中的记录进行修改。

如果用户随后执行COMMIT语句,事务结束也被记录在事务日志中。如果用户执行ROLLBACK语句,DBMS检查日志,找出自事务开始以来被修改的记录“以前”的样子,然后使用这些信息恢复它们以前的状态,有效地撤销事务期间对数据库所做的修改。

如果系统出错,系统操作员通常通过运行DBMS提供的特殊恢复程序来复原数据库。恢复程序检查到事务日志末尾,查找故障之前没有被提交的事务。恢复程序回滚没有完全完成的事务,以便仅有被提交的事务反映到数据库中,而故障中正处理的事务被回滚。

事务日志的使用明显增加了更新数据库的开销。在实际中,主流商用DBMS产品使用的日志技术比上述描述的方案更复杂,用以减小这种开销。此外,事务日志通常被存储在高速磁盘驱动器中,不同于存储数据库的磁盘,以减小磁盘访问竞争。某些个人计算机DBMS产品允许关闭事务日志性能,以提高DBMS的性能。

8. 示例

银行转帐的例子是最经典的事务示例:

用户把钱从一个银行账号转账至另一个银行账号,需要将资金从一个银行账号中取出,然后再存入另一个银行账号中。理想来说,这两次操作都应该成功。但是,如果有错误发生,则两次操作都应该失败,否则的话,操作之后其中一个账号中的金额将会是错误的,整个操作过程应该是原子性的,两个操作都是一个原子事务操作的一部分。

示例:

-- 从账户一向账户二转账DECLARE

  v_money NUMBER(8, 2); -- 转账金额

  v_balance account.balance%TYPE; -- 账户余额

BEGIN

  v_money := &转账金额; -- 输入转账金额

-- 从账户一减钱 

UPDATE account SET balance = balance - v_money WHERE id=&转出账户

  RETURNING balance INTO v_balance;

IF SQL%NOTFOUND THEN

    RAISE_APPLICATION_ERROR(-20001, '没有该账户:'||&转出账户);

END IF;

IF v_balance < 0 THEN

    RAISE_APPLICATION_ERROR(-20002, '账户余额不足');

END IF;

-- 向账户二加钱

UPDATE account SET balance = balance + v_money WHERE id=&转入账户;

IF SQL%NOTFOUND THEN

    RAISE_APPLICATION_ERROR(-20001, '没有该账户:'||&转入账户);

END IF;

-- 如果没有异常,则提交事务

COMMIT;

  DBMS_OUTPUT.PUT_LINE('转账成功');

  EXCEPTION

WHEN OTHERS THEN

ROLLBACK; -- 出现异常则回滚事务

      DBMS_OUTPUT.PUT_LINE('转账失败:');

      DBMS_OUTPUT.PUT_LINE(SQLERRM);END;

おすすめ

転載: www.cnblogs.com/czg-0705/p/11391978.html