基本概念
什么是事务?
事务从本质上讲就是:逻辑上的一组操作,组成这组操作的各个逻辑单元在不同的服务甚至服务器上,保证它们要成功就都成功,要失败就都失败。
事务的四大特性
提到事务就不得不提事务的四大特性(基本特征) ACID:
- 原子性(atomicity):“原子”的本意是“不可再分”,事务的原子性表现为一个事务中涉及到的多个操作在逻辑上缺一不可。事务的原子性要求事务中的所有操作要么都执行,要么都不执行。
- 一致性(consistency):“一致”指的是数据的一致,具体是指:所有数据都处于满足业务规则的一致性状态。一致性原则要求:一个事务中不管涉及到多少个操作,都必须保证事务执行之前数据是正确的,事务执行之后数据仍然是正确的。如果一个事务在执行的过程中,其中某一个或某几个操作失败了,则必须将其他所有操作撤销,将数据恢复到事务执行之前的状态,这就是回滚。
- 隔离性(isolation):在应用程序实际运行过程中,事务往往是并发执行的,所以很有可能有许多事务同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。隔离性原则要求多个事务在并发执行过程中不会互相干扰。
- 持久性(durability):持久性原则要求事务执行完成后,对数据的修改永久的保存下来,不会因各种系统错误或其他意外情况而受到影响。通常情况下,事务对数据的修改应该被写入到持久化存储器中。
并发事务可能会带来的问题
- 脏读:一个事务可以读取另一个事务未提交的数据
- 不可重复读:一个事务可以读取另一个事务已提交的数据 单条记录前后不匹配
- 虚读(幻读):一个事务可以读取另一个事务已提交的数据 读取的数据前后多了或者少了
我们实践出真知:举个例子,mysql(5.6.16)
首先创建一张表:
sql复制代码CREATE TABLE `test_account` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`money` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `test_account` VALUES (1, '张三', 1000);
INSERT INTO `test_account` VALUES (2, '李四', 1000);
INSERT INTO `test_account` VALUES (3, '王五', 1000);
查看当前数据库隔离级别(详见下文):
sql复制代码select @@tx_isolation;
# 结果:READ-COMMITTED
# 设置事务的隔离级别
# set tx_isolation='隔离级别';
# 我们简单做下脏读的复现,开启俩个事务,第一个窗口做数据修改,但不提交:
start transaction;
UPDATE test_account set money = money - 100 WHERE id = 1;
# 第二个窗口做数据查询,利用查询到的值去做数据处理:
start transaction;
SELECT money from test_acco