ホームページ  >  記事  >  データベース  >  MySQL と Redis トランザクションの比較 (写真とテキスト)

MySQL と Redis トランザクションの比較 (写真とテキスト)

不言
不言転載
2019-03-30 10:53:213404ブラウズ

この記事の内容は、MySQL と Redis のトランザクションの比較 (写真とテキスト) に関するもので、一定の参考価値があります。必要な友人が参考にすることができます。お役に立てれば幸いです。

要約: 一般に、トランザクションは 4 つの条件 (ACID) を満たす必要があります。アトミック性 (A トミシティ、または分割不可能性)、一貫性 (C一貫性)、分離 (##) #I孤立、独立としても知られています)、耐久性(Durability)。

タイトルから判断すると、どちらもトランザクションなので、両者の違いは何でしょうか? 2 つのデータベースから始めて、1 つずつ紐解いていきましょう。

MySQL は

リレーショナル データベース に属し、Redis は 非リレーショナル データベース に属しており、トランザクションの解釈が異なります。

(関連する推奨事項:

MySQL チュートリアル Redis チュートリアル )

Redis

[1] Redis トランザクションは複数のトランザクションを実行できます

    バッチ操作は、EXEC コマンドを送信する前にキュー キャッシュに入れられます。
  • EXEC コマンドを受信した後、トランザクションの実行を開始します。トランザクション内のいずれかのコマンドが実行に失敗した場合でも、残りのコマンドは引き続き実行されます。
  • トランザクション実行プロセス中、他のクライアントによって送信されたコマンド要求は、トランザクション実行コマンド シーケンスに挿入されません。
トランザクションは、開始から実行まで次の 3 つの段階を経ます:

    トランザクションの開始。
  • キューに参加するコマンド。
  • トランザクションを実行します。

単一の Redis コマンドの実行はアトミックですが、Redis はトランザクションのアトミック性を維持するメカニズムを追加していないため、Redis トランザクションの実行はアトミックではありません。

トランザクションは、パッケージ化されたバッチ実行スクリプトとして理解できますが、バッチ命令はアトミックな操作ではありません。途中で命令が失敗しても、前の命令はロールバックされません。また、後続の命令が実行されなくなることはありません。

操作エラー

少し複雑そうなので、実際に実行して結果を見てみましょう。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set tr_1 233
QUEUED
127.0.0.1:6379> lpush tr_1 666
QUEUED
127.0.0.1:6379> set tr_2 888
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
上記のトランザクションでは、

tr_1 というキーを持つ文字列データを設定し、lpush を通じて要素を追加していますが、これは明らかに間違っています。トランザクションを送信すると、オペレーションエラーが発生しますが、このときのtr_1の値を見てみましょう。

127.0.0.1:6379> get tr_1
"233"

get コマンドで取得した tr_1 の内容は 233 のままで変更されていません。

127.0.0.1:6379> keys *
1) "tr_2"
2) "tr_1"
127.0.0.1:6379> get tr_2
"888"
127.0.0.1:6379>
ここでは、

tr_2 が存在し、値が出力されていることがわかります。このとき、操作エラーが発生しても、エラーは発生しないことがわかりました。 いいえ 実行が停止され、エラー後のステートメントも実行されて正常に実行されます。これは、上記の内容と一致しているようです。 途中で特定の命令が失敗しても、エラーは発生しません。前の命令のロールバックが発生するだけでなく、後続の命令も発生しません。これは行わないでください。

構文エラー

NO~、現時点では別の状況があります

構文エラー

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set tr_1 233
QUEUED
127.0.0.1:6379> lpush tr_1 666
QUEUED
127.0.0.1:6379> set
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> set 233
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> set tr_2 888
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *
(empty list or set)
実行時

No の設定時にパラメータが指定され、2 回目の実行時に 1 つのパラメータが意図的に指定されました。 構文エラーが報告され、トランザクションが最終的に送信されたことがわかります。これにより、エラーによりトランザクションが失われたことがわかります。その後、keys * を使用して検索し、これが実際に当てはまることがわかりました。

ドキュメントの解釈

ここでは、公式ドキュメントで言及されている

トランザクション内のエラーを見つけることができます

// 実行中に発生する可能性があります2 つの間違ったコマンド エラーが発生します。

トランザクション中に、次の 2 種類のコマンド エラーが発生する可能性があります:

//

1 コマンドはキューに入力できません。たとえば、番号が間違っています。パラメータの不足、間違ったコマンド名 ...、またはメモリ不足などの重大なエラー

    コマンドがキューに入れられない可能性があるため、EXEC が呼び出される前にエラーが発生する可能性があります。たとえば、次のコマンドです。構文的に間違っている可能性があります (引数の数が間違っている、コマンド名が間違っているなど)。または、メモリ不足状態などの重大な状態が存在する可能性があります (サーバーが
  • maxmemory# を使用してメモリ制限を持つように構成されている場合) ##directive).
  • //
2

。上記の文字列で lpush を使用するなど、キーに対して間違った操作を実行します。##コマンドが失敗する可能性があります

after
    たとえば、間違った値のキーに対して操作を実行したため (文字列値に対してリスト操作を呼び出すなど)、EXEC が呼び出されます。
  • // クライアント入力されたコマンドをチェックします。ほとんどの場合、
  • exec
を呼び出す前に

最初のタイプ エラーが見つかります。コマンドの実行で QUEUED が返された場合、コマンドが正常にキューに入ったことを意味します。それ以外の場合は、エラーが発生します。ほとんどの場合、クライアントは終了します。このトランザクションは放棄してください。

Clients used to sense the first kind of errors, happening before the EXEC call, by checking the return value of the queued command: if the command replies with QUEUED it was queued correctly, otherwise Redis returns an error. If there is an error while queueing a command, most clients will abort the transaction discarding it.

关于 Redis 暂时看到这里 接下来看到 MySQL

MySQL

众所周知,MySQL 只有 InnoDB 引擎支持 事务,在启用 MySQL 事务之前需要先停掉自动提交

测试表结构 user

类型 注释
id int(11) 自动增量 主键ID
money int(11) [0] 金钱
title varchar(500) NULL 称呼

在这里来模拟一个转账的操作:AB100元

步骤解析 A+100 元,B -100元,即两步虽然很简单,简单走一下流程。

MySQL と Redis トランザクションの比較 (写真とテキスト)

可以看到,没有问题,那么我们从中人为的制造一些问题呢?

操作错误




类型 注释
id int(11) 自动增量
money int(11) unsigned [0]
title varchar(500) NULL

这里我们把 money 字段变成了无符号,即不能小于 0,并且,调整数据库中的数据如下。

`SELECT * FROM `user` LIMIT 50` (0.000 秒)
修改 id money title
编辑 1 10000 A
编辑 2 0 B

接着执行下面的 SQL

select version();
SET AUTOCOMMIT=0;
begin;
select * from user where title in ('A','B') for update;
update user set  money = money + 1000 where title = 'A';
update user set money = money - 1000 where title = 'B';
select * from user where title in ('A','B');
commit;

MySQL と Redis トランザクションの比較 (写真とテキスト)

问题出现了,这里报出了错误,但是可以看到 前面的 SQL 已经是已执行的了,结果已经发生了变化,从这里看,似乎和 Redis 的处理差不多,除了错误之后语句继续执行。但是 值的注意的是, 在我们实际开发中,这种情况程序会直接抛出异常,以供我们在 catch 块中执行 rollback ,以回滚操作确保数据完整,即使是单独使用 MySQL 命令行 我们也可以用存储过程来对异常进行回滚。

语法错误

刚刚看到 Redis 当遇到 语法错误 时会自动丢弃事务,阻止提交,那 MySQL 呢?

MySQL と Redis トランザクションの比較 (写真とテキスト)

答案:不会,MySQL 在顺序执行时,如果未对异常进行处理,总会将成功执行的的提交,而不会触发自动终止,但是我们可以在程序执行时进行放弃提交。

Redis 为什么没有回滚?

Redis 的官方文档给出了这样的解释

// 只有在使用错误的语法调用时才会失败Redis命令(并且在命令排队期间无法检测到问题),或者对于持有错误数据类型的键,Redis命令可能会失败:这意味着实际上失败的命令是编程错误的结果,以及在开发过程中很可能检测到的一种错误,而不是在生产中。

  • Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.

// Redis内部简化且速度更快,因为它不需要回滚的能力。

  • Redis is internally simplified and faster because it does not need the ability to roll back.

总结

数据库    自动回滚条件 操作错误 语法错误
MySQL
Redis

但是 MySQL 支持手动回滚,实际开发过程中可以自行手动对已提交的操作进行回滚操作,更加友好。

以上がMySQL と Redis トランザクションの比較 (写真とテキスト)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。