当前位置: 首页 > 科技观察

数据库事务的四大特性与事务的隔离级别

时间:2023-03-18 13:41:33 科技观察

本文介绍了数据库事务的四大特性(ACID),并对事务的隔离级别进行了详细的讲解。如果一个数据库声称支持事务性操作,那么这个数据库必须具备以下四个特性:(1)原子性(Atomicity)原子性是指一个事务中包含的所有操作要么成功要么失败回滚,这和前面的一样两个博客的功能引入了相同的概念,所以如果事务的操作成功,则必须完全应用到数据库中,如果操作失败,则不能对数据库产生任何影响。⑵一致性(Consistency)一致性是指事务必须使数据库从一种一致状态变为另一种一致状态,也就是说,一个事务在执行前后必须处于一致状态。以转账为例,假设用户A和用户B的钱的总和是5000,那么无论A和B之间怎么转钱,转多少次,这笔钱的总和交易结束后应向两个用户付款。是5000,就是交易的一致性。⑶隔离(Isolation)隔离是指当多个用户并发访问数据库时,比如操作同一张表时,数据库为每个用户开启的事务不能被其他事务的操作所干扰。彼此隔离。也就是实现这样一个效果:对于任意两个并发事务T1和T2,从事务T1的角度来看,T2要么在T1开始之前结束,要么在T1结束之后开始,这样每个事务感觉都不一样。直到其他事务并发执行。关于事务的隔离,数据库提供了各种隔离级别,后面会介绍。⑷持久性(Durability)持久性是指事务一旦被提交,对数据库中数据的更改是永久性的,即使数据库系统遇到故障,提交的事务也不会丢失操作。比如我们使用JDBC操作数据库时,提交事务方法后,提示用户完成事务操作。当我们的程序执行到看到提示时,我们就可以识别交易并正确提交。即使此时数据库有问题,我们的事务也必须全部执行完,否则会导致我们看到一个重大错误,提示事务已经处理,但是数据库由于没有执行事务到失败。介绍完事务(简称ACID)的四大特性,下面我们重点讲解一下事务的隔离性。当多个线程启动事务操作数据库中的数据时,数据库系统必须能够进行隔离操作,以保证每个线程都能获取到数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先来看看at如果不考虑事务的隔离会出现的几个问题:1脏读脏读是指在一个事务中读取另一个未提交事务中的数据。当一个事务在多次修改某个数据,而这个事务中的多次修改还没有提交,一个并发的事务访问数据时,两个事务获取的数据会不一致。例如:用户A转账100元给用户B,对应的SQL命令如下:updateaccountsetmoney=money+100wherename='B';(此时A通知B)updateaccountsetmoney=money-100wherename='A';当只执行了第一条SQL时,A通知B查账,B发现钱确实到了(此时已经发生脏读),然后不管第二条SQL是否执行,只要由于交易没有提交,所有的操作都会被回滚,那么稍后B再次查看账户时,会发现钱并没有真正转出。2不可重复读不可重复读是指对于数据库中的某条数据,在一个事务范围内多次查询返回不同的数据值。这是因为它在查询间隔期间被另一个事务修改并提交了。例如,事务T1正在读取某条数据,事务T2立即修改数据并提交事务到数据库。当事务T1再次读取数据时,得到了不同的结果,发送了一个不可重复读。不可重复读和脏读的区别在于,脏读是指一个事务读取了另一个事务未提交的脏数据,而不可重复读是指读取了前一个事务提交的数据。在某些情况下,不可重复读取不是问题。比如我们多次查询某个数据,当然***查询得到的结果是主要的。但在其他情况下,可能会出现问题。例如对于同一个数据A和B可能会被顺序查询,A和B可能会打架...3幻读(Phantomreading)幻读是在事务非独立执行时发生的一种现象。例如,事务T1将表中所有行的一个数据项从“1”修改为“2”。这时,事务T2往这张表中插入了一行数据,并且这条数据的值还是“1”,提交给了数据库。但是如果用户操作事务T1查看刚刚修改的数据,会发现还有一行没有修改。事实上,这一行是从事务T2中添加的,这似乎是幻觉。这就是幻读的发生。幻读和不可重复读都是读取另一个已经提交的事务(这与脏读不同)。不同的是,不可重复读查询的是同一个数据项,而幻读则是针对一批数据作为一个整体(比如数据的条数)。下面我们来看看MySQL数据库提供的四种隔离级别:①Serializable(序列化):可以避免脏读、不可重复读、幻读的发生。②可重复读(repeatableread):可以避免脏读和不可重复读的发生。③读提交(readcommitted):可以避免脏读的发生。④Readuncommitted(读未提交):***级别,任何情况下都不能保证。以上四种隔离级别中最好的是Serializable级别,最好的是Readuncommitted级别。当然,级别越高,执行效率越低。像Serializable这样的级别就是对表进行加锁(类似于Java多线程中的锁),让其他线程只能在锁外等待,所以平时选择的隔离级别要根据实际情况来选择。MySQL数据库中默认的隔离级别是可重复读(repeatableread)。在MySQL数据库中,支持以上四种隔离级别,默认为Repeatableread(可重复读);在Oracle数据库中,只支持Serializable(序列化)级别和Readcommitted(已提交读),其中默认级别为Readcommitted。查看MySQL数据库中当前事务的隔离级别:select@@tx_isolation;设置MySQL数据库中事务的隔离级别:set[glogal|session]transactionisolationlevelisolationlevelname;settx_isolation='isolationlevelname;'示例1:查看当前事务隔离级别:示例2:设置事务隔离级别为Readuncommittedlevel:or:切记:设置数据库隔离级别必须在事务开始之前!如果使用JDBC为数据库事务设置隔离级别,也应该在调用Connection对象的setAutoCommit(false)方法之前。调用Connection对象的setTransactionIsolation(level)来设置当前连接的隔离级别。至于参数级别,可以使用Connection对象的字段:JDBC中设置隔离级别的部分代码:后记隔离级别的设置只对当前连接有效。对于使用MySQL命令窗口,一个窗口相当于一个链接,当前窗口设置的隔离级别只对当前窗口的事务有效;对于JDBC操作的数据库来说,一个Connection对象就相当于一个链接,并且为Connection对象设置的隔离级别只对这个Connection对象有效,与其他链接的Connection对象无关。