MySQL 事务概念与用法深入详解

本文实例讲述了MySQL 事务概念与用法。分享给大家供大家参考,具体如下:

事务的概念

MySQL事务是一个或者多个的数据库操作,要么全部执行成功,要么全部失败回滚。

事务是通过事务日志来实现的,事务日志包括:redo log和undo log。

事务的状态

活动的(active)

事务对应的数据库操作正在执行过程中时,我们就说该事务处在活动的状态。

部分提交的(partially committed)

当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我们就说该事务处在部分提交的状态。

失败的(failed)

当事务处在活动的或者部分提交的状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在失败的状态。

中止的(aborted)

如果事务执行了半截而变为失败的状态,撤销失败事务对当前数据库造成的影响,我们把这个撤销的过程称之为回滚。

当回滚操作执行完毕时,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处在了中止的状态。

提交的(committed)

当一个处在部分提交的状态的事务将修改过的数据都同步到磁盘上之后,我们就可以说该事务处在了提交的状态。

从图中大家也可以看出了,只有当事务处于提交的或者中止的状态时,一个事务的生命周期才算是结束了。对于已经提交的事务来说,该事务对数据库所做的修改将永久生效,对于处于中止状态的事务,该事务对数据库所做的所有修改都会被回滚到没执行该事务之前的状态。

事务的作用

事务主要是为了保证复杂数据库操作数据的一致性,尤其是在并发访问数据时。
MySQL 事务主要用于处理操作量大,复杂度高的数据。

事务的特点

原子性(Atomicity,又称不可分割性)

事务的数据操作,要么全部执行成功,要么全部失败回滚到执行之前的状态,就像这个事务从来没有执行过一样。

隔离性(Isolation,又称独立性)

多个事务之间是相互隔离,互不影响的。数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

四种隔离状态:
1. 读未提交(Read uncommitted)
2. 读提交(Read committed)
3. 可重复读(Repeatable read)
4. 串行化(Serializable)

一致性(Consistency)

在事务操作之前和之后,数据都是保持一个相同的状态,数据库的完整性没有被破坏。
原子性和隔离性,对一致性有着至关重要的影响。

持久性(Durability)

当事务操作完成后,数据会被刷新到磁盘永久保存,即便是系统故障也不会丢失。

事务的语法

数据

#创建数据表:
create table account(
  -> id int(10) auto_increment,
  -> name varchar(30),
  -> balance int(10),
  -> primary key (id));
#插入数据:
insert into account(name,balance) values('老王媳妇',100),('老王',10);
mysql> select * from account;
+----+--------------+---------+
| id | name     | balance |
+----+--------------+---------+
| 1 | 老王媳妇 |   100  |
| 2 | 老王    |   10 |
+----+--------------+---------+

老王媳妇有100元存在自己的微信账户上了,专门给老王每个月发零花钱用的,表现好给的多,老王也有自己的小金库,目前已经攒到了10元零花钱了,哈哈哈。

begin

事务启动方式1

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> 事务操作SQL......

start transaction [修饰符]

修饰符:
1. read only //只读
2. read write //读写 默认
3. WITH CONSISTENT SNAPSHOT //一致性读

事务启动方式2

mysql> start transaction read only;
Query OK, 0 rows affected (0.00 sec)
mysql> 事务操作SQL......
#如设置read only后,对数据进行修改会报错:

mysql> start transaction read only;
Query OK, 0 rows affected (0.00 sec)

mysql> update account set balance=banlance+30 where id = 2;
ERROR 1792 (25006): Cannot execute statement in a READ ONLY transaction.

commit

事务执行提交,提交成功则刷新到磁盘

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

rollback

事务执行回滚,回到事务操作之前的状态。

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

这里需要强调一下,ROLLBACK语句是我们程序员手动的去回滚事务时才去使用的,如果事务在执行过程中遇到了某些错误而无法继续执行的话,事务自身会自动的回滚。

完整的提交例子

1月份,老王的表现很不错,老王媳妇给他奖励20元零花钱。

执行步骤:
1. 从老王媳妇账户读取数据
2. 从老王媳妇账户上减掉20元
3. 从老王账户读取数据
4. 给老王账户增加20元
5. 执行提交成功
6. 此时老王媳妇账户只有80元啦,而老王账户有30元啦,老王高兴不得了咯

mysql> begin;
Query OK, 0 rows affected (0.01 sec)

mysql> update account set balance=balance-20 where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> update account set balance=balance+20 where id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.01 sec)
#账户余额:
mysql> select * from account;
+----+--------------+---------+
| id | name | balance |
+----+--------------+---------+
| 1 | 老王媳妇 | 80 |
| 2 | 老王 | 30 |
+----+--------------+---------+

完整的回滚例子

2月份,老王本来表现得很棒,坚持干家务活和遛狗,老王媳妇要给他25元的零花钱,可老王不经夸啊,老王媳妇正在给老王转零花钱时,突然看到桌子上老王手机收到一条小女生发来的微信:亲爱的王哥....,老王媳妇特别生气,一怒之下撤回了转账,取消这个月的零花钱。

执行步骤:
1. 从老王媳妇账户读取数据
2. 从老王媳妇账户上减掉25元
3. 从老王账户读取数据
4. 给老王账户增加25元
5. 此时老王媳妇撤回之前的操作
6. 此时,老王和老王媳妇的账户余额还是保持操作之前的数目

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update account set balance=balance-25 where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> update account set balance=balance+25 where id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
#账户余额:
mysql> select * from account;
+----+--------------+---------+
| id | name     | balance |
+----+--------------+---------+
| 1 | 老王媳妇 |   80 |
| 2 | 老王    |   30 |
+----+--------------+---------+

事务支持的存储引擎

1. InnoDB
2. NDB

不支持的存储引擎,比如在MyISAM上操作事务,事务不会生效,SQL语句直接自动执行提交,所以回滚对于不支持事务的存储引擎是无效的。

create table tb1(
  -> id int(10) auto_increment,
  -> name varchar(30),
  -> primary key (id)
  -> )engine=myisam charset=utf8mb4;

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into tb1(name) values('Tom');
Query OK, 1 row affected (0.01 sec)

mysql> select * from tb1;
+----+------+
| id | name |
+----+------+
| 1 | Tom |
+----+------+
1 row in set (0.00 sec)

mysql> rollback;//回滚无效
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select * from tb1;
+----+------+
| id | name |
+----+------+
| 1 | Tom |
+----+------+
1 row in set (0.00 sec)

事务的设置与查看

#查看事务开启情况:
mysql> SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+

默认是事务自动提交的,每执行一条SQL就自动提交。

此时需要操作事务,则需要显式开启(begin or start transaction)和提交(commit)或回滚(rollback)。

如设置成OFF,则需要执行提交(commit)或回滚(rollback)操作时才会真正执行事务。

关闭自动提交方式

第一种

显式的的使用START TRANSACTION或者BEGIN语句开启一个事务。

第二种

把系统变量autocommit的值设置为OFF。

SET autocommit = OFF;

隐式提交情况

当我们使用START TRANSACTION或者BEGIN语句开启了一个事务,或者把系统变量autocommit的值设置为OFF时,事务就不会进行自动提交,但是如果我们输入了某些语句之后就会悄悄的提交掉,就像我们输入了COMMIT语句了一样,这种因为某些特殊的语句而导致事务提交的情况称为隐式提交

定义或修改数据库对象的数据定义语言(Data definition language,缩写为:DDL)

所谓的数据库对象,指的就是数据库、表、视图、存储过程等等这些东西。当我们使用CREATE、ALTER、DROP等语句去修改这些所谓的数据库对象时,就会隐式的提交前边语句所属于的事务。

BEGIN;
SELECT ... # 事务中的一条语句
UPDATE ... # 事务中的一条语句
... # 事务中的其它语句
CREATE TABLE ... # 此语句会隐式的提交前边语句所属于的事务
隐式使用或修改mysql数据库中的表

隐式使用或修改mysql数据库中的表。

当我们使用ALTER USER、CREATE USER、DROP USER、GRANT、RENAME USER、REVOKE、SET PASSWORD等语句时也会隐式的提交前边语句所属于的事务。

事务控制或关于锁定的语句

事务控制或关于锁定的语句。

当我们在一个事务还没提交或者回滚时就又使用START TRANSACTION或者BEGIN语句开启了另一个事务时,会隐式的提交上一个事务。

BEGIN;
SELECT ... # 事务中的一条语句
UPDATE ... # 事务中的一条语句
... # 事务中的其它语句
BEGIN; # 此语句会隐式的提交前边语句所属于的事务

或者当前的autocommit系统变量的值为OFF,我们手动把它调为ON时,也会隐式的提交前边语句所属的事务。

或者使用LOCK TABLES、UNLOCK TABLES等关于锁定的语句也会隐式的提交前边语句所属的事务。

加载数据的语句

比如我们使用LOAD DATA语句来批量往数据库中导入数据时,也会隐式的提交前边语句所属的事务。

关于MySQL复制的一些语句

使用START SLAVE、STOP SLAVE、RESET SLAVE、CHANGE MASTER TO等语句时也会隐式的提交前边语句所属的事务。

其它的一些语句

使用ANALYZE TABLE、CACHE INDEX、CHECK TABLE、FLUSH、 LOAD INDEX INTO CACHE、OPTIMIZE TABLE、REPAIR TABLE、RESET等语句也会隐式的提交前边语句所属的事务。

事务的保存点

概念

在事务对应的数据库语句中打几个点,我们在调用ROLLBACK语句时可以指定会滚到哪个点,而不是回到最初的原点。

有了事务的保存点,我们在进行复杂的事务操作时,我们不用担心一出错直接回滚到最初状态,就如一夜回到解放前。

使用语法

1. SAVEPOINT 保存点名称;//标记保存点
2. ROLLBACK TO [SAVEPOINT] 保存点名称;//回滚到某一个保存点
3. RELEASE SAVEPOINT 保存点名称;//删除

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update account set balance=balance-20 where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> savepoint action1;
Query OK, 0 rows affected (0.02 sec)

mysql> select * from account;
+----+--------------+---------+
| id | name     | balance |
+----+--------------+---------+
| 1 | 老王媳妇 |   60 |
| 2 | 老王    |   30 |
+----+--------------+---------+

mysql> update account set balance=balance+30 where id = 2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> rollback to action1;//回滚到action1保存点
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+--------------+---------+
| id | name     | balance |
+----+--------------+---------+
| 1 | 老王媳妇 |   60 |
| 2 | 老王    |   30 |
+----+--------------+---------+

更多关于MySQL相关内容感兴趣的读者可查看本站专题:《MySQL事务操作技巧汇总》、《MySQL索引操作技巧汇总》、《MySQL常用函数大汇总》、《MySQL日志操作技巧大全》、《MySQL存储过程技巧大全》及《MySQL数据库锁相关技巧汇总》

希望本文所述对大家MySQL数据库计有所帮助。

(0)

相关推荐

  • 在Mysql存储过程中使用事务实例

    复制代码 代码如下: CREATE DEFINER=`root`@`localhost` PROCEDURE `createBusiness`(parameter1 int)BEGIN    #Routine body goes here...    DECLARE flag int DEFAULT parameter1;#声明变量flag,将参数值赋给该变量    DECLARE uuidStr VARCHAR(32);#声明一个长度为32位的字符串    DECLARE currentTim

  • MySQL数据库事务隔离级别介绍(Transaction Isolation Level)

    数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 复制代码 代码如下: #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. [mysqld] transaction-isolation = REPEATABLE-READ 这里全局默认是REPEATABLE-READ,其实MySQL本来默认也是这个级别

  • Mysql中的事务是什么如何使用

    什么是事务? 事务是逻辑上的一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务 注意:mysql数据支持事务,但是要求必须是innoDB存储引擎 解决这个问题: mysql的事务解决这个问题,因为mysql的事务特性,要求这组操作,要不全都成功,要不全都失败,这样就避免了某个操作成功某个操作失败.利于数据的安全 如何使用: (1)在执行sql语句之前,我们要开启事务 start transaction; (2)正常执行我们的sql语句 (3)当sql语句执行完毕,存在两

  • 全面了解MySql中的事务

    最近一直在做订单类的项目,使用了事务.我们的数据库选用的是MySql,存储引擎选用innoDB,innoDB对事务有着良好的支持.这篇文章我们一起来扒一扒事务相关的知识. 为什么要有事务? 事务广泛的运用于订单系统.银行系统等多种场景.如果有以下一个场景:A用户和B用户是银行的储户.现在A要给B转账500元.那么需要做以下几件事: 1. 检查A的账户余额>500元: 2. A账户扣除500元: 3. B账户增加500元: 正常的流程走下来,A账户扣了500,B账户加了500,皆大欢喜.那如果A账

  • MySql的事务使用与示例详解

    在MySQL中,事务就是一个逻辑工作单元的一系列步骤.事务是用来保证数据操作的安全性. 事务的特征: 1.Atomicity(原子性) 2.Consistency(稳定性,一致性) 3.Isolation(隔离性) 4.Durability(可靠性) 注:事务只针对对数据数据产生影响的语句有效. show engines //查看mysql锁支持的数据引擎 MyISAM不支持事物,InnoDB支持事物 默认情况下,MySQL将以自动提交模式运行,这意味着没一条小命令都将当做一个只有一条命令的事物

  • MySQL存储过程例子(包含事务,输出参数,嵌套调用)

    drop procedure if exists pro_rep_shadow_rs; delimiter | ---------------------------------- -- rep_shadow_rs -- 用来处理信息的增加,更新和删除 -- 每次只更新上次以来没有做过的数据 -- 根据不同的标志位 -- 需要一个输出的参数, -- 如果返回为0,则调用失败,事务回滚 -- 如果返回为1,调用成功,事务提交 -- -- 测试方法 -- call pro_rep_shadow_rs

  • mysql 锁表锁行语句分享(MySQL事务处理)

    复制代码 代码如下: mysql_query("set autocommit=0"); $list_one = $db->fetch_first("select * from prizes where id = ".$id." FOR UPDATE"); $db->query("DELETE from prizes WHERE id =".$list_one['id']); mysql_query("co

  • MySQL中Innodb的事务隔离级别和锁的关系的讲解教程

    前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. 一次封锁or两段锁? 因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会

  • 利用mysql事务特性实现并发安全的自增ID示例

    项目中经常会用到自增id,比如uid,最简单的方法就是用直接用数据库提供的AUTO_INCREMENT,但是如果用户量非常大,几千万,几亿然后需要分表存储的时候呢,这种方案就搞不定了,所以最好有一个全局的自增ID的生成器,不管是否分表,都能从生成器中获取到全局自增的ID. 实现方法应该有很多,不过所有的方案都需要解决一个问题,就是保证在高并发的情景下,数据获取依然正确,每次获取的ID都不会重复. 这里我分享两种利用mysql的innodb的事务特性来实现的方案,一种是实现过了的,另一种没有试验过

  • 简单介绍MySQL中的事务机制

    从一个问题开始 最近银行这个事情闹的比较厉害啊,很多储户的钱放在银行,就不翼而飞了,而银行还不管不问,说是用户的责任,打官司,用户还能输了,这就是"社会主义".咱还是少发牢骚,多种树,莫谈国事. 说到银行存钱,就不得不说一下从银行取钱这件事情,从ATM机取钱这件简单的事情,实际上主要分为以下几个步骤: 登陆ATM机,输入密码: 连接数据库,验证密码: 验证成功,获得用户信息,比如存款余额等: 用户输入需要取款的金额,按下确认键: 从后台数据库中减掉用户账户上的对应金额: ATM吐出钱:

  • mysql存储过程事务管理简析

    ACID:Atomic.Consistent.Isolated.Durable 存储程序提供了一个绝佳的机制来定义.封装和管理事务. 1,MySQL的事务支持 1)MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关: Sql代码 复制代码 代码如下: MyISAM:不支持事务,用于只读程序提高性能 InnoDB:支持ACID事务.行级锁.并发 Berkeley DB:支持事务 MyISAM:不支持事务,用于只读程序提高性能 InnoDB:支持ACID事务.行级锁.并发 Ber

  • mysql实现事务的提交和回滚实例

    mysql创建存储过程的官方语法为: 复制代码 代码如下: START TRANSACTION | BEGIN [WORK]COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]SET AUTOCOMMIT = {0 | 1} 我这里要说明的mysql事务处理多个SQL语句的回滚情况.比如说在一个存储过程中启动一个事务,这个事务同时往三个表中插入数据,每插完一张表需要

随机推荐