事务 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;