本文介紹使用 AT 模式接入 GTS 時的注意事項。

單個事務(wù)內(nèi)操作記錄建議少于 200 條

雖然 GTS 本身支持大事務(wù),可以支持 1 萬行的數(shù)據(jù)規(guī)模,但建議使用時不要超過 200 條。原因有以下兩方面。

  • 造成事務(wù)執(zhí)行時間上升,事務(wù)信息規(guī)模擴(kuò)大,導(dǎo)致系統(tǒng)性能下降。
  • 造成潛在的事務(wù)數(shù)據(jù)不一致問題。如果有特殊業(yè)務(wù),需要單個事務(wù)超過 1000 條 SQL 語句,請?zhí)峤还紊暾垺?/li>

事務(wù)隔離級別

GTS 的缺省事務(wù)隔離級別為讀未提交,該模式下可以達(dá)到分布式事務(wù)的最大性能。如果有特殊業(yè)務(wù),需要隔離級別為讀已提交,可以使用 SQL 的 for update。

注意 讀已提交的 for update 必須在一個 GTS 的分布式事務(wù)內(nèi)部才能生效。

GTS 的讀已提交用法示例如下:

SELECT name FROM tb WHERE id =1 FOR UPDATE;            
說明 如果您需要讀已提交以上的隔離級別,或者您對 GTS 的讀未提交有疑慮,請?zhí)峤还紊暾?,GTS 技術(shù)支持人員會協(xié)助您優(yōu)化您的事務(wù)和相關(guān) SQL。

確保 GTS 事務(wù)管理范圍內(nèi)的所有數(shù)據(jù)不會被 GTS 管理范圍外的系統(tǒng)修改

GTS 的全局?jǐn)?shù)據(jù)庫寫鎖僅針對加入了 GTS 事務(wù)的數(shù)據(jù)庫操作,如果一個對數(shù)據(jù)庫的寫操作不在 GTS 事務(wù)管理的范圍內(nèi),會造成“臟寫”。例如,一個寫操作在 GTS 事務(wù)中對一條數(shù)據(jù)進(jìn)行了修改,但是尚未提交,使用 MySQL 控制臺(不在 GTS 事務(wù)范圍內(nèi))對該數(shù)據(jù)也進(jìn)行了修改,而此時業(yè)務(wù)驅(qū)動前面的 GTS 事務(wù)回滾,這次回滾會失敗,造成數(shù)據(jù)不一致。

關(guān)閉 Druid 連接池的 SQL 緩存功能

配合 EDAS、DRDS 共同使用的場景中,GTS 事務(wù)上下文通過 SQL hint 的形式下發(fā)到 DRDS。

在 Druid 開啟 PreparedStatement 緩存功能后,Druid 會緩存前一次執(zhí)行的包含事務(wù)上下文的 SQL 語句。在另一個事務(wù)進(jìn)行時,發(fā)送這個包含過期事務(wù)上下文的 SQL 就會被認(rèn)為無效而發(fā)生錯誤。

所以,這種場景中,需要關(guān)閉 Druid 連接池的 SQL 緩存功能。方法如下:

<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init">

    <!-- 其他property略 -->
    <!-- 同時配置下面兩個值來關(guān)閉PS Cache -->
    <!-- poolPreparedStatements = false -->
    <property name="poolPreparedStatements" value="false" />
    <!-- maxPoolPreparedStatementPerConnectionSize = 0 -->
    <property name="maxPoolPreparedStatementPerConnectionSize" value="0" />
</bean>     

數(shù)據(jù)源配置

GTS 可以支持 MySQL、DRDS、Oracle、RDS、PostgreSQL 等數(shù)據(jù)庫。在訪問不同類型數(shù)據(jù)庫時,配置也有所不同。

  • 訪問 5.3 以下版本的 DRDS 數(shù)據(jù)庫

    當(dāng)應(yīng)用通過 GTS 訪問 DRDS 數(shù)據(jù)庫時,不能使用 TxcDataSource 數(shù)據(jù)源,可以使用 JDBC 數(shù)據(jù)源。

    配置方式如下:

    <bean id="DataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://xxx:3306/xxx" />
        <property name="username" value="xxx" />
        <property name="password" value="xxx" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    </bean>           
  • 訪問 5.3 及以上版本的 DRDS 或其他關(guān)系數(shù)據(jù)庫

    當(dāng)應(yīng)用通過 GTS 訪問非 DRDS 數(shù)據(jù)庫時,如 MySQL、DRDS(5.3及以上版本)、Oracle、RDS、PostgreSQL 等,必須要使用 txc 的數(shù)據(jù)源。

    • 直接使用 txc 數(shù)據(jù)源,配置方式如下:

      <bean id="DataSource_rds" class="com.taobao.txc.datasource.cobar.TxcDataSource">
           <property name="url" value="jdbc:mysql://xxxxx" />
           <property name="username" value="xxx" />
           <property name="password" value="xxx" />
           <property name="driverClassName" value="com.mysql.jdbc.Driver" />
       </bean>                    
    • 使用 Druid 數(shù)據(jù)源,配置方式如下:

      <bean id="txcDataSource" class="com.taobao.txc.datasource.cobar.TxcDataSource">
             <constructor-arg ref="druidDataSource"/>
         </bean>
      
         <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init">
             <property name="url" value="jdbc:mysql://xxxxxxxxx:3306/xxx"/>
             <property name="username" value="xxx"/>
             <property name="connectProperties">
                 <props>
                     <prop key="password">xxx</prop>
                 </props>
             </property>
             <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
             <property name="filters" value="stat" />
             <property name="maxActive" value="300" />
             <property name="initialSize" value="10" />
             <property name="maxWait" value="60000" />
             <property name="minIdle" value="1" />
             <property name="timeBetweenEvictionRunsMillis" value="60000" />
             <property name="minEvictableIdleTimeMillis" value="300000" />
             <property name="validationQuery" value="SELECT 'x'" />
             <property name="testWhileIdle" value="true" />
             <property name="testOnBorrow" value="false" />
             <property name="testOnReturn" value="false" />
             <property name="poolPreparedStatements" value="false" />
             <property name="maxPoolPreparedStatementPerConnectionSize" value="0" />
         </bean>