mysql數據庫Too many connections 錯誤的解決過程記錄


在做一個注冊頁面的時候,要用到ajax異步校驗用戶輸入的信息是否正確,還得做用戶名查重工作,所以需要頻繁的訪問數據庫。我用的c3p0的一個操作數據庫的utils是我自己在我看完學習視頻之后做的,我做的utils和視頻中做的不同的是:視頻中做的utils是注冊驅動、設置ComboPooledDataSource和獲得connection分開,我做的是一個getConnection方法一步到位。平常使用數據庫頻率不高也就沒發現什么問題,直到現在東窗事發......

昨天出現了錯誤Too many connections ;我還納悶我每次用完連接都會關閉,為什么會Too many connections ...

使用命令  show full processlist; 發現居然有上2萬個sleep連接,

一停止程序運行又只剩下一個鏈接(就是本機連接),

檢查了一下代碼,發現“創建連接池”和“取用連接”和“關閉連接”代碼放在一起,導致了這樣一個工作流程:

一個用戶訪問----->創建一個鏈接池(20個連接)--->取用一個連接----->關閉一個鏈接;

於是多次訪問(多個用戶訪問)的時候就創建了多個連接池,但每一個用戶都只關閉了其中一個鏈接,留下一堆鏈接;

比如,30個用戶訪問,每個用戶訪問都創建一個20個連接的連接池,總共創建了600個鏈接,但30個用戶全部訪問結束時,總共才關閉了30個鏈接,留下570個鏈接。

用戶越來越多,導致無用的鏈接越來越多,所以就有了Too many connections 

 

正確的使用數據庫做法是:先設置ComboPooledDataSource;再調用一個鏈接,而且每次調用都要關閉;

參考以下程序(測試程序,不是注冊程序)

public class C3p0 {
    ComboPooledDataSource dataSource = new ComboPooledDataSource();  
    @Test
    public void name() throws Exception {//1000次測試
        setConnection();
        for(int i=0;i<1000;i++){
            Thread.sleep(200);
            operateDatabase();
            System.out.println(i);
        }
    }
    
    
    /** 
     * 演示c3p0的使用方法 
     * @project_name Day11    
     * @class_name C3P0Demo    
     * @author Dovinya 
     * @data 2014-8-27 下午07:57:42    
     * @version 1 
     * @notes 
     */  
 
    public void setConnection() {//設置ComboPooledDataSource
        try {
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/kxpro");  
        dataSource.setUser("root");  
        dataSource.setPassword("514079");  
        dataSource.setMinPoolSize(5);//連接池最小連接數
        dataSource.setInitialPoolSize(20);//連接池創建時連接數
        dataSource.setMaxPoolSize(80);//連接池最大連接數
        dataSource.setAcquireIncrement(5);//鏈接用完時創建的連接數
        dataSource.setNumHelperThreads(5);//多線程執行,提升性能
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("沒找到驅動");
        }  
    }
          
        @Test
        public void operateDatabase() {  //使用鏈接
            Connection conn =null;  
            PreparedStatement ps = null;  
            ResultSet rs = null;  
            try {  
//              Class.forName("com.mysql.jdbc.Driver");  
//              conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "123");  
//              ps = conn.prepareStatement("select * from account");  
             
                conn =  dataSource.getConnection();
                ps = conn.prepareStatement("select * from login");  
                rs = ps.executeQuery();  
                while(rs.next()){
                    System.out.println(rs.getString("username"));
                }
                  
                while(rs.next()){  
                    String name = rs.getString("name");  
                    System.out.println(name);  
                }  
                  
            } catch (Exception e) {  
                e.printStackTrace();  
            }finally{  
                if(rs!=null){  
                    try {  
                        rs.close();  
                    } catch (SQLException e) {  
                          
                        e.printStackTrace();  
                    }finally{  
                        rs=null;  
                    }  
                }  
                  
                if(ps!=null){  
                    try {  
                        ps.close();  
                    } catch (SQLException e) {  
                          
                        e.printStackTrace();  
                    }finally{  
                        ps=null;  
                    }  
                }  
                  
                if(conn!=null){  
                    try {  
                        conn.close(); 
                        System.out.println("conn yiguanbi");
                    } catch (SQLException e) {  
                          
                        e.printStackTrace();  
                    }finally{  
                        conn=null;  
                    }  
                }             
              
            }  
        }  
          
    
}

 

最重要的是ComboPooledDataSource 要作為成員變量,只執行一次,創建連接池,以后用戶只需取用即可 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM