MyCat和Sharding-JDBC的分散式事務
一、MyCat中使用分散式事務
1、資料準備
以前面介紹的使用者表資料為例 兩臺Mysql 192.168.127.134 (dn0) ,192.168.127.129 (dn1) , Mycat 安裝在192.168.127.129
如下圖所示
Mycat的配置,
1)、schema.xml配置
分片規則為sharding-by-intfile
cd /usr/local/mycat/conf/
cat schema.xml
2)、 cat rule.xml
使用的是provice_id 作為分片的欄位
hash-int使用的是partition-hash-int.txt檔案
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> <property name="defaultNode">0</property> </function>
3)、catpartition-hash-int.txt
10000 落在dn0, 10010落在dn1, 預設是dn0
2、Mycat分散式事務配置
cat server.xml
<!--分散式事務開關,0為不過濾分散式事務,1為過濾分散式事務(如果分散式事務內只涉及全域性表,則不過濾),2為不過濾分散式事務,但是記錄分散式事務日誌--> <property name="handleDistributedTransactions">0</property>
0: 支援分散式事務, 1: 不支援分散式事務
預設是支援分散式事務。
3、插入資料
先清空134和129中user表的資料
然後在MyCat中插入資料
INSERT into `user`(`id`,`username`,`province_id`) VALUES (1,"Larry1",10000),(2,"Larry2",10010);
可以看到134和129各插入1條資料
4、模擬異常情況
先清空134和129中user表的資料,然後將129的username長度改為1
可以發現報如下錯誤
檢視134和129中user表的資料,都沒有插入成。
set autocommit=0 set xa=on INSERT into `user`(`id`,`username`,`province_id`) VALUES (1,"Larry1",10000),(2,"Larry2",10010); commit
二、專案中連線MyCat,並使用分散式事務
1、新建SpringBoot工程
命名為mycat-demo
選擇需要的依賴
因為MySQL資料庫的版本 是5.7。所有這裡使用的mysql-connector-java版本為5.1.48
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency>
2、使用mybatis-generator外掛
pom.xml中增加外掛
<plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin>
generatorConfig.xml,連線mycat
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!--指定特定資料庫的jdbc驅動jar包的位置--> <classPathEntry location="C:\Users\Think\Desktop\MyBatis\mybatis-generator-core-1.3.2\mybatis-generator-core-1.3.2\lib\mysql-connector-java-5.1.29.jar"/> <context id="default" targetRuntime="MyBatis3"> <!-- optional,旨在建立class時,對註釋進行控制 --> <commentGenerator> <property name="suppressDate" value="true"/> <property name="suppressAllComments" value="true"/> </commentGenerator> <!--jdbc的資料庫連線 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.127.129:8066/user?characterEncoding=utf8" userId="root" password="123456" /> <!-- 非必需,型別處理器,在資料庫型別和java型別之間的轉換控制--> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- Model模型生成器,用來生成含有主鍵key的類,記錄類 以及查詢Example類 targetPackage 指定生成的model生成所在的包名 targetProject 指定在該專案下所在的路徑 --> <javaModelGenerator targetPackage="com.example.mycatdemo.model" targetProject="./src/main/java"> <!-- 是否允許子包,即targetPackage.schemaName.tableName --> <property name="enableSubPackages" value="false"/> <!-- 是否對model新增 建構函式 --> <property name="constructorBased" value="true"/> <!-- 是否對類CHAR型別的列的資料進行trim操作 --> <property name="trimStrings" value="true"/> <!-- 建立的Model物件是否 不可改變 即生成的Model物件不會有 setter方法,只有構造方法 --> <property name="immutable" value="false"/> </javaModelGenerator> <!--mapper對映檔案生成所在的目錄 為每一個數據庫的表生成對應的SqlMap檔案 --> <sqlMapGenerator targetPackage="mappers" targetProject="./src/main/resources"> <property name="enableSubPackages" value="false"/> </sqlMapGenerator> <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.mycatdemo.dao" targetProject="./src/main/java"> <!-- enableSubPackages:是否讓schema作為包的字尾 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <table schema="user" tableName="user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context> </generatorConfiguration>
生成後的工程結構如下圖所示
3、增加資料庫配置 application.prooperties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.username=root spring.datasource.password=123456 spring.datasource.url=jdbc:mysql://192.168.127.129:8066/user?characterEncoding=utf8&useSSL=false mybatis.mapper-locations=mappers/*.xml
4、增加服務層程式碼
@Service public class UserService { @Resource private UserMapper userMapper; @Transactional(rollbackFor = Exception.class) public void testUser(){ User user1 = new User(); user1.setId(1); user1.setUsername("Nick1"); user1.setProvinceId(10000); userMapper.insert(user1); User user2 = new User(); user2.setId(2); user2.setUsername("Nick2"); user2.setProvinceId(10010); userMapper.insert(user2); } }
5、測試
@SpringBootTest class MycatDemoApplicationTests { @Autowired UserService userService; @Test public void testUser(){ userService.testUser(); } }
執行testUser方法,出現如下錯誤: username太長了
注:Sharding-JDBC預設也是開啟了分散式事務