recherche
Maisonbase de donnéestutoriel mysql并发下的事务处理
并发下的事务处理Jun 07, 2016 pm 04:10 PM
事务事务处理保障并发行业软件

事务保障,是软件行业必须要做的事情。很多金融公司,就是由于事务处理不得当而倒闭。 我们都知道,事务有四大特性:ACID。即:原子性、一致性、隔离性、持久性。 四大特性 原子性 事务是数据库的逻辑单位,事务总包括的诸操作那么全部执行,要么都不执行;

事务保障,是软件行业必须要做的事情。很多金融公司,就是由于事务处理不得当而倒闭。

我们都知道,事务有四大特性:ACID。即:原子性、一致性、隔离性、持久性。

四大特性

原子性

事务是数据库的逻辑单位,事务总包括的诸操作那么全部执行,要么都不执行;

一致性

职务执行的结果,必须使数据库从一个一直状态、变到另一个一直状态。一致性与原子性紧密关联。

隔离性

一个事务的执行,不能被其他事务干扰

持久性

一个事务一旦提交,它对数据库中的数据改变就应该是永久性的。

这就是事务的四大特性。

隔离级别

下面,我们来具体来说一说隔离性

我们都知道,事务控制的太严格,程序在并发访问的情况下,会降低程序的性能。所以,人们总是想让事务为性能做出让步,那么就分出了四中隔离级别:

为提交读、提交读、重复读、序列化。

但是,由于隔离界别限制的程度不同,那么就会产生脏读、不可重复读、幻读的情况。

1. 脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

2. 不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以 避免该问题。

3.幻读 :是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。

下面看数据库事务的隔离级别,由低到高依次为未提交读、提交读、重复读、序列化。

这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

√:可能出现 ×:不会出现

脏读

不可重复读

幻读

Read uncommitted

Read committed

×

Repeatable read

×

×

Serializable

×

×

×

注意:我们讨论隔离级别的场景,主要是在多个事务并发的情况下,因此,接下来的讲解都围绕事务并发。

未提交读

公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有2000元,singo空欢喜一场。

出现上述情况,即我们所说的脏读,两个并发的事务,“事务A:领导给singo发工资”、“事务B:singo查询工资账户”,事务B读取了事务A尚未提交的数据。

当隔离级别设置为Readuncommitted时,就可能出现脏读,如何避免脏读,请看下一个隔离级别。

读提交

singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何......

出现上述情况,即我们所说的不可重复读,两个并发的事务,“事务A:singo消费”、“事务B:singo的老婆网上转账”,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。

当隔离级别设置为Readcommitted时,避免了脏读,但是可能会造成不可重复读。

大多数数据库的默认级别就是Readcommitted,比如Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。

重复读

当隔离级别设置为Repeatableread时,可以避免不可重复读。当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。

虽然Repeatableread避免了不可重复读,但还有可能出现幻读。

singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额(select sum(amount) from transaction where month =本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。

注:Mysql的默认隔离级别就是Repeatableread。

序列化

Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

PS:大多数数据库都是使用提交读,作为默认的隔离级别,如Oracle、SqlServer。因为在数据量访问的情况下,这种方式性能较好,同时防止了脏读的情况发生,尽管有不可重复读的情况,但是在可承受的范围内;也有一些数据采用重复读,作为默认的隔离级别。如果采用默认配置,那么使用MySql的性能会稍低一些。MySql隔离级别的默认配置实现,原理是数据访问时加了读写锁,并发读取时,分别加锁,但是只有第一个加锁的事务,才能修改事务,其他事务不能修改,它避免了可重复读的情况。序列化同样是加锁,但是它加的是独占锁,无论哪个线程读取到数据,立马会将其霸占,直至其操作完成。这种方式一致性高,但是并发性不好,很少使用。

事务的传播特性

在开发中,我们一个action中,可能调用多个Service,那么这种情况,是如何保证事务的呢?事务的传播特性。下面我们来看看Spring事务的传播特性:

1. PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
2. PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
3. PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
4. PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
5. PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6. PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7. PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。


具体解释一下:
1. PROPAGATION_REQUIRED:加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务。比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED,那么由于执行ServiceA.methodA的时候,ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚。
2. PROPAGATION_SUPPORTS:如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行。
3. PROPAGATION_MANDATORY:必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。
4. PROPAGATION_REQUIRES_NEW:这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,他才继续执行。他与PROPAGATION_REQUIRED的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。
5. PROPAGATION_NOT_SUPPORTED:当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。
6. PROPAGATION_NEVER:不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,那么ServiceB.methodB就要抛出异常了。
7. PROPAGATION_NEST:理解Nested的关键是savepoint。
他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立, 而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。而Nested事务的好处是他有一个savepoint。也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如 ServiceC.methodC,继续执行,来尝试完成自己的事务。 但是这个事务并没有在EJB标准中定义。

PS:我们最常用的传播特性就是PROPAGATION_REQUIRED。支持当前事务,如果当前没有事务,就新建一个事务。

分布式事务

1.XA

XA 是由X/Open组织提出的分布式事务的规范。XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口。XA接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁。XA之所以需要引入事务管理器是因为,在分布式系统中,从理论上讲,两台机器理论上无法达到一致的状态,需要引入一个单点进行协调。事务管理器控制着全局事务,管理事务生命周期,并协调资源。资源管理器负责控制和管理实际资源(如数据库或 JMS队列)。

2.JTA

作 为java平台上事务规范JTA(Java Transaction API)也定义了对XA事务的支持,实际上,JTA是基于XA架构上建模的,在JTA 中,事务管理器抽象为javax.transaction.TransactionManager接口,并通过底层事务服务(即JTS)实现。像很多其他 的java规范一样,JTA仅仅定义了接口,具体的实现则是由供应商(如J2EE厂商)负责提供,目前JTA的实现主要由以下几种:

1.J2EE容器所提供的JTA实现(JBoss)
2.独立的JTA实现:如JOTM,Atomikos.这些实现可以应用在那些不使用J2EE应用服务器的环境里用以提供分布事事务保证。如Tomcat,Jetty以及普通的java应用。


3.两阶段提交

所有关于分布式事务的介绍中都必然会讲到两阶段提交,因为它是实现XA分布式事务的关键(确切地说:两阶段提交主要保证了分布式事务的原子性:即所有结点要么全做要么全不做)。所谓的两个阶段是指:第一阶段:准备阶段和第二阶段:提交阶段。

n峨扎蕙h簑hn峨?%暥湊*&?[於?伜
</p>

Déclaration
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Go 语言中的 goroutine 是什么?Go 语言中的 goroutine 是什么?Jun 11, 2023 am 11:50 AM

Go语言是一种开源编程语言,由Google开发并于2009年面世。这种语言在近年来越发受到关注,并被广泛用于开发网络服务、云计算等领域。Go语言最具特色的特点之一是它内置了goroutine(协程),这是一种轻量级的线程,可以在代码中方便地实现并发和并行计算。那么goroutine到底是什么呢?简单来说,goroutine就是Go语言中的

Java 中的锁机制Java 中的锁机制Jun 08, 2023 am 08:03 AM

Java作为一种高级编程语言,在并发编程中有着广泛的应用。在多线程环境下,为了保证数据的正确性和一致性,Java采用了锁机制。本文将从锁的概念、类型、实现方式和使用场景等方面对Java中的锁机制进行探讨。一、锁的概念锁是一种同步机制,用于控制多个线程之间对共享资源的访问。在多线程环境下,线程的执行是并发的,多个线程可能会同时修改同一数据,这就会导致数

如何解决Python的函数中的并发不安全错误?如何解决Python的函数中的并发不安全错误?Jun 24, 2023 pm 12:37 PM

Python是一门流行的高级编程语言,它具有简单易懂的语法、丰富的标准库和开源社区的支持,而且还支持多种编程范式,例如面向对象编程、函数式编程等。尤其是Python在数据处理、机器学习、科学计算等领域有着广泛的应用。然而,在多线程或多进程编程中,Python也存在一些问题。其中之一就是并发不安全。本文将从以下几个方面介绍如何解决Python的函数中的并发不安

PHP8.0如何使用Fibers实现并发PHP8.0如何使用Fibers实现并发May 14, 2023 am 09:01 AM

随着现代互联网技术的不断发展,网站访问量越来越大,对于服务器的并发处理能力也提出了更高的要求。如何提高服务器的并发处理能力是每个开发者需要面对的问题。在这个背景下,PHP8.0引入了Fibers这一全新的特性,让PHP开发者掌握一种全新的并发处理方式。Fibers是什么?首先,我们需要了解什么是Fibers。Fibers是一种轻量级的线程,可以高效地支持PH

Java的并发异常——java.util.ConcurrentModificationException怎么办?Java的并发异常——java.util.ConcurrentModificationException怎么办?Jun 25, 2023 am 11:46 AM

Java作为一种高级语言,在编程语言中使用广泛。在Java的应用程序和框架的开发中,我们经常会碰到并发的问题。并发问题是指当多个线程同时对同一个对象进行操作时,会产生一些意想不到的结果,这些问题称为并发问题。其中的一个常见的异常就是java.util.ConcurrentModificationException异常,那么我们在开发过程中如何有效地解决这个异

Java中如何使用ConcurrentLinkedQueue函数进行并发队列操作Java中如何使用ConcurrentLinkedQueue函数进行并发队列操作Jun 26, 2023 pm 05:37 PM

Java中的ConcurrentLinkedQueue函数为开发者提供了一种线程安全的、高效的队列实现方式,它支持并发读写操作,并且执行效率较高。在本文中,我们将介绍Java中如何使用ConcurrentLinkedQueue函数进行并发队列操作,帮助开发者更好地利用其优势。ConcurrentLinkedQueue是Java中的一个线程安全、非阻塞的队列实

使用Go和Goroutines实现高效的并发图计算使用Go和Goroutines实现高效的并发图计算Jul 21, 2023 pm 03:58 PM

使用Go和Goroutines实现高效的并发图计算引言:随着大数据时代的到来,图计算问题也成为了一个热门的研究领域。在图计算中,图的顶点和边之间的关系非常复杂,因此如果采用传统的串行方法进行计算,往往会遇到性能瓶颈。为了提高计算效率,我们可以利用并发编程的方法使用多个线程同时进行计算。今天我将向大家介绍使用Go和Goroutines实现高效的并发图计算的方法

PHP和WebDriver扩展:如何模拟多个用户的并发访问PHP和WebDriver扩展:如何模拟多个用户的并发访问Jul 07, 2023 pm 06:03 PM

PHP和WebDriver扩展:如何模拟多个用户的并发访问随着互联网的快速发展,网站的访问量也越来越大,很多场景下需要测试网站在高并发情况下的表现。本文将介绍如何使用PHP和WebDriver扩展来模拟多个用户的并发访问,并提供相应的代码示例。首先,我们需要安装并配置PHP和WebDriver扩展。PHP是一种流行的服务器端脚本语言,而WebDriver是一

See all articles

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semainesBy尊渡假赌尊渡假赌尊渡假赌
Repo: Comment relancer ses coéquipiers
4 Il y a quelques semainesBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
4 Il y a quelques semainesBy尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

Listes Sec

Listes Sec

SecLists est le compagnon ultime du testeur de sécurité. Il s'agit d'une collection de différents types de listes fréquemment utilisées lors des évaluations de sécurité, le tout en un seul endroit. SecLists contribue à rendre les tests de sécurité plus efficaces et productifs en fournissant facilement toutes les listes dont un testeur de sécurité pourrait avoir besoin. Les types de listes incluent les noms d'utilisateur, les mots de passe, les URL, les charges utiles floues, les modèles de données sensibles, les shells Web, etc. Le testeur peut simplement extraire ce référentiel sur une nouvelle machine de test et il aura accès à tous les types de listes dont il a besoin.

Navigateur d'examen sécurisé

Navigateur d'examen sécurisé

Safe Exam Browser est un environnement de navigation sécurisé permettant de passer des examens en ligne en toute sécurité. Ce logiciel transforme n'importe quel ordinateur en poste de travail sécurisé. Il contrôle l'accès à n'importe quel utilitaire et empêche les étudiants d'utiliser des ressources non autorisées.

Version crackée d'EditPlus en chinois

Version crackée d'EditPlus en chinois

Petite taille, coloration syntaxique, ne prend pas en charge la fonction d'invite de code

mPDF

mPDF

mPDF est une bibliothèque PHP qui peut générer des fichiers PDF à partir de HTML encodé en UTF-8. L'auteur original, Ian Back, a écrit mPDF pour générer des fichiers PDF « à la volée » depuis son site Web et gérer différentes langues. Il est plus lent et produit des fichiers plus volumineux lors de l'utilisation de polices Unicode que les scripts originaux comme HTML2FPDF, mais prend en charge les styles CSS, etc. et présente de nombreuses améliorations. Prend en charge presque toutes les langues, y compris RTL (arabe et hébreu) ​​et CJK (chinois, japonais et coréen). Prend en charge les éléments imbriqués au niveau du bloc (tels que P, DIV),