JDBC的高级使用——事务提交模式和隔离级别
1. 事务提交模式
自动提交模式
默认方式,每执行完一条SQL语句就自动提交事务,每条SQL语句的执行都被单独提交,因此一个事务只有一条SQL语句组成。
手动提交模式
通常一个新的数据库连接产生,便意味着一个新的事务生成。我们要将一个整体操作设置为一个事务,而不是一条SQL语句当成一个事务。
Conncetion.setAutoCommit(false):设置为手动提交模式
Connection.commit():提交事务
Connection.rollback():回滚事务
一个事务中可以包含若干条SQL语句
2. 事务并发引发的问题
事务(Transaction),一般是指要做的或所做的事情。
事务是恢复和并发控制的基本单位。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
并发引发的问题
脏读(dirty read)
一个事务读取另一个事务未提交的数据。
例如,一个事务对数据库里面的数据进行读取,另一个事务对数据库进行更新,某一条数据记录原本为20,欲更新为100,在第二个事务提交之前,第一个事务读取到这个100,而此后第二个事务进行了回滚操作,这时,读取出来的数据即为脏数据。
不可重复读(unrepeatable read)
一个事务运行期间两次读取相同的数据但是内容不一致。原因可能是两次读取数据期间有另外一个事务对数据进行了修改。
虚读/幻影读(phantom read)
一个事务运行期间两次读取相同统计数据但内容不一致,原因是两次读取期间有其他事务执行了插入或删除符合统计条件的数据并提交。
3. 事务隔离级别
事务隔离(Transaction Isolation)
通过设置事务的隔离级别,来解决脏读、不可重复读、幻影读问题
五种事务隔离级别
TRANSACTION_NONE(0):不支持事务
TRANSACTION_READ_UNCOMMITTED(1):可读未提交数据
TRANSACTION_READ_COMMITTED(2):避免脏读
TRANSACTION_REPEATABLE_READ(4):避免不可重复读
TRANSACTION_SERIALIZABLE(8):避免幻影读
隔离级别 | dirty read | unrepeatable read | phantom read |
---|---|---|---|
read_uncommitted(1) | yes | yes | yes |
read_committed(2) | no | yes | yes |
repeatable read(4) | no | no | yes |
serializable(8) | no | no | no |
1. 隔离级别越高,并发性能越差,一般将隔离级别设置为2
Oracle的事务隔离级别:TRANSACTION_READ_COMMITTED(默认)和TRANSACTION_SERIALIZABLE
MySQL的事务隔离级别:默认为4(TRANSACTION_REPEATABLE_READ),还可以为1,2,8
JDBC中获取事务隔离级别:Connection.getTransactionIsolation(),返回int值
JDBC中设置事务隔离级别:Connection.getTransactionIsolation(int level),参数可以为隔离级别数字代号,也可以是Connection的静态常量(如:Connection.TRANSACTION_REPEATABLE_READ)