数据库事务,是并发控制的基本单位,是指作为单个逻辑工作单元执行的一系列操作,即访问数据库的一个操作序列。DB应用系统通过事务集来完成对数据的存取,事务控制实际上就是控制数据的安全访问。
(1)原子性:事务里面的操作要么全部执行,要么全部不执行。
(2)隔离性:事务的所有操作在执行过程中,他的执行不能被其他事务干扰。
(3)一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
(4)持久性:一旦事务提交,它对数据库中数据的改变就是永久的。
对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
(1)更新丢失:
当两个或多个事务选择同一行,然后基于选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题:最后的更新覆盖了由其他事务所做的更新。
(2)脏读:
①脏读,就是指当一个事务T1正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务T2也访问了这个数据,然后使用了这个数据,后来,T1因为某种原因被撤销回滚,这时T1已把修改后的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据是脏数据。
②脏数据:就是其他事务未提交的尚没有写回数据库中的数据。
(3)不可重复读:
①不可重复读,是指在同一个事务T1内,多次读同一个数据,在这个事务还没有结束之前,另外一个事务T2也访问了并修改了该同一数据。那么,在T1事务中的两次读数据之间,由于T2事务的修改,那么T1事务两次读到的数据可能是不一样的。这样就发生了在一个事务内,两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
②例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
(4)幻读:
①是指当事务不是独立执行时发生的一种现象,例如第一个事务对表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
②例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
注意:不可重复读和幻读的区别是:前者是指读到了已经提交的事务的更改数据(修改或删除),后者是指读到了其他已经提交事务的新增数据。对于这两种问题解决采用不同的办法:前者防止读到更改数据,只需对操作的数据添加行级锁,防止操作中的数据发生变化;后者防止读到新增数据,往往需要添加表级锁,将整张表锁定,防止新增数据(oracle采用多版本数据的方式实现)。
(1)读序列化:Serializable,一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。(表级锁)
(2)(默认级别)可重复读:Repeatable Read,一个数据在执行的过程中可以看到其他事务已经提交的记录,但是不能看到其他事务对已有记录的更新。
(3)读已提交:Read Commited,一个事务在执行过程中可以看到其他事务已经提交的记录,而且能看到其他事务对已有记录的更新。
(4)读未提交:Read UnCommited,一个事务在执行的过程中可以看到其他事务没有提交的记录,而且能看到其他事务没有提交的记录的更新。
四种隔离级别从上往下依次降低,隔离级别越高,越能保证数据的完整性和一致性,但对高并发性能影响也越大,即执行效率越低。像Serializable,就是以锁表的方式使得其他的线程只能在锁外等待。
√:可能出现的情况 ×:不会出现该情况
|
脏读 |
不可重复读 |
幻读 |
读序列化 |
× |
× |
× |
可重复读 |
× |
× |
√ |
读已提交 |
× |
√ |
√ |
读未提交 |
√ |
√ |
√ |
后记:隔离级别的设置只对当前链接有效。对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。