当前位置: 首页 > 后端技术 > Java

数据库事务与事务隔离级别

时间:2023-04-02 00:04:50 Java

数据库事务数据库事务可以理解为一组满足数据库ACID特性的操作。我们可以使用COMMIT命令来提交事务,使用ROLLBACK来回滚事务。MySQL默认使用自动提交(AUTOCOMMIT)模式。如果您没有使用STARTTRANSACTION语句显式启动事务,则每个查询都会自动作为事务提交。数据库的acid特性原子性(atomicity)原子性是指操作不能再被分割,要么全部成功,要么全部失败。回滚可以用日志来实现,日志记录了事务进行的修改操作,这些修改操作在回滚的时候是可以逆向的。一致性(consistency)一致性是指一个操作必须从一种一致状态转换到另一种一致状态。什么是一致状态?就拿转账来说,如果我给你转钱,那我的钱肯定会减少,如果你增加,我不可能有很多钱,你的钱会凭空增加。隔离(isolation)隔离是指对数据库的一个操作不能被其他操作影响。例如多个用户同时开启交易,则用户a开启的交易不会受到用户b开启的交易的影响。持久性(persistence)一旦你的交易被提交(commit),所有的修改和产生的数据都会被永久记录下来。即使系统崩溃,交易执行的结果也不能丢失。除非你的硬盘驱动器全部损坏0-0。并发带来的问题就是修改丢失了。两个事务同时修改一行记录,前面修改的数据被后面修改的数据覆盖。之前修改的数据无效:这里T1先修改了数据为50,但随后又被T2覆盖,导致对T的修改无效。脏数据读取和上面差不多。两个并发事务,A事务和B事务同时操作同一行数据,A修改数据后,这个数据被B事务读取,然后如果A回滚事务,B会读到无效的“脏数据””举个例子:小明给我打了1000元,我查了一下余额,发现我还有1000元,很高兴去买衣服。此时由于银行手续错误,小明刚刚打的钱被回滚了。结果我的账户其实并没有那么多钱。后来我选好衣服后发现账户余额不足。。。不可重复读指的是在一个事务中多次读取同一个数据,而这个事务还没有结束,另一个事务也访问了同一个数据,那么在第一个事务的两次读取之间,由于第二个事务的修改,数据被读取了两次由第一笔交易可能会有所不同。一个事务中两次读取的数据是不同的,所以称为不可重复读。(同时运行,事务1在运行时和提交后分别读取事务2的数据,读取到的记录内容不一致,不可重复读是指在同一个事务中,两次相同的查询返回不同的结果。)MagicRead事务T1读取指定Where子句返回的结果集,然后T2事务插入一行新的记录,正好满足T1使用的查询条件。然后T1再次检索表,但再次看到T2插入的数据。(类似于可重复读,但事务T2的数据操作只是插入和删除,不是数据修改,读取的记录条数不一致)。幻读的重点是增加或删除(数据项数量变化)。事务隔离级别Serializable(序列化)将所有事务一一执行,避免幻读(phantomread)RepeatdedRead(可重复读)Select得到的所有数据都不可修改,从而避免事务前后读取不一致在获取的数据中。但是没有办法控制幻读,因为此时其他事务不能改变选中的数据,但是可以添加数据,也就是之前的事务有读锁但是没有范围锁。为什么叫可重复读级别呢?那是因为这个级别解决了底层的不可重复读问题。已提交读(ReadCommitted)读取的数据可以被其他事务修改,这可能导致不可重复读取。也就是说,读锁是在事务读取时获取的,但读完后立即释放(不需要等待事务结束),而写锁是在事务提交后释放。读锁释放后,数据可能会被其他事务修改。未提交读(readuncommitted)是最低的隔离级别,允许其他事务看到未提交的数据,这会造成脏读。综上所述,四个层次逐步提升,每一层次解决一个问题,每一层次解决一个问题。遇到事务级别的时候,性能越差,大部分环境(可以使用Readcommitted)。