目次
 介绍
mysql 事务类型
mysql事务级别" >mysql事务级别
锁机制" >锁机制
排它锁:" >排它锁:
共享锁:" >共享锁:
实例讲解" >实例讲解

mysql事务_MySQL

Jun 01, 2016 pm 01:01 PM
事務

 介绍

mysql 从4.1 就开始支持事务处理,但是只有用 InnoDB /BDB 类型的引擎创建的数据库才支持事务操作。

查看mysql数据库创建引擎类型:show create table table_name

创建或修改指定类型数据库:Create table .... type=InnoDB; Alter table table_name type=InnoDB;

mysql 事务类型

认为分为两种:

1、begin ,rollback,commit .当然有的人用begin /begin work .推荐用START TRANSACTION 是SQL-99标准启动一个事务。

start transaction;
update from account set money=money-100 where name='a';
update from account set money=money+100 where name='b';
commit;
ログイン後にコピー

<code class="language-sql"><code class="language-sql">解释: 这样start transaction 手动开启事务,commit 手动关闭事务。

<code class="language-sql"><code class="language-sql">2、默认的时候autocommit=1 自动提交是开启的,所以你可以理解为每条语句一输入到mysql就commit 了。当你 set autocommit=0 时候,你可以这样:

update from account set money=money-100 where name=&#39;a&#39;;
update from account set money=money+100 where name=&#39;b&#39;;
commit;
ログイン後にコピー

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">mysql事务级别


<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">在介绍事务级别之前需要了解常见在数据库查询和更新过程中出现的一些问题,简单来讲就是这些事务级别是为了解决什么问题而存在的。 ?

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">1.不可重复读 重复读指的是我们在每次读取的结果都需要是一致的。那么不可重复读就是这个问题会出现每次读取相关的数据出现不一致。出现这个的原因是读取到了其他会话对这条记录进行了修改。<br /> <br /> 2.幻读 幻读指的是当前会话来读取相关记录时,出现其他会话对这个记录添加了一条记录。为了避免幻读通常将事务的隔离级别设置为 serializable 。但是随之而来的问题就有了,当数据库的事务级别设置为serializable级别,数据库就变成了单线程访问数据库,导致性能下降非常大。<br /> <br /> 3.脏读 例如:用户A\B同时向t_accout 表操作,A对t_accout做了这样一个操作,update account set money=money+100 ;在没有提交之前,B用户去查询到没有提交的的money,而后A此时有了一个rollback,B用户再查发现钱少了100.这时候为了避免这个情况,一般设置事务的级别为 <strong>read committed 。就是只能读取提交后的东东 ;</strong><br /> <br /> 为了解决上述的问题出现了事务的级别,以下是数据库中常见的事务级别。<br /> <br /> 级别<br /> <br /> 1.读未提交(Read Uncommitted):这种隔离级别可以让当前事务读取到其它事物还没有提交的数据。这种读取应该是 在回滚段中完成的。通过上面的分析,这种隔离级别是最低的,会导致引发脏读,不可重复读,和幻读。 2.读已提交(Read Committed):这种隔离级别可以让当前事务读取到其它事物已经提交的数据。通过上面的分析,这种隔离级别会导致引发不可重复读,和幻读。 3.可重复读取(Repeatable Read):这种隔离级别可以保证在一个事物中多次读取特定记录的时候都是一样的。通过上面的分析,这种隔离级别会导致引发幻读。 4.串行(Serializable):这种隔离级别将事物放在一个队列中,每个事物开始之后,别的事物被挂起。同一个时间点只能有一个事物能操作数据库对象。这种隔离级别对于数据的完整性是最高的,但是同时大大降低了系统的可并发性。<br /> <strong>各个级别对应可能出现的问题</strong><br /> <br /> <strong><img src="/static/imghw/default1.png" data-src="http://img.bitscn.com/upimg/allimg/c150410/142V3E423Z60-11355.jpg" class="lazy" alt="\" style="max-width:90%" style="max-width:90%" /></strong>

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">锁机制


<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><small><small>除了事务来处理以上不可重复读、幻读、脏读等问题。还有锁也能解决上述问题。</small></small> 在讲解锁之前,需要对常见的几个锁的名词有一个感性的认识。

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">排它锁:


<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁,典型是mysql事务中。也就是既不能对表查询,也不能对表进行修改。<br /> 例如:为user表加排它锁
start transaction;
 
select * from user where userId = 1 for update;
ログイン後にコピー

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">共享锁:


<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写 排它锁和共享锁都是针对某个数据库来讲的,而通常我们听到的还有例如悲观锁、乐观锁、行锁、表锁。<br> 悲观锁其实是针对于开发者或者说是程序员来讲的。悲观锁就是认为在操作数据库时,悲观的认为会在同一时间出现并发访问问题。一般是更新多、查询少的时候用。与之对应的是乐观锁,一般在更新少、查询多的时候用。<br> <br> 这里援引来自网上的一个经典的实例来讲解事务的现实使用。

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">实例讲解


<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">场景:老公去在 ATM 上取钱,老婆在柜台存钱,假设这个账户中有 1000 元。老公首先执行查询操作,查询到账户余额为 1000 此时程序将 1000 拿到内存中,老公取了 200 元,程序就执行了更新操作将账户余额改为 800,但是当老公的程序没有 commit 的时候,老婆查询账户,此时账户余额还是 1000 元,老婆存入 200 元,程序执行了更新操作将账户余额改为 1200,然后老公将更新语句提交,接着老婆也将更新语句提交。最后导致的结果就是该账户的余额为 1200,这就是更新丢失的问题。引发更新丢失的根源就是查询上,因为双方都是根据从数据库查询到的数据再对数据库中的数据进行更新的。解决更新丢失有三个方案:(1) 将事务隔离级别设置为最高,采用死锁策略。(2) <strong>采用悲观锁</strong>,悲观锁不是数据库中真正的锁,是人们看待事务的态度。(3)<strong> 采用乐观锁</strong>,乐观锁也不是数据库中真正的锁。

 

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">如果我们采用的是第一个方案时,老公进行查询操作,数据库为表增加了共享锁,老婆进行查询操作时数据库也增加了一个共享锁。但是当老公进行更新数据库操作时,由于老婆拿着共享锁,导致老公不能增加排它锁,老婆进行更新操作时,因为老公拿着共享锁,导致老婆也拿不到排它锁,这就发生了死锁现象,你等我,我等你。在 mysql 中,处理死锁的方案是释放掉一方的锁。这样就保证了一方更新成功,但是这种性能极低,因为数据库频繁在解决死锁问题。

 

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><strong>悲观锁(更新多,查询少时用)</strong>

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">如果我们采用的是第二个方案时,即采用悲观锁。就是我们在操作数据库时采用悲观的态度,认为别人会在此时并发访问数据库。我们在查询语句中 select * from account where name='aaa' for update; 等于加了排它锁。当老公查询余额的时候,select money from account where name='aaa' for update; 增加了排它锁,老婆查询账户余额的时候, select money from account where name='aaa' for update;也要求对数据库加排它锁,因为老公已经拿到了排它锁,导致老婆不能加锁,所以老婆只有等待老公执行完毕,释放掉锁以后才能继续操作。

 

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><strong>乐观锁(更新少,查询多时用)</strong>

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">如果我们采用的是第三个方案时,即采用乐观锁,就是我们在操作数据库的时候会认为没有其它用户并发访问,但是乐观锁也不是完全乐观的,乐观锁是采用版本号的方式进行控制的。在数据库表中有一列版本号。从数据库中查询的时候,将版本号也查询过来,在进行更新操作的时候,将版本号加1,查询条件的版本号还是查询过来的版本号。比如,老公执行查询操作的时候,select money,version from account where name='aaa'; 假设此时查询到的版本号为 0,老公在进行更新操作的时候 update account set money=money+100,version=version+1 where name='aaa' and version=0; 未提交时老婆来查询,查询到的版本号依然是 0,老婆也执行更新操作 update account set money=money+100,version=version+1 where name='aaa' and version=0; 现在老公提交了事务,老婆再提交事务的时候发现版本号为 0 的记录没有了,所以就避免了数据丢失的问题。不过这种情况也导致了多个用户更新操作时,只有一个用户的更新被执行。

 

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">附:各数据库默认事务级别

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">1、mysql的默认事务的隔离级别:可重复读取(repeatable read);

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">2、sqlserver的默认事务的隔离级别:提交读取(read committed);

<code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql"><code class="language-sql">3、oracle的默认事务的隔离级别:提交读取(read committed).

 

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

ロック待機タイムアウトを超過しました。トランザクションを再起動してください - MySQL エラーの解決方法: トランザクション待機タイムアウト ロック待機タイムアウトを超過しました。トランザクションを再起動してください - MySQL エラーの解決方法: トランザクション待機タイムアウト Oct 05, 2023 am 08:46 AM

Lockwaittimeoutexceeded;tryrestartingtransaction - MySQL エラーの解決方法: トランザクション待機タイムアウト。MySQL データベースを使用すると、一般的なエラーが発生することがあります: Lockwaittimeoutexceeded;tryrestartingtransaction。このエラーは、トランザクション待機タイムアウトを示します。このエラーは通常、次の場合に発生します。

MySQL トランザクション処理: 自動送信と手動送信の違い MySQL トランザクション処理: 自動送信と手動送信の違い Mar 16, 2024 am 11:33 AM

MySQL トランザクション処理: 自動送信と手動送信の違い。MySQL データベースでは、トランザクションは一連の SQL ステートメントです。すべての実行が成功するか、すべての実行が失敗するかのいずれかで、データの一貫性と整合性が保証されます。 MySQL では、トランザクションは自動送信と手動送信に分けられ、その違いはトランザクション送信のタイミングとトランザクションの制御範囲にあります。以下では、自動送信と手動送信の違いを詳しく紹介し、具体的なコード例を示して説明します。 1. MySQL が表示されない場合は自動的に送信する

MySQL トランザクションの原則と適用シナリオ MySQL トランザクションの原則と適用シナリオ Mar 02, 2024 am 09:51 AM

MySQL トランザクションの原理と適用シナリオ データベース システムでは、トランザクションは一連の SQL 操作であり、これらの操作はすべて正常に実行されるか、すべて失敗してロールバックされます。一般的に使用されるリレーショナル データベース管理システムとして、MySQL はトランザクション特性をサポートし、データベース内のデータの一貫性、分離性、耐久性、アトミック性を保証できます。この記事では、MySQL トランザクションの基本原則から始めて、そのアプリケーション シナリオを紹介し、読者の参考となる具体的なコード例を示します。 MySQL トランザクションの原則: My

PHP PDO チュートリアル: 基本から習得までの上級ガイド PHP PDO チュートリアル: 基本から習得までの上級ガイド Feb 19, 2024 pm 06:30 PM

1. PDO の概要 PDO は、データベースを操作するためのオブジェクト指向の方法を提供する PHP の拡張ライブラリです。 PDO は、Mysql、postgresql、oracle、SQLServer などのさまざまなデータベースをサポートします。 PDO を使用すると、開発者は統合 API を使用してさまざまなデータベースを操作できるため、さまざまなデータベースを簡単に切り替えることができます。 2. PDO はデータベースに接続します PDO を使用してデータベースに接続するには、まず PDO オブジェクトを作成する必要があります。 PDO オブジェクトのコンストラクターは、データベース タイプ、ホスト名、データベース ユーザー名、およびパスワードの 3 つのパラメーターを受け取ります。たとえば、次のコードは、mysql データベースに接続するオブジェクトを作成します。 $dsn="mysq

Java データベース接続はトランザクションと同時実行をどのように処理しますか? Java データベース接続はトランザクションと同時実行をどのように処理しますか? Apr 16, 2024 am 11:42 AM

トランザクションは、原子性、一貫性、分離性、耐久性などのデータベース データの整合性を保証します。 JDBC は、Connection インターフェイスを使用してトランザクション制御 (setAutoCommit、コミット、ロールバック) を提供します。同時実行制御メカニズムは、ロックまたはオプティミスティック/ペシミスティック同時実行制御を使用して同時操作を調整し、トランザクションの分離を実現してデータの不整合を防ぎます。

PHP PDO のパワーをマスターする: 高度なクエリと更新 PHP PDO のパワーをマスターする: 高度なクエリと更新 Feb 20, 2024 am 08:24 AM

PHP Data Objects (PDO) 拡張機能は、データベース サーバーとの効率的でオブジェクト指向の対話を提供します。高度なクエリおよび更新機能により、開発者は複雑なデータベース操作を実行できるようになり、パフォーマンスとコードの保守性が向上します。この記事では、PDO の高度なクエリ機能と更新機能を詳しく説明し、その強力な機能をマスターする方法を説明します。高度なクエリ: プレースホルダーとバインドされたパラメーターの使用 プレースホルダーとバインドされたパラメーターは、クエリのパフォーマンスとセキュリティを向上させるための重要なツールです。プレースホルダーでは疑問符 (?) を使用してクエリ内の置換可能なパラメーターを表し、バインド パラメーターを使用すると各パラメーターのデータ型と値を指定できます。これらの方法を使用すると、データベース エンジンが事前にクエリを最適化できるため、SQL インジェクション攻撃を回避し、パフォーマンスを向上させることができます。 // プレースホルダー $stmt=$ を使用します

MongoDB テクノロジー開発で遭遇するトランザクション管理問題の解決策の分析 MongoDB テクノロジー開発で遭遇するトランザクション管理問題の解決策の分析 Oct 08, 2023 am 08:15 AM

MongoDB テクノロジー開発で遭遇するトランザクション管理問題の解決策の分析 最新のアプリケーションがますます複雑かつ大規模になるにつれて、データのトランザクション処理要件もますます高くなっています。 MongoDB は、人気のある NoSQL データベースとして、データ管理において優れたパフォーマンスとスケーラビリティを備えています。ただし、MongoDB はデータの一貫性とトランザクション管理が比較的弱く、開発者にとって課題となっています。この記事では、MongoDB 開発で遭遇するトランザクション管理の問題を調査し、いくつかの解決策を提案します。

安定したスケーラブルなシステムを構築するためのJava EJBアーキテクチャの詳細な説明 安定したスケーラブルなシステムを構築するためのJava EJBアーキテクチャの詳細な説明 Feb 21, 2024 pm 01:13 PM

EJBとは何ですか? EJB は、サーバー側のエンタープライズクラス Java アプリケーションを構築するためのコンポーネントのセットを定義する Java Platform, Enterprise Edition (JavaEE) 仕様です。 EJB コンポーネントはビジネス ロジックをカプセル化し、トランザクション、同時実行性、セキュリティ、その他のエンタープライズ レベルの懸念事項を処理するための一連のサービスを提供します。 EJB アーキテクチャ EJB アーキテクチャには、次の主要コンポーネントが含まれています。 Enterprise Bean: これは、EJB コンポーネントの基本的な構成要素であり、ビジネス ロジックと関連データをカプセル化します。 EnterpriseBean は、ステートレス (セッション Bean とも呼ばれます) またはステートフル (エンティティ Bean とも呼ばれます) にすることができます。セッション コンテキスト: セッション コンテキストは、セッション ID やクライアントなど、現在のクライアント インタラクションに関する情報を提供します。

See all articles