mysql環境RR独立性レベルをRCに変換する問題について記す


まずRR(REPEATABLE-READ)とRC(READ-COMMITTED)の違いを知る.
RR独立性レベルはギャップロックを追加し、幻読を回避し、重複しない読み取りを阻止し、同じトランザクション内のクエリーと変更が一致するようにします.mysqlのデフォルトの独立性レベルはRRです.
RC独立性レベルは、同じトランザクション内で異なるデータがクエリーされる現象があるとはいえ、これらのデータは必ずコミットされ、ハードディスクに実際に保存されているデータである.だから、あまり心配する必要はない.また、RC独立性レベルはかえってロック粒度を低下させ、役に立たないわけではない.oracleとsql serverのデフォルトの独立性レベルはRCに似ている.
だからRCは绝対に悪いというわけではありません.シーンを见て选ぶのですが、ここはプロフィールだけで、深く入り込むつもりはありません.
操作フローの説明:システムが高く、送信されるため、複数のセッションが同時に同じレコードを更新する可能性があるという問題があるが、値は同じである.問題は、トランザクションにRR独立性レベルがRCに変換されるという問題があり、データの戻りが正しくなく、コードの戻りがエラーになるが、データは正確である.
通常のRRトランザクション
まず、現在の環境情報を参照してください.
#   mysql  
mysql> select @@version;
+------------+
| @@version  |
+------------+
| 5.6.39-log |
+------------+
1 row in set (0.00 sec)
#       
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
#   binlog  
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | MIXED |
+---------------+-------+
1 row in set (0.00 sec)

まず、通常のトランザクションを見てみましょう.
#オープントランザクションmysql>begin;Query OK, 0 rows affected (0.00 sec)
#オープントランザクションmysql>begin;Query OK, 0 rows affected (0.00 sec)
#現在のレコードが一致するmysql>select express_cost from m_order_sub where order_sub_no = 'O152022324482662671828';+--------------+| express_cost |+--------------+|         2000 |+--------------+1 row in set (0.02 sec)
#現在のレコードが一致するmysql>select express_cost from m_order_sub where order_sub_no = 'O152022324482662671828';+--------------+| express_cost |+--------------+|         2000 |+--------------+1 row in set (0.02 sec)
#ここでまずレコードを更新mysql>update m_order_sub set express_cost = 3000 where order_sub_no = 'O152022324482662671828';Query OK, 1 row affected (0.01 sec)Rows matched: 1  Changed: 1  Warnings: 0
#こちらは後でレコードを更新しますが、反対側にcommitはありませんので、こちらはロック解除待ちupdate m_order_sub set express_cost = 3000 where order_sub_no = 'O152022324482662671828';
#ここでもう一度検索し、mysql>select express_の変更に成功しました.cost from m_order_sub where order_sub_no = 'O152022324482662671828';+--------------+| express_cost |+--------------+|         3000 |+--------------+1 row in set (0.00 sec)
#コミットトランザクションmysql>commit;Query OK, 0 rows affected (0.01 sec)
#そしてロック解除後こちらの更新も実行済みですが、更新値が同じなので記録には変更されていません.Changedは0 Query OK、0 rows affected(12.40 sec)Rows matched:1  Changed: 0  Warnings: 0
#ここでもう一度検索して、修正に成功したことを記録します.最新データmysql>select expressです.cost from m_order_sub where order_sub_no = 'O152022324482662671828';+--------------+| express_cost |+--------------+|         3000 |+--------------+1 row in set (0.00 sec)
#こちらのクエリの結果は古いです.レコードは変更されていませんので、トランザクション開始時のデータmysql>select express_も表示されます.cost from m_order_sub where order_sub_no = 'O152022324482662671828';+--------------+| express_cost |+--------------+|         2000 |+--------------+1 row in set (0.00 sec)
#トランザクションのコミットと終了mysql>commit;Query OK, 0 rows affected (0.13 sec)
♪すると最新のデータが表示されますmysql>select express_cost from m_order_sub where order_sub_no = 'O152022324482662671828';+--------------+| express_cost |+--------------+|         3000 |+--------------+1 row in set (0.00 sec)
これは正常な状況であり、記録が変更することがないため、表示されるのもトランザクション開始時のデータであり、RRレベルの繰返し可能な読み取り特性を保証する.
もんだいげんしょう
次に別の異常な状況を見てみましょう.環境は上と一致していて、変わっていません.直接図を見てみましょう.
右側のトランザクションは12秒後に実行する、つまり左のcommit後に実行される.しかし、繰り返して読むことができなくなり、右側のトランザクションにはcommitがなくても最新のコミットデータが表示され、非常に奇妙であることがわかる.
解決策
1つ目の方法:独立性レベルをRCに変更することは問題を解決できるようだが、左の問題を解決し、繰り返し可能な特性を繰り返し不可に変更しただけで、両方とも提出した新しいデータを調べることができる.
#  mysql       RC
set global tx_isolation = 'READ-COMMITTED'

変更後、グローバルは繰り返し不可になり、クリアランスロックが無くなり、既に提出された新しいデータが見られるだけに、上の正常な状況も下と一致するが、問題があるわけではない、それ自体がRC分離レベルの特徴である.
それから、これは問題を解決していないのではないかと言われました.ただ、問題を全部同じに変えただけです.そうです.だから、2つ目の案があります.
第2の方案:binlogフォーマットをROWに変えて、隔離レベルを変えなくて、問題は本当に解決しました.
#   binlog    ROW  
set global binlog_format = 'ROW';

元のbinlog形式はMIXED混合モードであることが上に見られたが、今はROWモードに変更し、もう一度試してみる.
はい、すべて正常です.これがRRの特性です.繰り返し読むことができます.
転載先:https://blog.51cto.com/arthur376/2085445