zoukankan      html  css  js  c++  java
  • MySQL事务隔离级别 和spring事务

    SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
    Read Uncommitted(读取未提交内容)

           在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
    Read Committed(读取提交内容)

           这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
    Repeatable Read(可重读)

           这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

    Serializable(可串行化) 
           这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

               

           

              脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

             不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

             幻读(Phantom Read):在一个事务的两次查询中数据行数不一致,例如有一个事务查询了几列行Row)数据,而另一个事务却在此时插入了新的几行数据,先前的事务在接下来的查询中,就会发现有几行数据是它先前所没有的。

             

               

            Spring事务:

                        先导入jar包

           <dependency>

        <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.29</version>
    </dependency>


    实体类:

    public class Stock {
    private Integer sid;
    private String sname;
    private Integer count;

    public Integer getSid() {
    return sid;
    }

    public void setSid(Integer sid) {
    this.sid = sid;
    }

    public String getSname() {
    return sname;
    }

    public void setSname(String sname) {
    this.sname = sname;
    }

    public Integer getCount() {
    return count;
    }

    public void setCount(Integer count) {
    this.count = count;
    }
    }
    ublic class Accounta {
    private Integer aid;
    private String aname;
    private Integer balance;

    public Integer getAid() {
    return aid;
    }

    public void setAid(Integer aid) {
    this.aid = aid;
    }

    public String getAname() {
    return aname;
    }

    public void setAname(String aname) {
    this.aname = aname;
    }

    public Integer getBalance() {
    return balance;
    }

    public void setBalance(Integer balance) {
    this.balance = balance;
    }
    }

    dao层:
    public interface StockDAO {
    public boolean updateStock(int sid,int quantity,boolean isBuy);
    }

    public class StockDAOimpl extends JdbcDaoSupport implements StockDAO{
    //quantity 交易的数量
    public boolean updateStock(int sid, int quantity, boolean isBuy) {
    boolean b=false;
    String sql=null;
    if(isBuy){
    sql="update stock set count=count+? where sid=?";
    }else{
    sql="update stock set count=count-? where sid=?";
    }
    int update = this.getJdbcTemplate().update(sql,quantity,sid);
    if (update>0){
    b=true;
    }
    return b;

    }
    }


    public interface AccountaDAO {

    //isBuy 判断股票的交易方式
    public boolean updateAccounta(int aid,int amoney,boolean isBuy);
    }

    public class AccountaDAOimpl extends JdbcDaoSupport implements AccountaDAO {

    //amoney 花费的金额

    public boolean updateAccounta(int aid, int amoney,boolean isBuy) {
    boolean a=true;
    String sql="";
    if(isBuy){
    sql="update accounta set balance=balance-? where aid=?";
    }else{
    sql="update accounta set balance=balance+? where aid=?";
    }

    int update = this.getJdbcTemplate().update(sql,amoney,aid);


    if (update>0){
    a=false;
    }
    return a;
    }
    }


    service层:
    public interface Stock {
    public boolean by(int aid,int amoney,int sid,int quantity) throws StockException;
    }



    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,rollbackFor = SocketException.class)
    public class Stockserviceimpl implements Stock {
    private AccountaDAO accountaDAO;
    private StockDAO stockDAO;

    public AccountaDAO getAccountaDAO() {
    return accountaDAO;
    }

    public void setAccountaDAO(AccountaDAO accountaDAO) {
    this.accountaDAO = accountaDAO;
    }

    public StockDAO getStockDAO() {
    return stockDAO;
    }

    public void setStockDAO(StockDAO stockDAO) {
    this.stockDAO = stockDAO;
    }

    public boolean by(int aid, int amoney, int sid, int quantity) throws StockException {
    boolean isBuy=true;
    accountaDAO.updateAccounta(aid,amoney,isBuy);

    //int result=5/0;
    if(1==1) {
    // throw new SecurityException("fgh");
    throw new StockException("错啦");
    }
    stockDAO.updateStock(sid,quantity,isBuy);

    return false;
    }
    }

    配置文件:

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql:///smbms"></property>
    <property name="username" value="root"></property>
    <property name="password" value=""></property>
    </bean>

    <!--2.识别到jdbc.properties文件-->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:jdbc.properties"></property>
    </bean>
    <!--3.StockDAO-->
    <bean id="stockDAO" class="dao.daoimpl.StockDAOimpl">
    <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--4.AccountaDAO-->
    <bean id="accountDAO" class="dao.daoimpl.AccountaDAOimpl">
    <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--5.service id-->
    <bean id="stockService" class="service.serviceimpl.Stockserviceimpl">
    <property name="stockDAO" ref="stockDAO"></property>
    <property name="accountaDAO" ref="accountDAO"></property>
    </bean>

    <!--事务:事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--方式三:AspectJ AOP 配置事务-->
    <!-- <tx:advice id="stockAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="by" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException"/>
    &lt;!&ndash; <tx:method name="select*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>&ndash;&gt;
    </tx:attributes>
    </tx:advice>

    <aop:config>
    &lt;!&ndash;1.切点&ndash;&gt;
    <aop:pointcut id="mypointcut" expression="execution(* *..serviceimpl.*.*(..))"></aop:pointcut>
    &lt;!&ndash;3.顾问&ndash;&gt;
    <aop:advisor advice-ref="stockAdvice" pointcut-ref="mypointcut"></aop:advisor>
    &lt;!&ndash;2.切面&ndash;&gt;
    </aop:config>-->

    <!--方式二:事务注解驱动-->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!--事务控制 事务代理工厂Bean 方式一: TransactionProxyFactoryBean -->
    <!--<bean id="stockServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"></property>
    <property name="target" ref="stockService"></property>
    &lt;!&ndash; &lt;!&ndash;事务属性&ndash;&gt;&ndash;&gt;
    <property name="transactionAttributes">
    <props>
    <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED,-StockException</prop>
    </props>
    </property>
    </bean>-->


    测试类:
    public class Text {
    @Test
    public void test01(){
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext22tx.xml");
    Stock service=(Stock) context.getBean("stockService");
    try{
    service.by(3,100,1,5);
    }catch (Exception ex){
    ex.printStackTrace();
    }
    }
    }
     


  • 相关阅读:
    iFrmae_HTML
    表单_HTML
    使用 docker-compose 运行 MySQL
    【消息中间件是啥哟?】
    vue项目打包经验
    【css之flex布局】a guide to flexbox
    vue表格数据查询
    模块化导出导入的几种方式
    快速搭建一个本地服务node
    小程序性能优化
  • 原文地址:https://www.cnblogs.com/xu06123/p/8583942.html
Copyright © 2011-2022 走看看