一、数据库存储事务机制概念¶
事务(Transaction)可以更通俗的理解为交易,所以事务会伴随着交易类的业务类型出现的概念(工作模式);
现实生活中存在很多的交易行为,比如:物换物的等价交换、货币换物的等价交换、虚拟货币换物(虚拟物品)的等价交换;
因此就需要考虑如何保证现实生活中交易过程的和谐,一般会有法律、道德等方面规则进行约束;
而在数据库服务中为了保证线上交易的"和谐",便加入了"事务"工作机制
二、数据库存储事务机制特性¶
在数据库服务中引入事务机制概念,主要是为了应用事务机制的相关特性处理安全一致性问题,其中事务机制主要包含的特性有:
特性一:原子性(Atomicity)
原子性表示一个事务生命周期中的DML语句,要么全成功要么全失败,不可以出现中间状态;
语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log
Begin:DML01 DML02 DML03 Commit;
特性二:一致性(Consistency)
一致性表示一个事务发生前、中、后,数据都最终保持一致,即读和写都要保证一致性;
事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障;
CR + Double write
特性三:隔离性(Isolation)
隔离性表示一个事务操作数据行的时候,不会受到其他事务的影响,主要利用锁机制来保证隔离性;
特性四:持久性(Durability)
持久性表示一旦事务进行了提交,即可永久生效(落盘)
保证事务提交后不会因为宕机等原因导致数据丢失;实现主要基于redo log
事务ACID相关知识官方说明:https://dev.mysql.com/doc/refman/8.0/en/mysql-acid.html
三、数据库存储事务生命周期¶
在运用事务机制完成相关工作任务时,对于事务使用是存在生命周期概念的,标准显示的事务生命周期控制语句有:
# 开启事务机制
-- 方式一
begin;
-- 方式二
start transaction;
# 提交事务任务
commit;
# 回滚事务操作
rollback;
说明:事务生命周期中,只能使用DML语句,其中包括:select、update、delete、insert;DDL语句会隐式进行提交
事务的生命周期操作演示:
# 进行测试数据库查询数据
mysql> use world;
mysql> select * from city limit 10;
# 进行测试数据库数据撤销修改
-- 由于是采用事务进行的修改,所以只是在内存层面进行的修改,并没有对磁盘上的数据进行修改;
mysql> begin;
mysql> update city set population=10 where id=1;
mysql> update city set population=10 where id=2;
-- 由于是采用事务进行的修改,此时看到的数据信息只是内存层面的修改信息
mysql> select * from city limit 10;
-- 由于是采用事务进行的撤销,会读取undo文件信息,将事务操作撤回到事务开始前的状态
mysql> rollback;
-- 由于是采用事务进行的修改,当撤销操作执行完,看到数据信息还是原来的;
mysql> select * from city limit 10;
# 进行测试数据库数据永久修改
-- 由于是采用事务进行的修改,所以只是在内存层面进行的修改,并没有对磁盘上的数据进行修改;
mysql> begin;
mysql> update city set population=10 where id=1;
mysql> update city set population=10 where id=2;
-- 由于是采用事务进行的修改,此时看到的数据信息只是内存层面的修改信息
mysql> select * from city limit 10;
-- 由于是采用事务进行的提交,会加载redo文件信息,将事务内存层面的修改同步到磁盘中(完成了D特性)
mysql> commit;
-- 由于是采用事务进行的修改,当执行操作执行完,看到数据信息将永久保存下载;
mysql> select * from city limit 10;
四、数据库存储事务提交方式¶
方式一:在事务生命周期管理过程中,事务的提交机制可以采用自动提交方式(auto_commit)
事务自动提交方式作用说明:
事务自动提交表示在没有显示的使用begin语句的时候,执行DML操作语句时,会在DML操作语句前自动添加begin;
并在DML操作语句执行后自动添加commit;
在生产环境中,若处于频繁事务业务场景中,建议关闭autocommit自动提交功能,或者每次事务执行的时候;
都进行显示的执行begin和commit
事务自动提交方式参数信息:
-- 在事务自动提交功能设置修改时,设置为1表示开启自动提交,设置为0表示关闭自动提交
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
事务自动提交方式参数修改:
# 临时关闭事务自动提交功能
-- 配置调整后,重新登录mysql数据库生效
mysql> set global autocommit=0;
# 永久关闭事务自动提交功能
-- 配置调整后,重新启动mysql数据库生效
[root@master ~]# vim /etc/my.cnf
...
...
[mysqld]
autocommit=0
事务自动提交方式设置方式优点缺点说明:
| 序号 | 参数配置 | 优势 |
|---|---|---|
| 情况01 | autocommit=0 关闭事务自动提交 |
可以编写多个关联的DML,进行一次性提交操作,若出现异常可以回滚 符合原子特性 |
| 劣势 | ||
| 可能出现多个关联的DML,只是完成了部分操作,这时就可能等待状态 基于隔离特性,操作的数据表或数据行就会进入锁定状态 |
||
| 参数配置 | 优势 | |
| 情况02 | autocommit=1 开启事务自动提交 |
可以出现多个关联的DML,逐行操作自动提交,就可以不用处于锁等待状态 |
| 劣势 | ||
| 可能出现多个关联的DML,,每执行一条就进行提交,会造成多个语句执行不符合原子性 |
方式二:在事务生命周期管理过程中,事务的提交机制可以采用隐式提交方式:
在进行事务操作时,需要注意操作语句必须都是DML语句,如果中间插入了DDL语句,也会造成之前的事务操作自动提交;
-- 这种情况出现会破坏原本事务的原子性
begin; DML1; DML2; DDL1; COMMIT; DML3; COMMIT;
隐式自动提交方式语句:
在出现隐式自动提交时,可能导致提交的非事务语句有:
| 序号 | 语句类型 | 涉及命令 |
|---|---|---|
| 01 | DDL语句类型 | alter、create、drop |
| 02 | DCL语句类型 | grant、revoke、set password |
| 03 | 锁定语句类型 | lock tables、unlock tables |
| 04 | 其他语句类型 | truncate table、load data infile、select for update |
说明:在多个数据库会话窗口中,A窗口的所有事务性DML操作,不会受到B窗口的非事务语句影响,同一会话窗口会有影响;
-- 关闭显示自动提交
mysql> set global autocommit=0;
-- 创建数据库db20
mysql> create database db20;
-- 创建表test1
mysql> create table db20.test1 (id int,name char(5));
-- 开启事务机制
mysql> begin;
-- 使用DML语句连续插入3条数据
mysql> insert into db20.test1 values (1,'a');
mysql> insert into db20.test1 values (2,'b');
mysql> insert into db20.test1 values (3,'c');
-- 查看表内数据
mysql> select * from db20.test1;
+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
| 3 | c |
+------+------+
3 rows in set (0.00 sec)
-- 回滚
mysql> rollback;
-- 再次进行观察,观察因执行回滚导致数据没有保存,为空
mysql> select * from db20.test1;
Empty set (0.00 sec)
-- 使用DDL语句新建表test2
mysql> create table db20.test2 (id int,name char(5));
-- 执行rollback操作观察是否撤回建表的这个操作
mysql> rollback;
-- 结论:DDL语句会自动隐式的提交commit语句,无法使用rollback回滚操作
mysql> show tables from db20 like 'test2';
+------------------------+
| Tables_in_db20 (test2) |
+------------------------+
| test2 |
+------------------------+
1 row in set (0.00 sec)
隐式自动回滚情况分析:
- 情况一:在事务操作过程中,会话窗口自动关闭了,会进行隐式自动回滚;
- 情况二:在事务操作过程中,数据库服务被停止了,会进行隐式自动回滚;
- 情况三:在事务操作过程中,出现事务冲突死锁了,会进行隐式自动回滚;
注意事项:从库中尽量不要关闭此功能 autocommit=0,也就是说最好不要隐式提交