1、 数据库事务的概念
- 在数据库中,所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。
- 为确保数据库中数据的一致性,数据的操纵应当是离散的成组的逻辑单元:当它全部完成时,数据的一致性可以保持,而当这个单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。
- 事务的操作:先定义开始一个事务,然后对数据作修改操作,这时如果提交(COMMIT),这些修改就永久地保存下来,如果回退(ROLLBACK),数据库管理系统将放弃您所作的所有修改而回到开始事务时的状态。
2、事务的ACID
- 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
- 隔离性(Isolation)事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
- 数据库的事务由下列语句组成:
一组DML语句,修改的数据在他们中保持一致
一个 DDL (Data Define Language) 语句
一个 DCL (Data Control Language)语句
DCL(Grant(赋于权限 ) / Revoke(回收权限 ))
1、开始于第一个执行的语句
-
2、结束于:
- 用户执行COMMIT 或 ROLLBACK。
- 单个的DDL or DCL 语句。
- 用户连接异常错误,或者用户断开连接 。
- 系统崩溃。
3、事务控制语句
- COMMIT和 ROLLBACK可以显式的控制事务。
- 好处:
- 1、保证数据一致性,修改过的数据在没有提交之前是不能被其他用户看到的。
- 2、在数据永久性生效前重新查看修改的数据
- 3、将相关操作组织在一起,一个事务中相关的数据改变或者都成功,或者都失败。
4、事务的隔离级别
SQL 中定义了四种隔离级别, 每种级别都规定了一个事务所做的修改,哪些在事务内和事务间是可见的, 哪些是不可见的. 较低的隔离通常可以执行更高的并发, 系统的开销也更低.
-
SQL 标准中的四种隔离有:
-
READ UNCOMMITED
(未提交读)
在 READ UNCOMMITED 级别中, 事务的修改, 即使没有提交, 对其他事务也是可见的. 其他事务可以读取此事务中的未提交的数据, 这也被称为脏读(Dirty Read). 此事务隔离级别会导致很多问题, 并且性能也不会比其他事务隔离级别好多少, 因此在实际环境中很少使用. -
READ COMMITED
(提交读)
大多数的数据库默认隔离级别都是 READ COMMITED, 但是 MySQL 并不是. 在 READ COMMITED 级别中, 一个事务从开始到提交之前, 所做的任何修改对其他事务都是不可见的.
这个级别有时候也叫做不可重复读(nonrepeatable read), 因为两次执行相同的查询, 可能会得到不一样的结果.
REPEATABLE READ
(可重复读),可重复读是 MySQL 的默认事务隔离级别.
REPEATABLE READ 解决了脏读的问题. 该级别保证了在同一个事务中多次读取同样记录的结果时一致的. 但是理论上, 可重复读隔离级别还是无法解决另一个幻读(Phantom Read)的问题. 所谓幻读, 指的是当某个事务在读取某个范围内的记录时, 另外一个事务又在该范围内插入了新的记录, 当之前的事务再次读取该范围的记录时, 会产生幻行(Phantom Row).SERIALIZABLE
(可串行化)
SERIALIZABLE 是最高的隔离级别. 他通过强制事务串行执行, 避免了前面说的幻读的问题. 简单来说, SERIALIZABLE 会在读取的每一行数据上都加上锁, 所以可能导致大量的超时和锁争用的问题. 实际应用中也很少用到这个隔离级别, 只有在非常需要确保数据的一致性而且可以接受没有并发的情况下, 才考虑采用该级别.
-
5、死锁
- 死锁是指两个或多个事务在同一个资源上相互占用, 并请求锁定对方占用的资源, 从而导致恶性循环的现象. 当多个事务试图以不同顺序锁定资源时, 就可能产生死锁.
- 死锁发生以后, 只有部分或者完全回滚其中一个事务, 才能打破死锁.
6、MySQL 中的事务
在 MySQL 提供的众多存储引擎中, 只有 InnoDB 和 NDB Cluster 支持事务.
-
关于自动提交(AUTOCOMMIT)
- MySQL 默认采用自动提交(AUTOCOMMIT) 模式. 即如果不显示地开始一个事务, 则每个操作都被当做一个事务执行提交操作.
我们可以通过SHOW VARIABLES LIKE 'autocommit';
- MySQL 默认采用自动提交(AUTOCOMMIT) 模式. 即如果不显示地开始一个事务, 则每个操作都被当做一个事务执行提交操作.
查询当前是否已经开启了字段提交事务, 例如:
- 如果是 ON, 则表示已经开启了, 0 或 OFF 表示禁用.
- 可以通过
set autocommit=0;
来禁用自动提交:
7、自动提交和非自动提交的区别
- 下面以一个例子来展示 autocommit 启动和非启动时的区别.首先建立一个测试用的表:
接着关闭自动提交功能:
mysql> set autocommit=0;
然后插入一个数据:
mysql> INSERT INTO user (
id,
name,
age) VALUES (1, 'xys', 18);
-
接着查看数据:
数据库中可以查询到这条数据了.
-
但是我们通过 SHOW BINLOG EVENTS 查看操作日志:
会发现上面的输出中, 并没有插入数据相关的记录, 并且此时如果我们退出 MySQL 的话, 那么我们插入的数据并没有被保存:
- 如果我们不退出, 而是输入COMMIT; 时, 那么此时数据才真正保存到 MySQL 中:
从上面的操作中我们可以看到, 当禁用了 AUTOCOMMIT 后, 我们对数据库的写入操作并不会实际落地到数据库中, 除非我们显示地提交事务.
-
接下来, 我们使能 AUTOCOMMIT, 再次进行相同的操作.
然后插入一个数据:
mysql> INSERT INTO user (
id,
name,
age) VALUES (1, 'xys', 18);
-
接着查看数据: