纵横研究院数据库技术专题社区

【转载】MySQL事务介绍

2019-03-05  本文已影响58人  四美_64b9

事务介绍

MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关, 一个事务是一个连续的一组数据库操作,就好像它是一个单一的工作单元进行。换言之,永远不会是完整的事务,除非该组内的每个单独的操作是成功的。如果在事务的任何操作失败,则整个事务将失败

事务的特性

事务有以下四个标准属性的缩写ACID,通常被称为:

事务使用

在MySQL中,有两种方法开启事务,第一种,事务使用BEGIN(或者START TRANSACTION)语句开启

第二种,用set来改变mysql的自动提交模式,set autocommit = 0 禁止自动提交,以后所有的sql都将作为事务处理,直到你用commit确认或 rollback结束,注意当你结束这个事务的同时也开启了新的事务!按第一种方法只将当前的做为一个事务

事务锁定模式

  1. SELECT …… LOCK IN SHARE MODE(共享锁)
    查询到的数据,就是数据库在这一时刻的数据(其他已commit事务的结果,已经反应到这里了),SELECT 必须等待,某个事务结束后才能执行

  2. SELECT …… FOR UPDATE(排它锁)
    例如 SELECT * FROM tablename WHERE id<200
    那么id<200的数据,被查询到的数据,都将不能再进行修改、删除、SELECT …… LOCK IN SHARE MODE操作,一直到此事务结束,

  3. INSERT / UPDATE / DELETE
    所有关联数据都会被锁定,加上排它锁

  4. 防插入锁
    例如 SELECT * FROM tablename WHERE id>200
    那么id>200的记录无法被插入

  5. 死锁
    自动识别死锁
    先进来的进程被执行,后来的进程收到出错消息,并按ROLLBACK方式回滚
    innodb_lock_wait_timeout = n 来设置最长等待时间,默认是50秒

共享锁 和 排它锁 的区别:在于是否阻断其他客户发出的 SELECT …… LOCK IN SHARE MODE命令

事务的并发访问问题

1.脏读:在一个事务中,当读取数据时,读到了另一个事务未提交的数据。

比如A账户给B账户转了1块钱,但是A没有提交事务,被B账户通过脏读看到了,这时,B就会以为A已经把钱转过来了,但是这时,A账户回滚事务。其实钱就没给B转过去,但是B自己本身以为A已经转过去了

看代码:

update account set money=money+1 where name=’B’ --此时A去通知B
update account set money=money -1 where name=’A’

2.不可重复读:在一个事务中,两次读取的数据内容不一致,这是因为在查询时,有时间间隔,数据被另一个事务已经修改提交了,那就会出现问题。

3.幻读/虚读:在一个事务中,两次读取的数据量不一致。

事务隔离模式

SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL
READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE
1、不带SESSION、GLOBAL的SET命令
只对下一个事务有效
2、SET SESSION
为当前会话设置隔离模式
3、SET GLOBAL
为以后新建的所有MYSQL连接设置隔离模式(当前连接不包括在内)

查看mysql数据库默认的隔离级别:select @@tx_isolation

隔离模式

Spring声明式事务管理

基于AOP注解@Transactional的声明式事务管理

默认情况下,数据库处于自动提交模式,每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果执行失败则隐式的回滚事务。
对于正常的事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式。不过,这个我们不用担心,spring会将底层连接的自动提交特性设置为false。
org/springframework/jdbc/datasource/DataSourceTransactionManager.java

if (con.getautocommit()) {
      txobject.setmustrestoreautocommit(true);
      if (logger.isdebugenabled()) {
         logger.debug("switching jdbc connection [" + con + "] to manual commit");
     }
     con.setautocommit(false);
 }
用法

添加位置,接口实现类或接口实现方法上,而不是接口类中,@Transactional 注解应该只被应用到 public 方法上,这是由AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常

下期预告:项目上线压测过程中抛出异常,提示record_not_exists_or_version_not_mach,使用了框架的updateByPrimaryKeySelective方法,下期计划介绍一些数据库锁方面和补充一下分布式事务的东西

转自:https://www.cnblogs.com/hellomandy/p/8068269.html

上一篇下一篇

猜你喜欢

热点阅读