一.事务的基本要素:

1.1原子性:事务开始后所有操作,要么全部做完,要么全部不做完。比如:A向B转账,不可能A扣了钱,B却没收到。
1.2一致性:事务开始前和结束后,数据库的完整性约束没有破坏。比如:A向B转账,不可能A扣了50,B却收到30。
1.3隔离性:数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
1.4持久性:事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

二.事务并发的问题:

2.1脏读:A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据;A读取了此次脏数据,称为脏读。
2.2不可重复读(侧重于修改):事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。(事务A内部的相同查询语句子不同时刻读出的结果不一致,不符合隔离性。)
2.3幻读(侧重于新增或者删除):系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。(事务A读取到了事务B提交的新增数据,不符合隔离性。)
2.4更新丢失或者脏写:当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题–最后的更新覆盖了由其他事务所做的更新。

三.事务的隔离级别:

3.1读未提交(read uncommitted):一个事务还没提交,他做的变更就能被别的事务看到。也就是事务B读到了事务A未提交的数据,可能会出现脏读的情况;可以通过”排他锁”,可以避免更新数据的丢失。
3.2读提交(read committed):一个事务提交之后,他做的变更才会被其他事务看到。事务A先读取了数据,事务B更新数据并提交事务,事务A再次读取更新的数据,出现不可重复读,避免了脏读。
3.3可重复读(repeatable read):一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。这样避免了不可重复读和脏读,但是有时可能会出现幻读。
3.4串行化(serializable):是对于同一行记录, “ 写 ” 会加 “ 写锁 ” , “ 读 ” 会加 “ 读锁 ” 。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读。
圖片.png
四种隔离级别中最高的是串行化,最低的是读未提交,级别越高,执行效率越低。
mysql数据库默认的是可重复读。如图:
圖片.png

查看当前数据库事务隔离级别:show variables like ‘tx_isolation’或者SELECT @@tx_isolation; 设置事务隔离级别:set tx_isolation=’REPEATABLE-READ’; Mysql默认的事务隔离级别是可重复读,用Spring开发程序时,如果不设置隔离级别默认用Mysql设置的隔 离级别,如果Spring设置了就用已经设置的隔离级别


四、隔离级别的演示

4.1读未提交(产生现象—脏读)
— 设置隔离级别 **set tx_isolation=’read-uncommitted’;
圖片.png
4.2读已提交(产生不可重复读现象(前后查询的内容不一致))
— 设置隔离级别 s**et tx_isolation=’read-committed’;
圖片.png
圖片.png
4.3可重复读(可能会产生幻读现象,解决了不可重复读问题)
— 设置隔离级别 set tx_isolation=’repeatable-read’;
圖片.png
圖片.png
4.4可串行化(解决了幻读现象)
— 设置隔离级别 set tx_isolation=’serializable’;
圖片.png
圖片.png