最近在做项目时遇到了操作多个表的操作,要保证所有的sql操作要么全部完成或者全部失败,在之前的学习中只知道mysql的事务性,这次算是实践吧.
一、实现过程
1.首先是开启事务,在事务代码外面用try catch 捕获异常 在try中开启事务startTransaction(),对于在try中的任何error都将捕获,catch中将进行回滚,sql表数据不变,返回失败。
2.之后就是操作数据库,insert/update... 判断这些操作的返回值,如果是false抛出异常在catch下打出log后rollback进行回滚 如果操作数据库命令全部成功 在try的最后一行进行commit()提交。这就完成了一个事物。
下来也了解了一下try catch 的使用规范 和mysql的事务性。
因为当时底层框架直接有异常类,所以自己也没有新建自己的异常类进行处理。
二、知识点学习总结
1. mysql的事务性
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 事务用来管理 insert,update,delete 语句
事务的四个特性:原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)
1>原子性:多条操作"整合"为一条命令,要么全部成功,要么全部失败,如果失败,会进行回滚,如果全部成功最后才会进行提交
2>一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
引用一个阐述一致性和原子性之间的区别的博客:
3>隔离型:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
4>持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
隔离性中有几个隔离的级别:读未提交(Read uncommitted)----可以读取还未提交的事务数据,如果提前读取到的未提交数据在后面rollback会发生脏读情况。
读提交(Read committed)-----只能读取提交的事务,如果读取时另一个事务还未提交操作数据,在当前事务读取了之后另一事务再进行提交那么当前数据操作的就是之前的数据,类似于"脏读"
重复读( Repeatable read)(mysql 默认隔离级别)-----重复读 重复读,就是在开始读取数据(事务开启)时,不再允许修改操作,可以进行INSERT操作(幻读)eg:事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。重复读针对的是update操作不能并行,而insert操作是可以并行操作的,
// 问题:在做一个项目时需要对某个隔离级别为重复读的表中记录进行insert,首先需要进行查表,根据表符合条件的最大的页码生成对应insert数据的page+1,这时因为不是update所以没有限制,导致两个进程或者事务几乎同时访问并且
序列化(Serializable) Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
2. 各个数据读取中脏读,幻读含义以及存在场景
脏读:读取sql中数据时读取到另一个事务尚未提交的数据,而之后该事务回滚,那么读取到的数据称为脏数据,这个过程称为脏读。这种情况经常发生在隔离级别为读未提交
幻读:第一次读取到的数据为A,在操作之后(不修改A数据)再读取A数据,这是A数据改为了A+1,这就称为幻读,这种一般发送在可重复读。
事务隔离级别介绍以及存在问题详细讲述文章借鉴: