MySQL:事务

153 阅读3分钟

事务 transaction

什么是事务?

一个事务是一个完整的业务逻辑单元,不可分割

比如:银行账户转账,从A账户向B账户转账,需要执行两条update语句

update t_act set balance = balance-10000 where actno = 'acto-001';
update t_act set balance = balance+10000 where actno = 'acto-002';

以上两条DML语句必须同时成功,或者同时失败,不允许一条成功,一条失败。若想保证以上两条DML语句同时成功或失败,那么就需要使用数据库的 “ 事务机制 ”

和事务相关的语句只有DML语句(delete,update,insert)

为什么?因为他们这三条语句都是和数据库表当中的“数据”相关的

事务的存在是为了保证数据的完整性,安全性

假设所有业务都能使用一条DML语句搞定,那就不需要事物了

但实际情况不是这样的,通常一个 “ 事儿(事务(或者叫业务))” 需要多条DML语句共同联合完成

此外,有关事务的关键字还有savepoint,作用是rollback的数据回滚到savepoint处,清空从savepoint之后的历史记录,而不会清空前面的历史记录

事务的四大特性

事务包括四大特性:ACID

  • 原子性(Atomicity)

    事务是最小的工作单元,不可再分

  • 一致性(Consistency)

    事务必须保证多条DML语句同时成功或者同时失败

  • 隔离性(Isolation)

    事务A与事务B之间具有隔离,但有时业务需要两个事务协作完成,所以隔离程度分为四个等级

  • 持久性(Durability)

    说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束

事务的隔离性

MySQL数据库默认的隔离级别是:repetable read

Oracle数据库默认的隔离级别是:read committed

事务隔离性存在隔离级别,理论上隔离级别包括四个:

第一级别:读未提交(read uncommitted)

对方事务还没有提交,我们当前事务可以读取到对方未提交的数据

读未提交也叫作脏读(Dirty Read)现象

第二级别:读已提交(read committed)

对方事物提交之后的数据我方可以读取到

这种隔离级别解决了:脏读现象

存在的问题是:不可重复读

第三级别:可重复读(repeatable read)

这种隔离级别解决了不可重复读

存在的问题是:幻读现象,读取到的数据是幻象 (只要事务不结束,读到的数据永远是幻象,对方提交了也读不到,要自己结束事务再重新读对方才行)

第四级别:序列化读 / 串行化读(Serializable)

解决了所有问题

缺点是:效率低,需要事物排队

A 操作数据库,没提交,B 就查不到(要排队),A 提交了之后 B 那边才出结果。

演示事务

  • MySQL事务默认情况下是自动提交的

    也就是执行任意一条DML语句则提交一次

  • 怎么关闭自动提交?

    start transaction;

  • 用 auto_increment 设置的自动主键约束,就算回滚了,没提交,主键值也不会连号,会继续往下

MySQL 默认自动提交机制

每条 SQL 语句都会被当做一个单独的事务自动执行。但有些情况下,我们需要关闭事务自动提交来保证数据的一致性

开启事务,即手动提交

完事之后一定要记得手动 commit

查看数据库默认提交方式

mysql> SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set, 1 warning (0.01 sec)

设置事务的全局隔离级别

四个隔离级别任君挑选

set global transaction isolation level 
    read uncommitted / read committed / repeatable read / serializable

注意,设置完成之后,要退出数据库,重新进入才能生效

查看事务的全局隔离级别

旧版本MySQL的:
select @@global.tx_isolation;
​
新版本用这个:
select @@transaction_isolation;