最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Seata?AT模式前后鏡像是如何生成詳解

 更新時間:2022年11月29日 11:40:52   作者:夢想實現(xiàn)家_Z  
這篇文章主要為大家介紹了Seata?AT模式前后鏡像是如何生成的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

Seata官網(wǎng)中,我們可以知道AT模式一階段的處理流程如下:

1.解析 SQL:得到 SQL 的類型(UPDATE),表(product),條件(where name = 'TXC')等相關(guān)的信息。

2.查詢前鏡像:根據(jù)解析得到的條件信息,生成查詢語句,定位數(shù)據(jù)。

3.執(zhí)行業(yè)務(wù) SQL。

4.查詢后鏡像:根據(jù)前鏡像的結(jié)果,通過 主鍵 定位數(shù)據(jù)。

5.插入回滾日志:把前后鏡像數(shù)據(jù)以及業(yè)務(wù) SQL 相關(guān)的信息組成一條回滾日志記錄,插入到 UNDO_LOG 表中

......

前鏡像的作用是保證在分布式事務(wù)失敗時能夠成功回滾的重要依據(jù),后鏡像是在回滾前校驗是否臟寫的數(shù)據(jù)依據(jù),那么我們一階段的前后鏡像在真實的代碼實現(xiàn)中是如何生成的呢?

前后鏡像的生成

為了能夠探尋到前后鏡像的生成原理,我們需要看一看seata源碼。最終我們把入口定位到AbstractDMLBaseExecutor.executeAutoCommitFalse()方法:

    protected T executeAutoCommitFalse(Object[] args) throws Exception {
        // 獲取前鏡像
        TableRecords beforeImage = beforeImage();
        // 執(zhí)行業(yè)務(wù)SQL
        T result = statementCallback.execute(statementProxy.getTargetStatement(), args);
        // 獲取后鏡像
        TableRecords afterImage = afterImage(beforeImage);
        // 存儲前后鏡像
        prepareUndoLog(beforeImage, afterImage);
        return result;
    }

前鏡像

繼續(xù)深入探究一下到底是怎么獲取beforeImage的,根據(jù)源碼來看,我們發(fā)現(xiàn)beforeImage()方法有很多實現(xiàn):

也就是說,Seata會根據(jù)不同的業(yè)務(wù)SQL來生成beforeImage,有點經(jīng)驗的小伙伴能夠看出,這里其實使用到了模版模式加上策略模式,我們挑一個DeleteExecutor來看一下:

@Override
    protected TableRecords beforeImage() throws SQLException {
        SQLDeleteRecognizer visitor = (SQLDeleteRecognizer) sqlRecognizer;
        // 根據(jù)表名解析出元數(shù)據(jù)
        TableMeta tmeta = getTableMeta(visitor.getTableName());
        ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
        // 生成查詢beforeImage的SQL語句
        // SELECT [列名,] FROM [表名] (別名) (WHERE) (ORDER BY) (LIMIT) FOR UPDATE
        String selectSQL = buildBeforeImageSQL(visitor, tmeta, paramAppenderList);
        // 執(zhí)行SQL查詢beforeImage
        return buildTableRecords(tmeta, selectSQL, paramAppenderList);
    }

1.關(guān)鍵原理就是根據(jù)業(yè)務(wù)SQL反向查詢出被影響的數(shù)據(jù);

2.為了保證查詢到的數(shù)據(jù)不是快照數(shù)據(jù),一定要記得加上FOR UPDATE;

另外的話,我們發(fā)現(xiàn)其實UpdateExecutor的前鏡像生成方式和DeleteExecutor也差不多,像普通的insert這種SQL的前鏡像就更簡單了:

    @Override
    protected TableRecords beforeImage() throws SQLException {
        return TableRecords.empty(getTableMeta());
    }

因為普通insert語句不存在任何前鏡像,所以直接返回空記錄;

后鏡像

我們再來看一下后鏡像是如何生成的,這次我們看一下UpdateExecutor的后鏡像生成方法afterImage():

@Override
    protected TableRecords afterImage(TableRecords beforeImage) throws SQLException {
        // 獲取元數(shù)據(jù)
        TableMeta tmeta = getTableMeta();
        // 沒有前鏡像,也不存在后鏡像,說明沒有數(shù)據(jù)被修改
        if (beforeImage == null || beforeImage.size() == 0) {
            return TableRecords.empty(getTableMeta());
        }
        // 生成查詢后鏡像SQL
        // SELECT [列名,] FROM [表名] (別名) WHERE 主鍵 in (前鏡像的主鍵值)
        // 這里面有一個配置項[client.undo.onlyCareUpdateColumns],是否只關(guān)心被修改的列名,默認(rèn)是true
        String selectSQL = buildAfterImageSQL(tmeta, beforeImage);
        ResultSet rs = null;
        try (PreparedStatement pst = statementProxy.getConnection().prepareStatement(selectSQL)) {
            SqlGenerateUtils.setParamForPk(beforeImage.pkRows(), getTableMeta().getPrimaryKeyOnlyName(), pst);
            // 執(zhí)行查詢后鏡像
            rs = pst.executeQuery();
            // 包裝查詢結(jié)果
            return TableRecords.buildRecords(tmeta, rs);
        } finally {
            IOUtil.close(rs);
        }
    }

后鏡像的生成原理與前鏡像的生成原理差不多,不過還是有一些小小的區(qū)別的:

1.后鏡像的查詢條件使用的是前鏡像對應(yīng)的主鍵值,就沒有用業(yè)務(wù)SQL的查詢條件;不同的Executor處理方式不同,需要根據(jù)具體的業(yè)務(wù)SQL來區(qū)分;

2.查詢后鏡像的SQL沒有使用FOR UPDATE加鎖,直接拿的快照數(shù)據(jù);

小結(jié)

通過對seata源碼的分析,我們現(xiàn)在已經(jīng)了解了前后鏡像的生成原理了:

1.通過業(yè)務(wù)SQL來判斷SQL語句的類型,從而選擇不同的Executor來獲取前后鏡像;

2.前鏡像是通過業(yè)務(wù)SQL的查詢條件,并加上FOR UPDATE來查詢業(yè)務(wù)SQL執(zhí)行前的數(shù)據(jù);(不同的Executor實現(xiàn)不同)

3.后鏡像是在業(yè)務(wù)SQL執(zhí)行完畢后,根據(jù)前鏡像內(nèi)的主鍵數(shù)據(jù)來獲取的數(shù)據(jù);(不同的Executor實現(xiàn)不同)

4.通過前后鏡像的多種實現(xiàn)可以判斷出seata AT模式所支持的SQL語句的所有類型;

以上就是Seata AT模式前后鏡像是如何生成詳解的詳細(xì)內(nèi)容,更多關(guān)于Seata AT模式生成前后鏡像的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot中@Import注解如何正確使用

    SpringBoot中@Import注解如何正確使用

    這篇文章主要介紹了SpringBoot中@Import注解的使用方式,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-06-06
  • Spring 4 支持的 Java 8 特性

    Spring 4 支持的 Java 8 特性

    Spring 框架 4 支持 Java 8 語言和 API 功能。在本文中,我們將重點放在 Spring 4 支持新的 Java 8 的功能。最重要的是 Lambda 表達(dá)式,方法引用,JSR-310的日期和時間,和可重復(fù)注釋。下面跟著小編一起來看下吧
    2017-03-03
  • 詳解Java的Hibernat框架中的Map映射與SortedMap映射

    詳解Java的Hibernat框架中的Map映射與SortedMap映射

    這篇文章主要介紹了Java的Hibernat框架中的Map映射與SortedMap映射,Hibernat是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • Java中Future、FutureTask原理以及與線程池的搭配使用

    Java中Future、FutureTask原理以及與線程池的搭配使用

    這篇文章主要為大家詳細(xì)介紹了Java中Future、FutureTask原理以及與線程池的搭配使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • 在Java中如何對類進行排序詳解

    在Java中如何對類進行排序詳解

    這篇文章主要給大家介紹了關(guān)于如何在Java中使用Arrays.toString()對類進行排序的相關(guān)資料,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • 如何使用JavaCV進行圖像灰度化處理

    如何使用JavaCV進行圖像灰度化處理

    在計算機視覺和圖像處理領(lǐng)域,圖像灰度化是一項基礎(chǔ)且重要的任務(wù),它將彩色圖像轉(zhuǎn)換為灰度圖像,JavaCV 是一個強大的開源庫,它提供了對各種計算機視覺算法和圖像處理操作的支持,本文將詳細(xì)介紹如何使用 JavaCV 進行圖像灰度化處理,需要的朋友可以參考下
    2024-10-10
  • 最全Gson使用

    最全Gson使用

    GSON彌補了JSON的許多不足的地方,在實際應(yīng)用中更加適用于Java開發(fā),本文主要介紹了最全Gson使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 解決rror updating database.Cause:java.sql.SQLSyntaxErrorException問題

    解決rror updating database.Cause:java.sql.SQLSyntaxE

    這篇文章主要介紹了解決rror updating database.Cause:java.sql.SQLSyntaxErrorException問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java設(shè)計模式之訪問者模式使用場景及代碼示例

    Java設(shè)計模式之訪問者模式使用場景及代碼示例

    這篇文章主要介紹了Java設(shè)計模式之訪問者模式使用場景及代碼示例,小編覺得還是挺不錯的,這里分享給大家,供需要的朋友參考。
    2017-11-11
  • JAVA String.valueOf()方法的用法說明

    JAVA String.valueOf()方法的用法說明

    這篇文章主要介紹了JAVA String.valueOf()方法的用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09

最新評論

公主岭市| 辽源市| 行唐县| 温宿县| 德清县| 馆陶县| 大同县| 基隆市| 顺义区| 秀山| 合江县| 嘉黎县| 辽宁省| 客服| 尉氏县| 玛多县| 云浮市| 乌什县| 开封市| 洪洞县| 滕州市| 和政县| 鹿泉市| 苏州市| 高唐县| 兰考县| 吉林市| 衡山县| 航空| 鄂伦春自治旗| 岗巴县| 阿拉尔市| 乌恰县| 亳州市| 奉贤区| 鄂尔多斯市| 库尔勒市| 临泽县| 禹城市| 财经| 南城县|