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

Mysql数据库事务与隔离级别

时间:2023-03-26 13:59:09 Python

⑴原子性(Atomicity) 原子性是指事务中包含的所有操作要么成功要么失败回滚,与前两篇博客介绍的事务的功能相同概念,所以如果事务的操作成功,则必须完全应用到数据库,如果操作失败,则不能对数据库产生任何影响。⑵一致性(Consistency) 一致性是指事务必须使数据库从一种一致状态变为另一种一致状态,也就是说,一个事务在执行前后必须处于一致状态。  以转账为例,假设用户A和用户B的钱总和为5000,那么无论A和B之间怎么转钱,转多少次,转的钱都是交易结束后两个用户加起来应该还是5000,这就是交易的一致性。⑶隔离(Isolation) 隔离是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每个用户开启的事务不能被其他事务的操作所干扰,多个并发事务是彼此隔离。  就是要实现这样一个效果:对于任意两个并发事务T1和T2,从事务T1的角度来看,T2要么在T1开始之前结束,要么在T1结束之后开始,这样每个事务都没有其他事务的感觉正在同时执行。  事务的隔离数据库提供了多种隔离级别,后面会介绍。⑷持久性(Durability) 持久性是指事务一旦被提交,对数据库中数据的更改是永久性的,即使数据库系统遇到故障,提交的事务也不会丢失操作。  比如我们使用JDBC操作数据库时,提交事务方法后,会提示用户事务操作完成。当我们的程序执行到看到提示时,我们就可以确认交易并正确提交,即使此时数据库有问题,我们的交易也必须完全执行,否则会导致我们看到一个majorerror提示事务已处理,但数据库因故障不执行事务。  介绍完事务的四大特性(简称ACID),现在重点讲解事务的隔离性。当多个线程启动事务操作数据库中的数据时,数据库系统必须能够进行隔离操作,以保证每个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先来看看几种如果不考虑事务的隔离会出现的问题:1.脏读 一个事务从另一个未提交的事务中读取数据。  当一个事务在多次修改某个数据,而这多次修改都没有在本次事务中提交,那么一个并发的事务访问该数据,会导致两个事务获取的数据不一致。例如:用户A转账100元给用户B,对应的SQL命令如下:updateaccountsetmoney=money+100wherename='B';(此时A通知B)updateaccountsetmoney=money-100wherename='A'; 只执行了第一条SQL,第二条SQL执行时,A通知B查账,B发现钱确实到了(此时已经发生脏读),不管第二条SQL是否执行ornot,只要事务没有commit,所有的操作都会回滚,那么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.conf.d文件中的transaction-islation选项查看MySQL数据库中当前事务的隔离级别:select@@tx_isolation;设置MySQL数据库中事务的隔离级别:set[glogal|session]transactionisolationlevel隔离级别名称;settx_isolation='Isolationlevelname;'例1:查看当前事务的隔离级别:例2:设置事务的隔离级别为Readuncommittedlevel:或者:切记:设置数据库的隔离级别必须在打开交易之前!如果使用JDBC为数据库事务设置隔离级别,也应该在调用Connection对象的setAutoCommit(false)方法之前。调用Connection对象的setTransactionIsolation(level)来设置当前连接的隔离级别。至于参数级别,可以使用Connection对象的字段:JDBC中设置隔离级别的部分代码:后记:隔离级别的设置只对当前连接有效。对于MySQL命令窗口的使用,一个窗口相当于一个链接,当前窗口设置的隔离级别只对当前窗口内的事务有效;对于JDBC操作的数据库来说,一个Connection对象就相当于一个链接,而为Connection对象设置的隔离级别只对这个Connection对象有效,与其他链接的Connection对象无关。

猜你喜欢