トランザクション、トランザクションの同時実行性、トランザクション、読取り一貫性の特性

1トランザクションデータベースとは何ですか?
1.1 A代表的なシーン総務
そこプロジェクトでは、どこかの出来事、または構成された業務を開くのだろうか?それはまた、この方法で注釈されているかどうか
これは、構成セクションであります
<TX:アドバイスID = " txAdvice "トランザクション・マネージャー= " のTransactionManager " >
  <TX:属性> <TX:メソッド名= " *保存" rollback-  = " Throwableを" />
  <TX:メソッド名= " *追加" rollback-  = " Throwableを" />
  <TX:メソッド名= " *送信" rollback-  = " Throwableを" />
  <TX:メソッド名= " 挿入* " rollback-  = " Throwableを" />     
  </ TX:属性> 
</ TX:アドバイス>
このような注文として、受注は、テーブルの上に私たちはこれらの操作を行う必要があり、この時間はそう、テーブル、テーブルの資金調達、物流、を操作します
単一のトランザクションで完了しました。複数のテーブルを含む場合は、ビジネス・プロセス・オペレーション、そして我々は、彼らがいずれかであることを望みます
すべての成功したか成功していない、この時間は、私たちは、取引を可能にします。
このような操作内の銀行振込など非常に一般的であるシステムの金融取引の構成では、我々はそれを置く場合
増加は、単に実際よりよくこれ以上、当然の状況(他の口座に残高を減らし、口座残高と解釈します
コンプレックス)、これら2つのアクションが、それ以外の場合は、銀行の経理部門の原因となります、同時に同時成功または失敗でなければなりません
ヘッドの不均衡。
トランザクションの1.2定義
トランザクションとは何ですか?
ウィキペディアの定義:トランザクション論理ユニットプロセスである(DBMS)を実行するデータベース管理システム
データベース操作の有限シーケンス。
そしてまず、それは作業データベースの最小単位である、二つの重要なポイントがあり、細分化されていません。最初の
2つ、またはそれは、削除、更新インサートを含む、DML文のシリーズが含まれていてもよいです。
(シングルDDL(ドロップを作成)し、DCL(助成REVOKE)が業務を持つことになります)
1.3どのようなストレージエンジンは、トランザクションをサポート
一日に来る私たちの最初のレッスンでは、InnoDBはトランザクションをサポートし、これはそれがデフォルトのストレージエンジンとなっています
重要な理由: 
https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html
もう一つは、NDBです。
4つのプロパティ1.4総務
トランザクションの4つの特徴:ACID。
まず、原子、原子性、我々は今言った、我々はログを意味し、分割することはできませんされて
ライブラリの一連の操作によると、いずれかのすべての成功またはすべて失敗し、または部分的な成功の部分的な損失が低く表示されます
失う事態。転送シナリオでは、例えば、口座残高が、口座の対応する増加、両者を減少します
同時に、成功または失敗を与えている間。
それはすべて失敗してみましょうか?我々が持っているこの時間は、ロールバックされます。
アンドゥログによってInnoDB内で達成されるアトミックは、その値(変更前の論理データを記録します
一連のログ)に異常が発生すると、アンドゥログは、ロールバック動作を実現するために使用することができます。
一貫性のある一貫した第二には、、、破損していないデータベースの整合性制約を意味し、トランザクションの実行
前と後のデータが正当な状態です。主キーは一意である必要があります例えば、フィールドの長さは、要件を満たすことができます。
独自のデータベースの整合性制約に加えて、ユーザー定義の整合性があります。
例えば、このシーンの転送は、口座残高が1000減らすために、Bの口座残高は、500だけで、この時間を増加しました
両方の操作が成功しているので待って、原子の私達の定義によれば、それはアトミックを満たすことであるが、それはしていません
ミートの一貫性は、それはアカウントの不均衡につながるため。
別のケースでは、口座残高が、この時間は転送が成功した場合、口座残高がAになり、ゼロであります
-1000それは原子性を満たしているが、我々はそう、デビットカードの残高がゼロ未満にはできませんことを知っているが、
また、一貫性の違反。整合性は、通常、ユーザ定義の制御コードです。
第三に、分離、分離、我々はデータベースの多くがあるだろうしたトランザクションを、定義した後
同時に、私たちの業務は、同じテーブルを操作するために、データの同じ行に、いくつかの干渉や同時動作を生成するためにバインドされて、
だから、これらの取引の数、同時手術台または行で隔離の私達の定義は、それは徹底的にする必要があります
明は、相互に非干渉します。このように、我々は最終的には業務データの一貫性を確保します。
最後は、それが何を意味するの耐久性、永続性情勢、持続性と呼ばれていますか?私達のデータベースのいずれか
オペレーション、追加および削除は、限り、トランザクションが正常にコミットされると、その結果は永久的で、私たちのシステムはぐずぐずすることができないので、
サーバーのデータベースをマシンまたは再起動し、元の状態に復元します。これは、トランザクションの耐久性です。
どれだけ持続的な達成するために?達成されたものを介してデータベースクラッシュ回復(クラッシュセーフ)?
持続性は、REDOログダブル、ダブルライトバッファ書き込みによって達成され、我々はデータを操作し、
REDOログを記録中に例外がブラシプレートの前に発生した場合、我々は最初に、メモリ・バッファ・プールの内側に書き込みます
再起動は、REDOログの内容を読み取ることができた後に永続的なデータを確保し、ディスクに書き込まれます。
もちろん、自身が破壊されていないデータページの正常な回復の前提は、二重による書き込みバッファ完了します
(二重書き込み)保证。
アトミック、分離性、耐久性、そして最終的には一貫性を達成することです。
それは総務が表示されます1.5データベース
私たちは、このようなツールのNavicatの内部を操作するために行くかどうか、またはパス内の私達のJavaコードで
最終的にAを送信して、実際に、または@TransactionalコメントやAOPの設定で動作するAPI
実行するには、データベースへの指示、JavaのJDBCは、ちょうどこれらのコマンドまでのパッケージを置きます。
私たちの動作環境で見てみましょう。バージョン(5.7)、ストレージエンジン(InnnoDB)、トランザクション分離
レベル(RR)。 
選択したバージョンを();
以下のような変数を示して%エンジン%を;
表示さグローバルような変数tx_isolationを
アップデートの実行時間などAステートメントは、それが右の問題に?
学生の更新のSET SNAME = ' 猫の夫111 ' のID = 1。 ;
実際には、それが自動的にトランザクションを開き、提出され、その最終的にディスクに書き込まれます。
これは、トランザクションをオープンする最初の方法で、自動的に開き、自動的に提出します。
2つのレベルに分割されたパラメータのInnoDB自動コミット内部(セッションレベルとグローバル
レベル)。 
以下のような変数を示して自動コミットを ;
デフォルト値はONです。このパラメータは、自動コミットは、それが何を意味するのでしょうか?かどうかを自動的に提出します。それはだ場合
値が上真/で、我々はデータを操作するとき、そして、それは自動的にトランザクションを開き、自動的にトランザクションをコミットします。
私たちは偽/オフに設定でautocommitそうでない場合、トランザクションデータベースが手に私たちを必要とし
そして、地球がオープンすると、手動で終了します。
手動で開いているトランザクションはいくつかの方法があり、一つは開始使うことです。一つは、開始トランザクションです。
それでは、どのトランザクションが終了していますか?我々はまた、最初のそれは、トランザクションを提出することで、二つの方法で終了しました
コミット、つまり、時間のロールバック、ロールバックがあるされ、トランザクションが完了します。別の場合には、クライアント
切断された場合、トランザクションが完了します。
私たちは、取引を終了したときにロックを保持しているトランザクションがリリースされるとき、私たちはどちらか、戻ってきます
コミットまたはロールバック。
私たちは、手動トランザクションで開く始まり、2番目の更新を行いますが、データがディスクに書き込まれていない、なぜなら
トランザクションが提出されていないために、この時間は、それをコミットし、その後、リフレッシュ、OK、書かれました。
これが私たちのオープンやトランザクションを終了するには、2つの方法です。
1.6並行トランザクションは、すべての問題をもたらすでしょうか?
ときに、データベーステーブルまたは行の多くのトランザクションが同時に動作させる一方で、私たちは業務の話でない場合
分離分離は、いつ、何の問題それをもたらすのだろうか?

 

 

我々は二つのトランザクション、1トランザクションAを持って、トランザクションB、最初のトランザクションであります
表面、条件ID = 1、データ戻り名=エイダ、年齢= 16を介して第一クエリ
このデータ。その後で第2のトランザクションは、同じ方法でデータのID = 1つの行を操作Aを介してそれを更新します
声明、このラインID =年齢18にデータ1が、それは提出しなかったことを指摘しました。
今回は、それが再び同じクエリを実行するためにした最初のトランザクションは、見つかったデータが変更されました
18歳に取得したデータのうち。だから、これは単一のトランザクションで、他の時間が変更されたため、
そして、このトランザクションの並行性の問題を2つの読み出しデータの不整合の前と後の状況につながったデータを、提出しませんでした
私たちは、何としてそれを定義しますか?
これは、ダーティリードと呼ばれています。
内側に例転送は、我々は最初のトランザクションのコミットされていないにを読み取るために2番目のトランザクションのバランスに基づいている場合
ライン操作が、2番目のトランザクションがロールバックされた、この時間は、それが一貫性のないデータにつながります。
このデータは、他のコミットされていないトランザクションの状況に読み込まれ、我々は、ダーティリード、それを呼び出します。
第二に見てみましょう。 

 

 

また、二つのトランザクションは、トランザクションデータのID = 1の最初のクエリ。そして、2番目のトランザクションでいます
更新操作を実行し、ここで私はあなたの注意を持って、我々はコミットすることにより、更新後にそれを行います
変更をコミットします。データではありません前と後に続いて他のコミットされたトランザクションからデータを読み込むための最初のトランザクションは、二つの測定値の結果
同じような状況は、ちょうどここのように、年齢は、このトランザクションは並行性の問題によって引き起こされ、最終的には16または18に等しいです
私たちはそれを呼び出しますか?
このようなトランザクションは、2つの愛を読み込み一貫性のないデータが得られ、他のコミットされたトランザクションにデータを読み込みます
状況、我々は非反復可能読み取り、それを呼び出します。

 

我々は、範囲クエリを実装した最初のトランザクションでは、データの条件を満たすために、この時間はわずか1です。
在第二个事务里面,它插入了一行数据,并且提交了。重点:插入了一行数据。在第一
个事务里面再去查询的时候,它发现多了一行数据。这种情况,我们把它叫做什么呢?
一个事务前后两次读取数据数据不一致,是由于其他事务插入数据造成的,这种情
况我们把它叫做幻读。
不可重复读和幻读,的区别在那里呢?
不可重复读是修改或者删除,幻读是插入。
小结:我们刚才讲了事务并发带来的三大问题,现在来给大家总结一下。无论是脏
读,还是不可重复读,还是幻读,它们都是数据库的读一致性的问题,都是在一个事务
里面前后两次读取出现了不一致的情况。
读一致性的问题,必须要由数据库提供一定的事务隔离机制来解决。就像我们去饭
店吃饭,基本的设施和卫生保证都是饭店提供的。那么我们使用数据库,隔离性的问题
也必须由数据库帮助我们来解决。 
1.7 SQL92 标准
所以,就有很多的数据库专家联合制定了一个标准,也就是说建议数据库厂商都按
照这个标准,提供一定的事务隔离级别,来解决事务并发的问题,这个就是 SQL92 标准。
我们来看一下 SQL92 标准的官网。
http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
这里面有一张表格(搜索_iso),里面定义了四个隔离级别,右边的 P1 P2 P3 就是
代表事务并发的 3 个问题,脏读,不可重复读,幻读。Possible 代表在这个隔离级别下,
这个问题有可能发生,换句话说,没有解决这个问题。Not Possible 就是解决了这个问
题。
我们详细地分析一下这 4 个隔离级别是怎么定义的。
第一个隔离级别叫做:Read Uncommitted(未提交读),一个事务可以读取到其
他事务未提交的数据,会出现脏读,所以叫做 RU,它没有解决任何的问题。
第二个隔离级别叫做:Read Committed(已提交读),也就是一个事务只能读取
到其他事务已提交的数据,不能读取到其他事务未提交的数据,它解决了脏读的问题,
但是会出现不可重复读的问题。
第三个隔离级别叫做:Repeatable Read (可重复读),它解决了不可重复读的问题,
也就是在同一个事务里面多次读取同样的数据结果是一样的,但是在这个级别下,没有
定义解决幻读的问题。
最后一个就是:Serializable(串行化),在这个隔离级别里面,所有的事务都是串
行执行的,也就是对数据的操作需要排队,已经不存在事务的并发操作了,所以它解决
了所有的问题。
这个是 SQL92 的标准,但是不同的数据库厂商或者存储引擎的实现有一定的差异,
比如 Oracle 里面就只有两种 RC(已提交读)和 Serializable(串行化)。那么 InnoDB
的实现又是怎么样的呢?
1.8 MySQL InnoDB 对隔离级别的支持
在 MySQL InnoDB 里面,不需要使用串行化的隔离级别去解决所有问题。那我们来
看一下 MySQL InnoDB 里面对数据库事务隔离级别的支持程度是什么样的。

 

InnoDB 支持的四个隔离级别和 SQL92 定义的基本一致,隔离级别越高,事务的并
发度就越低。唯一的区别就在于,InnoDB 在 RR 的级别就解决了幻读的问题。这个也是
InnoDB 默认使用 RR 作为事务隔离级别的原因,既保证了数据的一致性,又支持较高的
并发度。
1.9 两大实现方案
那么大家想一下,如果要解决读一致性的问题,保证一个事务中前后两次读取数据
结果一致,实现事务隔离,应该怎么做?我们有哪一些方法呢?你的思路是什么样的呢?
总体上来说,我们有两大类的方案。
1.9.1 LBCC
第一种,我既然要保证前后两次读取数据一致,那么我读取数据的时候,锁定我要
操作的数据,不允许其他的事务修改就行了。这种方案我们叫做基于锁的并发控制 Lock
Based Concurrency Control(LBCC)。
如果仅仅是基于锁来实现事务隔离,一个事务读取的时候不允许其他时候修改,那
就意味着不支持并发的读写操作,而我们的大多数应用都是读多写少的,这样会极大地
影响操作数据的效率。 
1.9.2 MVCC
所以我们还有另一种解决方案,如果要让一个事务前后两次读取的数据保持一致,
那么我们可以在修改数据的时候给它建立一个备份或者叫快照,后面再来读取这个快照
就行了。这种方案我们叫做多版本的并发控制 Multi Version Concurrency Control
(MVCC)。
MVCC 的核心思想是: 我可以查到在我这个事务开始之前已经存在的数据,即使它
在后面被修改或者删除了。在我这个事务之后新增的数据,我是查不到的。
问题:这个快照什么时候创建?读取数据的时候,怎么保证能读取到这个快照而不
是最新的数据?这个怎么实现呢?
InnoDB 为每行记录都实现了两个隐藏字段:
DB_TRX_ID,6 字节:插入或更新行的最后一个事务的事务 ID,事务编号是自动递
增的(我们把它理解为创建版本号,在数据新增或者修改为新数据的时候,记录当前事
务 ID)。
DB_ROLL_PTR,7 字节:回滚指针(我们把它理解为删除版本号,数据被删除或记
录为旧数据的时候,记录当前事务 ID)。
我们把这两个事务 ID 理解为版本号。
https://www.processon.com/view/link/5d29999ee4b07917e2e09298 MVCC 演示图
第一个事务,初始化数据(检查初始数据)
Transaction 1
begin;
insert into mvcctest values(NULL,'qingshan') ;
insert into mvcctest values(NULL,'jack') ;
commit;
此时的数据,创建版本是当前事务 ID,删除版本为空:

 

第二个事务,执行第 1 次查询,读取到两条原始数据,这个时候事务 ID 是 2:
Transaction 2
begin;
select * from mvcctest ; -- (1) 第一次查询
 
第三个事务,插入数据:
Transaction 3
begin;
insert into mvcctest values(NULL,'tom') ;
commit;
此时的数据,多了一条 tom,它的创建版本号是当前事务编号,3:
第二个事务,执行第 2 次查询:
Transaction 2
select * from mvcctest ; (2) 第二次查询
MVCC 的查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大
于当前事务 ID 的行(或未删除)。
也就是不能查到在我的事务开始之后插入的数据,tom 的创建 ID 大于 2,所以还是
只能查到两条数据。 
 
第四个事务,删除数据,删除了 id=2 jack 这条记录:
Transaction 4
begin;咕泡出品,必属精品 www.gupaoedu.com
14
delete from mvcctest where id=2;
commit;
此时的数据,jack 的删除版本被记录为当前事务 ID,4,其他数据不变:

 

 

在第二个事务中,执行第 3 次查询:
Transaction 2
select * from mvcctest ; (3) 第三次查询
查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事
务 ID 的行(或未删除)。
也就是,在我事务开始之后删除的数据,所以 jack 依然可以查出来。所以还是这两
条数据。
第五个事务,执行更新操作,这个事务事务 ID 是 5:
Transaction 4
begin;
update mvcctest set name ='盆鱼宴' where id=1;
commit;
此时的数据,更新数据的时候,旧数据的删除版本被记录为当前事务 ID 5(undo),
产生了一条新数据,创建 ID 为当前事务 ID 5:

 

第二个事务,执行第 4 次查询:
Transaction 2咕泡出品,必属精品 www.gupaoedu.com
select * from mvcctest ; (4) 第四次查询
查找规则:只能查找创建时间小于等于当前事务 ID 的数据,和删除时间大于当前事
务 ID 的行(或未删除)。
因为更新后的数据 penyuyan 创建版本大于 2,代表是在事务之后增加的,查不出
来。
而旧数据 qingshan 的删除版本大于 2,代表是在事务之后删除的,可以查出来。
通过以上演示我们能看到,通过版本号的控制,无论其他事务是插入、修改、删除,
第一个事务查询到的数据都没有变化。
在 InnoDB 中,MVCC 是通过 Undo log 实现的。
Oracle、Postgres 等等其他数据库都有 MVCC 的实现。
需要注意,在 InnoDB 中,MVCC 和锁是协同使用的,这两种方案并不是互斥的。
第一大类解决方案是锁,锁又是怎么实现读一致性的呢?

 

おすすめ

転載: www.cnblogs.com/flgb/p/12154348.html