mysql事务
mysql中的事务
- 默认自动提交,每条语句都处在单独的事务中
- 手动控制事务:
- 开启事务:begin,start transaction
- 提交事务:commit
- 回滚事务:rollback
JDBC如何控制事务
- java代码中
- connection.setAutoCommit(false);开启事务(关闭自动提交)相当于begin
- connection.commit();提交事务,相当于commit
- connection.rollback();抛出异常时回滚事务,相当于rollback
事务的特性(面试题)
- 原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
- 一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。如转账前和转账后的总金额不变
- 隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
- 持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
事务的隔离级别
读的问题
- 赃读:指一个事务读取了另一个事务未提交的数据
- 不可重复读:意思是重复读的话会读到不一样的而数据即在一个事务内读取表中的某一行数据,多次读取结果不同。一个事务读取到了另一个事务提交后的数据。(update)
- 虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。 (insert)
避免读的问题发生(设置事物的隔离级别)
- READ UNCOMMITTED:读未提交级别及以上的,即赃读、不可重复读、虚读都有可能发生
- READ COMMITTED:读已提交级别及以上的,即避免赃读。但不可重复读、虚读都有可能发生。(oracle默认的)
- REPEATABLE READ:读重复读级别及以上的,即避免赃读和不可重复读。但虚读有可能发生。(mysql默认)
- SERIALIZABLE:避免赃读、不可重复读、虚读
- 写问题
- 两类丢失更新的问题
- A事务撤销回滚时,把已经提交的B事务的更新数据覆盖了
- A事务提交时覆盖B事务已经提交的数据,造成B事务所做操作丢失
- 避免写的问题发生
- 悲观锁,一个锁定系统,可以阻止用户以影响其他用户的方式修改数据。如果用户执行的操作导致应用了某个锁,只有这个锁的所有者释放该锁,其他用户才能执行与该锁冲突的操作。这种方法之所以称为悲观并发控制,是因为它主要用于数据争用激烈的环境中,以及发生并发冲突时用锁保护数据的成本低于回滚事务的成本的环境中.悲观锁常见的问题就是死锁,例如A在修改文件T1,B在修改文件T2,他们分别锁定了这两个文件,假设T1和T2内容相关,B在修改T2的时候发现他还需要修改T1,可是T1却被A锁定;与此同时,A在修改T1的时候也发现了他还需要修改T2,可是T2又被B锁定了,这样就出现了死锁
- 乐观锁,用户读取数据时不锁定数据。当一个用户更新数据时,系统将进行检查,查看该用户读取数据后其他用户是否又更改了该数据。如果其他用户更新了数据,将产生一个错误。一般情况下,收到错误信息的用户将回滚事务并重新开始。这种方法之所以称为乐观并发控制,是由于它主要在以下环境中使用:数据争用不大且偶尔回滚事务的成本低于读取数据时锁定数据的成本。
- mysql中查看当前事务级别:SELECT @@TX_ISOLATION;
- 更改当前事务的级别:SET TRANSACTION ISOLATION LEVEL 四个级别之一。设置隔离级别必须在事务之前。
JDBC控制事务的隔离级别
- Connection接口:4
- Connection.setTransactionIsolation(int level);
- TRANSACTION_READ_COMMITED 避免赃读。不可重复读、虚读都有可能发生
- TRANSACTION_READ_UNCOMMITED 赃读、不可重复读、虚读都有可能发生
- TRANSACTION_REPEATABLE_READ 避免赃读、不可重复读。虚读有可能发生
- TRANSACTION_SERIALIZABLE 避免赃读、不可重复读、虚读
连接池
连接池原理:
- 数据库创建连接需要消耗较多的资源,使用数据库连接池存放链接,用后不用关闭资源(连接)而是放到连接池中,再用时直接从中取出,不用创建新连接,以便提高性能
编写标准的数据源
- 实现javax.sql.DataSource接口
- 使用LinkedList存放链接对象…
装饰设计模式:使用频率很高
- 改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)
- 口诀:
1、编写一个类,实现与被包装类相同的接口。(具备相同的行为)
2、定义一个被包装类类型的变量。
3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
4、对于不需要改写的方法,调用原有的方法。
5、对于需要改写的方法,写自己的代码。适配器模式:装饰设计模式一个变体
- 1、编写一个类,继承包装类适配器。(具备相同的行为)
2、定义一个被包装类类型的变量。
3、定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
4、对于不需要改写的方法,调用原有的方法。
5、对于需要改写的方法,写自己的代码。常用的第三方数据源及其配置(日后都使用数据源,一定要配置一下)
DBCP–Apache推出的Database Connection Pool(没有自动回收空闲连接的功能)
//加载资源
Properties p = new Properties();
p.load(DBCPUtils.class.getClassloader().getResourceAsStream(“dbcpconfig.properties”));//DBCPUtils为所在当前类
DataSource ds = BasicDataSourceFactory.createDataSource(p);
Connection conn = ds.getConnection();
C3P0–一个开源的JDBC连接池,它实现了数据源和JNDI[^13a]绑定(有自动回收空闲连接功能)
- c3p0-config.xml配置文件classpath或classes中(会自动读取信息?)
Druid–阿里巴巴
用JavaWeb服务器管理数据源:Tomcat
- JNDI(java nameing directory interface)Java命名和目录接口,tomcat管理数据源时,多个数据源用目录形式存储于JNDI容器(Map)中,根据新颖的名字找打对应的数据源
自定义JDBC框架
数据库元信息的获取(很简单、很无聊、很重要)
自定义JDBC框架
解释:
JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互