专栏首页DBA随笔Innodb事务的一些概念

Innodb事务的一些概念

innodb之事务
Innodb事务的一些概念
1

事务简介

事务是由一系列SQL组成的逻辑处理单元,要么全'部'执行,要么全'不'执行。事务具有四个属性,也就是常说的ACID属性,分别代表原子性,一致性,隔离性和持久性,再重新巩固一下吧:

原子性(Atomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。

一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。

隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。

持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。

2

并发事务带来的问题

事务的运行经常是并发的,因为并发的事务执行效率高于串行执行,然而,并发事务处理也带来了一些其他的问题。

更新丢失(Lost Update):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题--最后的更 新覆盖了由其他事务所做的更新。例如,两个编辑人员制作了同一文档的电子副本。每个编辑人员独立地更改其副本,然后保存更改后的副本,这样就覆盖了原始文 档。最后保存其更改副本的编辑人员覆盖另一个编辑人员所做的更改。如果在一个编辑人员完成并提交事务之前,另一个编辑人员不能访问同一文件,则可避免此问 题。

脏读(Dirty Reads):一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加 控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做"脏读"。

不可重复读(Non-Repeatable Reads):一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”。

幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。

3

事务的隔离级别

在上面讲到的并发事务处理带来的问题中,“更新丢失”通常是应该完全避免的。但防止更新丢失,并不能单靠数据库事务控制器来解决,需要应用程序对要更新的数据加必要的锁来解决,因此,防止更新丢失应该是应用的责任。

“脏读”、“不可重复读”和“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。数据库实现事务隔离的方式,基本上可分为以下两种。

  一种是在读取数据前,对其加锁,阻止其他事务对数据进行修改。

   另一种是不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一 致 性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本,因此,这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC),也经常称为多版本数据库。

  数据库的事务隔离越严格,并发副作用越 小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的。同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏 感,可能更关心数据并发访问的能力。

为了解决“隔离”与“并发”的矛盾,ISO/ANSI SQL92定义了4个事务隔离级别,每个级别的隔离程度不同,允许出现的副作用也不同,应用可以根据自己的业务逻辑要求,通过选择不同的隔离级别来平衡 “隔离”与“并发”的矛盾。下面的表很好地概括了这4个隔离级别的特性。

需要注意的是,在读数据的一致性方面,读未提交是最低级别,只能保证不读取物理上损坏的数据,不可重复读是语句级别,可重复度是事务级别,而序列化、也叫串行化是最高级别。mysql默认的事务隔离级别为repeatable-read,可以通过下面的方法查看:

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.03 sec)

关于事务概念的介绍大概就这么多,最后补充几个需要关注的点:

1、事务隔离级别为读提交时,写数据只会锁住相应的行

2、事务隔离级别为可重复读时,如果检索条件有索引(包括主键索引)的时候,默认加锁方式是next-key 锁;如果检索条件没有索引,更新数据时会锁住整张表。一个间隙被事务加了锁,其他事务是不能在这个间隙插入记录的,这样可以防止幻读。

3、事务隔离级别为串行化时,读写数据都会锁住整张表

4、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。

4

MySQL中事务的处理语法

事务控制语句:

BEGIN或START TRANSACTION;显式地开启一个事务;

COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的;

ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;

SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;

RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;

ROLLBACK TO identifier;把事务回滚到标记点;

SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。

MYSQL 事务处理主要有两种方法:

1、用 BEGIN, ROLLBACK, COMMIT来实现

BEGIN 开始一个事务

ROLLBACK 事务回滚

COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:

SET AUTOCOMMIT=0 禁止自动提交

SET AUTOCOMMIT=1 开启自动提交

最后给出一个测试用例用来方便理解:

mysql> use test_db;
Database changed
mysql> CREATE TABLE tbl_test( id int(5)) engine=innodb;  # 创建数据表
Query OK, 0 rows affected (0.04 sec)

mysql> select * from tbl_test;
Empty set (0.01 sec)

mysql> begin;  # 开始事务
Query OK, 0 rows affected (0.00 sec)

mysql> insert into tbl_test values (5);
Query OK, 1 rows affected (0.01 sec)

mysql> insert into tbl_test values (6);
Query OK, 1 rows affected (0.00 sec)

mysql> commit; # 提交事务
Query OK, 0 rows affected (0.01 sec)

mysql>  select * from tbl_test;
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)

mysql> begin;    # 开始事务
Query OK, 0 rows affected (0.00 sec)

mysql>  insert into tbl_test values(7);
Query OK, 1 rows affected (0.00 sec)

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

mysql>   select * from tbl_test;   # 因为回滚所以数据没有插入
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)

后续还将用一篇文章对事务的四种隔离级别做相应的示例说明。

本文分享自微信公众号 - DBA随笔(gh_acc2bbc0d447),作者:AsiaYe

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 事务分类---innodb存储引擎笔记+闲扯

    事务想必大家都比较熟悉,我们可能张口就来ACID,但是事务的分类,之前我没怎么关心过,今天看姜大神的书MySQL技术内幕---innodb存储引擎看到了这...

    AsiaYe
  • MySQL并行复制解析

    在MySQL的主从复制架构中,主库上经常会并发的执行很多SQL,只要这些SQL没有产生锁等待,那么同一时间并发好几个SQL线程是没有问题的。

    AsiaYe
  • MySQL5.7并行复制解析

    在之前的文章中,我对MySQL并行复制做过一个简单的介绍,有兴趣可以翻看5月19日的文章《MySQL并行复制解析》。今天针对这个问题,补充一些知识点。

    AsiaYe
  • SQL Server数据库高级进阶之事务实战演练

    跟着阿笨一起玩NET
  • Mysql进阶垫脚石 -- 到底什么是数据库事务?

    事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务处理可以确保...

    陈哈哈
  • 关于数据库事务

    转账是最经典也常被拿出来说的例子。假如小明要给小红转账1000元,这个操作会涉及到两个关键:将小明的余额减少1000元,将小红的余额增加1000元。但万一在这两...

    happyJared
  • 浅谈Spring的事务隔离级别与传播行为

    Q:在一个批量任务执行的过程中,调用多个子任务时,如果有一些子任务发生异常,只是回滚那些出现异常的任务,而不是整个批量任务,请问在Spring中事务需要如何配置...

    JAVA日知录
  • mysql的四种隔离级别

    b事务中多次读取同一个值,b事务多次读的过程中,如果a事务把值改了,并且事务也提交了,这种情况下,a事务读的值依然是最开始读的那个值。

    IT云清
  • MySQL的事务隔离级别是什么?

    想必事务大家都已经非常熟悉了,它是一组SQL组成的一个执行单元,要么全执行要么全不执行,这也是它的一个特性——原子性。而事务的应用场景也非常广泛,最经典的就是转...

    平也
  • 聊聊分布式事务

    这次使用分布式事务框架过程中了学习了一些分布式事务知识,所以本文我们就来聊聊分布式事务那些事。首先我们先回顾下什么是事务。

    andyxh

扫码关注云+社区

领取腾讯云代金券