成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

數(shù)據(jù)庫相關(guān)異常分析

IamDLY / 2995人閱讀

摘要:起因最近一段時間,生產(chǎn)系統(tǒng)持續(xù)碰到一些數(shù)據(jù)庫異常,導(dǎo)致執(zhí)行失敗。綜上,若發(fā)生異常,為數(shù)據(jù)庫連接失效,但是失效的原因可能會有多種,大致都與各種參數(shù)相關(guān)。當(dāng)時數(shù)據(jù)量大概多條,然后在批量插入時拋出該異常。

起因

最近一段時間,生產(chǎn)系統(tǒng)持續(xù)碰到一些數(shù)據(jù)庫異常,導(dǎo)致 sql 執(zhí)行失敗。

應(yīng)用環(huán)境

Java 1.7 + Mysql 5.6 + spring + ibatis

問題排查

將各種失敗的異常記錄了一下,碰到最多下面幾種異常。

java.net.SocketTimeoutException: Read timed out

java.sql.BatchUpdateException: No operations allowed after statement closed。

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

java.io.EOFException: Can not read response from server. Expected to read 8 bytes, read 7 bytes before connection was unexpectedly lost.

java.net.SocketException: Software caused connection abort: recv failed

SocketTimeoutException

針對上面第一種情況,很容易從字面意義就得出是讀取超時。然而查詢資料 JDBC 存在多種 timeout,仔細(xì)研究了一下,梳理一下。

JBDC 可以設(shè)置超時時間分別是 Transaction Timeout,Statement Timeout,Socket TimeOut,ConnectionTimeout。上述超時時間層次從上至下。

以下我們從上之下分別了解這幾種種超時時間。

Transaction Timeout :事務(wù)超時時間,由多個 Statement 組成。事務(wù)的超時時間=N*Statement.timeout+其他代碼執(zhí)行時間。所以我們不應(yīng)該在一個事務(wù)中執(zhí)行一些 RPC 或 HTTP 等這些長耗時的調(diào)用。如果時間卡在這些調(diào)用上,會導(dǎo)致事務(wù)超時發(fā)生回滾。

Statement Timeout:一次語句的執(zhí)行的時間,可以用來限制一個查詢語句的執(zhí)行時間。但是如果出現(xiàn)網(wǎng)絡(luò)故障,這個超時間將不起作用。最終需要 Socket TimeOut 解決。

Socket TimeOut :目前 JDBC 類型存在四種,而我們通常使用的是數(shù)據(jù)庫協(xié)議驅(qū)動(Database-Protocol driver (Pure Java driver) or thin driver)。這種驅(qū)動采用 Socket 用來與數(shù)據(jù)庫通信。若沒有設(shè)置,一但發(fā)生網(wǎng)絡(luò)故障,SCOKET 讀取就會直接阻塞。而設(shè)置以后,時間超時后將會拋出 java.net.SocketTimeoutException: Read timed out,防止長時間阻塞,系統(tǒng)不可用。

ConnectionTimeout :這個超時參數(shù)也是與 Socket 建立連接有關(guān)。若沒有設(shè)置,一旦如果數(shù)據(jù)庫相關(guān)地址參數(shù)錯誤錯誤,將會長時間阻塞在建立數(shù)據(jù)庫連接上。

使用網(wǎng)上一張圖可以清晰的解析前三者關(guān)系。

實(shí)際上還存在操作系統(tǒng)層面上 Socket 超時。各個操作系統(tǒng)可以設(shè)置相應(yīng) Socket 超時時間,然后若 JDBC 沒有設(shè)置,到了操作系統(tǒng)的超時時間也將會斷開。但是我們不能依賴該超時間,因?yàn)樵摃r間完全不可控,我們應(yīng)該顯式設(shè)置。

綜上,針對相關(guān) JDBC 參數(shù)我們至少需要設(shè)置 ConnectionTimeout 以及 Socket TimeOut.針對 sql 語句,可以設(shè)置 Statement Timeout。若存在事務(wù),還可以設(shè)置相應(yīng) Transaction Timeout。

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException

這個 CommunicationsException 異常會因?yàn)槠渌讓赢惓?dǎo)致如以下這兩種異常。

java.io.EOFException: Can not read response from server. Expected to read 8 bytes, read 7 bytes before connection was unexpectedly lost.

java.net.SocketException: Software caused connection abort: recv failed

剛開始碰到該異常,根據(jù) CommunicationsException 查詢一下了,大致都是說 Mysql server 端會檢測空閑連接,超時后主動斷開連接,導(dǎo)致客戶端的連接失效。

那么什么是 mysql 的空閑連接那?簡單來說,mysql 連接進(jìn)程 Command 為 sleep 狀態(tài)。我們可以使用 show processlist ; 查看正在運(yùn)行的進(jìn)程??臻e的進(jìn)程示例如圖:

jdbc 連接會根據(jù) mysql wait_timeout 檢測空閑連接。若在 wait_timeout 時間內(nèi),連接還是空閑狀態(tài),mysql server 將會斷開這個鏈接。針對這種情況,采用編碼模擬。
采用如下代碼:

        try {
            Connection connection = dataSource.getConnection();
            TimeUnit.SECONDS.sleep(11L);
            run.query(connection,"select "X"", h);
            //Thread.sleep(60000);
        } catch (Exception e) {
            log.error("查詢異常", e);
        }

然后設(shè)置 mysql wait_timeout=10 。
以下模擬代碼獲取連接后,休眠11s,這個過程中,mysql 主動斷開連接,等真正執(zhí)行時,程序拋出異常。

以下為報錯的情況:

但是底層異常卻為 java.net.SocketException: Software caused connection abort: recv failed,而不是 java.io.EOFException。

這個報錯卻是很疑惑。然后仔細(xì)查看 EOFException 后面描述 Expected to read 8 bytes, read 7 bytes before connection was unexpectedly lost,可以看出這個連接其實(shí)有一段時間其實(shí)還是可用,有讀取數(shù)據(jù),但是在讀取數(shù)據(jù)過程中,未讀到符合數(shù)量的相應(yīng)數(shù)據(jù),導(dǎo)致報錯。而上面代碼模擬的卻是連接使用時連接已生效的情況。

執(zhí)行 show variables like "%timeout%"; 查看 mysql 其他超時時間,

從上圖可以注意到 net_read_timeoutnet_write_timeout 這兩個參數(shù)。

查看 mysql 官方文檔

net_read_timeout 默認(rèn)30s
The number of seconds to wait for more data from a connection before aborting the read. When the server is reading from the client, net_read_timeout is the timeout value controlling when to abort. When the server is writing to the client,
net_write_timeout 默認(rèn)60s
The number of seconds to wait for a block to be written to a connection before aborting the write

net_write_timeout 控制 mysql 服務(wù)端向客戶端寫數(shù)據(jù)超時時間。針對這種情況,在 MysqlIO read 處打上短點(diǎn),

程序啟動時,先放開斷點(diǎn),查看 mysql processlist,看到 mysql 進(jìn)程 state send to client 時,這個時候使斷點(diǎn)生效。這個時候,等待60s 以后,成功復(fù)現(xiàn)出如下錯誤。

net_read_timeout 該超時不知道如何模擬:(。

綜上,若發(fā)生 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 異常,為數(shù)據(jù)庫連接失效,但是失效的原因可能會有多種,大致都與 mysql 各種 timeout 參數(shù)相關(guān)。

BatchUpdateException

這個錯誤是發(fā)生在數(shù)據(jù)批量導(dǎo)入時。當(dāng)時數(shù)據(jù)量大概 20 多W條,然后在批量插入時拋出該異常。以下為批量插入代碼。

getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
            @Override
            public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
                executor.startBatch();
                for (int i = 0; i < 200000; i++) {
                    Demo demo = new Demo();
                    demo.setName("asd");
                    demo.setAge(String.valueOf(i));
                    demo.setSubject("adassad");
                    // 原項(xiàng)目 這里會發(fā)生一次 RPC調(diào)用 現(xiàn)用 Sleep 代替
                    try {
                        TimeUnit.MILLISECONDS.sleep(10L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    executor.insert("insertDemo", demo);
                }
                executor.executeBatch();
                return null;
            }
        });

這段代碼就是使用 ibatis batch 功能,批量插入數(shù)據(jù)。

其實(shí)看到這個異常信息,java.sql.BatchUpdateException: No operations allowed after statement closed 可以明確看出是因?yàn)?statement 關(guān)閉導(dǎo)致,那么為什么 statement 會提前關(guān)閉。下面我們跟蹤源碼。

現(xiàn)在我們先看 SqlMapClientCallback doInSqlMapClient 方法。debug executor.startBatch() 方法最后其調(diào)用的是 SqlMapExecutorDelegate.startBatch 方法

查看代碼注釋可知,其目的就是為了設(shè)置一個狀態(tài)值,這個狀態(tài)值下面將用到。

此時我們查看 executor.insert ,正常來說該方法應(yīng)該會執(zhí)行sql 語句,然后插入數(shù)據(jù)庫。但是查看源碼你會發(fā)現(xiàn),他最后調(diào)用的是 MappedStatement.sqlExecuteUpdate,進(jìn)入方法剛開始就判斷上文設(shè)置的 session batch 屬性。當(dāng)然這個屬性,我們剛開始已經(jīng)設(shè)置成 true , 所以此時并沒有執(zhí)行 sql 插入動作,而是將這次 sql 以及相關(guān)參數(shù)存儲到內(nèi)存。

  protected int sqlExecuteUpdate(StatementScope statementScope, Connection conn, String sqlString, Object[] parameters) throws SQLException {
    if (statementScope.getSession().isInBatch()) {
      getSqlExecutor().addBatch(statementScope, conn, sqlString, parameters);
      return 0;
    } else {
      return getSqlExecutor().executeUpdate(statementScope, conn, sqlString, parameters);
    }
  }

最后我們查看 executor.executeBatch,該方法最后調(diào)用了 Statement.executeBatch,真正開始執(zhí)行批量插入。

看完 SqlMapClientCallback 里面的邏輯,現(xiàn)在我們來查看 SqlMapClientTemplate.execute 代碼邏輯。

查看時序圖可知,在真正執(zhí)行 SqlMapClientCallback 回調(diào)方法邏輯時,這個時候會首先從 DataSource 獲取 Connection, 然后后面開始執(zhí)行 SqlMapClientCallback 回調(diào)邏輯,最后釋放 Connection。這個過程中若 SqlMapClientCallback 方法執(zhí)行時間過久,如我們的方法中調(diào)用 for 循環(huán)中每次都會發(fā)生一次 Dubbo 調(diào)用,然后由于這個循環(huán)需要遍歷 20 多 W 數(shù)據(jù),這就導(dǎo)致該循環(huán)結(jié)束就需要半個多小時(假設(shè)一次 dubbo 調(diào)用耗時 10 ms),而我們 mysql server wait_timeout 為 300s,所以 mysql server 提前主動釋放空閑連接,然后等到真正執(zhí)行批量插入時,就會導(dǎo)致上面的異常。

題外話:mysql jdbc 使用 Batch 插入時,需要設(shè)置 rewriteBatchedStatements=true 參數(shù)。若沒有設(shè)置,其最后等效使用一次 for 循環(huán)插入數(shù)據(jù),并不能提升插入的效率。

參考

JDBC 驅(qū)動程序類型

Understanding JDBC Internals & Timeout Configuration

深入理解 JDBC 的超時

深入分析JDBC超時機(jī)制

mysql: show processlist 詳解

聊聊jdbc socketTimeout的設(shè)置

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/72664.html

相關(guān)文章

  • AIOps在攜程的踐行

    摘要:隨著人工智能時代的到來,攜程生產(chǎn)環(huán)境運(yùn)維進(jìn)入了新的運(yùn)維時代。本文選取了幾種典型的運(yùn)維場景對在攜程的踐行展開了介紹,首先讓我們從概念認(rèn)識下。針對應(yīng)用異常指標(biāo)檢測這種場景,抽取一定的樣本統(tǒng)計(jì),在基于專家經(jīng)驗(yàn)標(biāo)注下的準(zhǔn)確率可達(dá)到以上,召回率接近。 作者簡介徐新龍,攜程技術(shù)保障中心應(yīng)用管理團(tuán)隊(duì)高級工程師,負(fù)責(zé)多個AIOps項(xiàng)目的設(shè)計(jì)與研發(fā)。信號處理專業(yè)碩士畢業(yè),對人工智能、機(jī)器學(xué)習(xí)、神經(jīng)網(wǎng)絡(luò)及數(shù)學(xué)有...

    MingjunYang 評論0 收藏0
  • 如何實(shí)現(xiàn)多維智能監(jiān)控?--AI運(yùn)維的實(shí)踐探索

    摘要:近十年監(jiān)控系統(tǒng)開發(fā)經(jīng)驗(yàn),具有構(gòu)建基于大數(shù)據(jù)平臺的海量高可用分布式監(jiān)控系統(tǒng)研發(fā)經(jīng)驗(yàn)。監(jiān)控多維數(shù)據(jù)特點(diǎn)監(jiān)控的核心是對監(jiān)控對象的指標(biāo)采集處理檢測和分析。通過單一對象的指標(biāo)反映的狀態(tài)已不能滿足業(yè)務(wù)監(jiān)控需求。 吳樹生:騰訊高級工程師,負(fù)責(zé)SNG大數(shù)據(jù)監(jiān)控平臺建設(shè)。近十年監(jiān)控系統(tǒng)開發(fā)經(jīng)驗(yàn),具有構(gòu)建基于大數(shù)據(jù)平臺的海量高可用分布式監(jiān)控系統(tǒng)研發(fā)經(jīng)驗(yàn)。前言在2015年構(gòu)建多維監(jiān)控平臺時用kmeans做了異常點(diǎn)...

    王軍 評論0 收藏0
  • 如何實(shí)現(xiàn)多維智能監(jiān)控?--AI運(yùn)維的實(shí)踐探索【一】

    摘要:近十年監(jiān)控系統(tǒng)開發(fā)經(jīng)驗(yàn),具有構(gòu)建基于大數(shù)據(jù)平臺的海量高可用分布式監(jiān)控系統(tǒng)研發(fā)經(jīng)驗(yàn)。的哈勃多維監(jiān)控平臺在完成大數(shù)據(jù)架構(gòu)改造后,嘗試引入能力,多維根因分析是其中一試點(diǎn),用于摸索的應(yīng)用經(jīng)驗(yàn)。 作者丨吳樹生:騰訊高級工程師,負(fù)責(zé)SNG大數(shù)據(jù)監(jiān)控平臺建設(shè)。近十年監(jiān)控系統(tǒng)開發(fā)經(jīng)驗(yàn),具有構(gòu)建基于大數(shù)據(jù)平臺的海量高可用分布式監(jiān)控系統(tǒng)研發(fā)經(jīng)驗(yàn)。 導(dǎo)語:監(jiān)控?cái)?shù)據(jù)多維化后,帶來新的應(yīng)用場景。SNG的哈勃多...

    xioqua 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<