互联网科技老男孩的成长之路

重学MySQL:事务与连接池,一文详解带你搞懂!

2019-12-26  本文已影响0人  java菲菲

推荐阅读:

1. 秋招JAVA面试总结:Java+并发+Spring+MySQL+分布式+Redis+算法+JVM等
2. 吊打MySQL:21性能优化实践+学习导图+55面试+笔记+20高频知识点
3. 欢迎大家关注我的专栏:【Java架构技术进阶】,里面有大量batj面试题集锦,还有各种技术分享,如有好文章也欢迎投稿哦~

01 Mysql事务

image.png

事务:

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

a、mysql引擎是支持事务的

b、mysql默认自动提交事务。每条语句都处在单独的事务中。

c、手动控制事务

开启事务:start transaction | begin

提交事务:commit

回滚事务:rollback

Connection conn = null;
PreparedStatement ps = null;
try{
    conn = DBUtils.getConnection();
    conn.setAutoCommit(false);      //相当于begin
    ps.conn.prepareStatement("update account set money=money-100 where id=1");
    ps.executeUpdate();
    ps = conn.prepareStatement("update account set money=money+100 where id=2");
    ps.executeUpdate();
    conn.commit();                  //提交事务 commit
}catch(Exception e){

    try{
        conn.rollback();            //回滚事务 rollback
    }catch(SQLException e1){
        e1.printStackTrace();
    }
    e.printStackTrace();
}finally{
    DBUtils.closeAll(null, ps, conn);
}

原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。转账前和转账后的总金额不变。

隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

赃读:指一个事务读取了另一个事务未提交的数据。

不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同。一个事务读取到了另一个事务提交后的数据.(update)

虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。 (insert)

数据库通过设置事务的隔离级别防止以上情况的发生:

级别越高,性能越低,数据越安全

mysql中:

Connection.setTransactionIsolation(int level);

02 数据库连接池

目的:解决建立数据库连接耗费资源和时间很多的问题,提高性能。

自定义数据库连接池要实现javax.sql.DataSource接口,一般都叫数据源。

public class MyDataSource implements DataSource{
  //存放连接的池子
    private static LinkedList<Connection> pool = new LinkedList<>();
    //创建10个连接放在池中
    static{
        for(int i = 0; i < 10; i++){
            Connection conn = null;
            try{
                conn = JdbcUtil.getConnection();
                pool.addLast(conn);
            }catch(SQLException e){
                e.printStackTrace();
            }
        }
    }
    public Connection getConnection() throws SQLException{
        if(pool.size() > 0){
            Connection conn = pool.removeFirst();
            return conn;
        }else{
            //等待
            //新创建一个连接
        throws new RuntimeException("服务器忙。。。");
        }
    }

}

a、装饰设计模式:使用频率很高

目的:改写已存在的类的某个方法或某些方法,装饰设计模式(包装模式)

口诀:

b、默认适配器:装饰设计模式一个变体

口诀:

1)DBCP

DBCP:Apache推出的Database Connection Pool

使用步骤:

public class DBCPUtils{
  //声明一个连接池对象
private static DataSource ds;
static{
Properties p = new Properties();

try{
p.load(DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));

ds.BasicDataSourceFactory(p);

}catch(Exception e){

e.printStackTrace();
}
}
public static Connection(){

try{

return ds.getConnection();

}catch(SQLException e){

throw new RuntimeException("创建数据库连接失败");
}
}
}

2)C3P0

使用步骤:

<?xml version="1.0" encoding="UTF-8"?>
  <c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property>
<property name="user">root</property>
<property name="password">password</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
</c3p0-config>

编写工具类

public class C3P0Util{
  private static ComboPooledDataSource datasource = new ComboPooledDataSource();
//得到Connection对象
public static Connection getConnection(){
try{
return datasource.getConnection();
}catch(SQLException e){
throw new RuntimeException("创建数据库连接失败");
}
}
}

开发JavaWeb应用,必须使用一个JavaWeb服务器,JavaWeb服务器都内置数据源

Tomcat:(DBCP)

数据源只需要配置服务器即可

配置数据源的步骤:

a)如果把配置信息写在tomcat下的conf目录的context.xml中,那么所有应用都能使用此数据源

b)如果是在当前应用的META-INF中创建context.xml, 编写数据源,那么只有当前应用可以使用

<Resource name="jdbc/mydb1" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username"root" password="password" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb1"/>

使用连接池

<%
  Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:/comp/env/jdbc/mydb1");
%>

JNDI:java nameing directory interface

JNDI容器就是一个Map

作者:Mr.ml
原文链接:https://blog.csdn.net/MarcoAsensio/article/details/95520220

上一篇下一篇

猜你喜欢

热点阅读