Mysql事务

5 篇文章 0 订阅
3 篇文章 0 订阅

事务是最小的工作单位,这个单位由对数据库的若干操作组成

事务的特性

        原子性(Atomicity)

                事务中的操作,要么完成,要么取消

        一致性(Consistency)

                事务中的操作保证数据库中的数据不会出现逻辑上的不一致

        隔离性(lsolation)

                指当前事务和其他事务的操作是隔离的

        永久性(Durability)

                对事务发出commit命令后,事务的效果是永久的

控制语句

        BEGIN  或者(START) TRANSACTION:开启事务

        COMMIT:也可以使用COMMIT WORK,这两个是等价的,COMMIT会提交事务,并且对数据库进行的所有修改都是永永久的

        ROLLBACK:也可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户事务,并撤销所有正在进行未提交的修改

  MYSQL的两种处理事务的方法

              BEGN或 start transaction :开始一个事务

               ROLLBACK:回滚事务

                COMMIT:确认事务  

   使用指令查看正在进行事务

SELECT * FROM information_schema.INNODB_TRX;

每个线程都是独立的(每开启一个事务就会创建一个独立的线程 )

在JDBC中使用事务

      JDBCconnection接口有提供了两个事务模式:自动提交和手动提交  

        在java中使用事务

定义一个全局变量Connection 第一个方法设置为false就是手动提交,这种方法适用于我们删除东西后重新再添加东西,类似权限管理系统这种可以用得上

        如果没有问题就可以提交事务

全局变量.commit();

传统JDBC的操作流程

         1)获取JDBC连接     2)声明sql      3)预编译sql   4   )执行sql       5)处理sql集        6)释放结果集          7)释放Statement      8)提交事务      9)处理异常并回滚事务   10)释放JDBC连接

JDBC的优缺点

        1冗长,重复  2显示事务控制  3 每个步骤不可取  4 显示处理受检查异常

关于connection关闭的问题

        无论是否使用线程池,线程都是固定的

        如果connection不close那么能使用的connection的数量是有上限的,一但不管的话很容易超过上限

        如果每次都在dao关闭connection,可能会导致事务失效,因为每一次打开的connection可能不是同一个

        可以在service操作成功之后,见connection关闭,还需要将Threadlocal中的connection移除

提高插入的效率

       可以在多行插入的时候开启事务,然后再全面插入之后在提交事务 

        使用executeBatch进一步提升插入速度

                需要配置rewriteBatchedStatements=true提高性能

                在mysql中insert支持一次性插入多条数据

事务的隔离性

        根据隔离的可见性可以分为四个级别

                Read Uncommitted(读取未提交的内容)

                        这个时候把读取的数据称为脏读(脏读又称无效的数据读出,指某一个事务更新了数据,在这个时候另一个事务读取了这个数据,因为前面这个修改了数据,所以这个时候读的数据是不对的,这个就叫脏读)

                Read Committed(读取提交内容)

                        这个不会出现脏读.但是不能重复读取(在一个事务中前后读取的数据不一样)

                Repeatable Read(可重读)

                        一个connection的事务开启之后,无论什么情况,前后读取的数据都是一致的

                        默认情况下,虽然可重复读取,但是会出现幻读

                                幻读:可以感觉到一行数据的存在,但是就是看不见

                                在mysql中使用的是MVCC,在开启事务的同时,就使用一个快照将当前的表的情况进行储存

                        这个是mysql的默认额事务隔离级别

                Serializable (可串行化)

                        它通过强制事务排序,让他不可能相互冲突,性能低下

                        在mysql中需要打开

        主要是防止并发问题,在事务开启时,通过锁来解决并发问题

            在mysql中有一下几种锁

                        全局锁

                        表锁

                        行锁

  全局锁

        全局锁可以将整个数据库锁定,主要是在备份的还是使用

        启动全局锁

flush tables with read lock;

        释放锁

unlock tables;

在导出的时候为了提高性能,也可以通过single transaction代替全局锁

mysqldump --single-transaction -uroot -p8888 htgl > bak.sql

表锁

        只锁一张表

        可以分为read和whrite

        使用read锁

                基本语法

lock tables tb_user read;

        自己和别的线程都可以读取

        自己在写入数据后直接失败

        其他的线程在写入数据的时候,会进入阻塞,直到释放锁

使用写锁

        基本语法

lock tables tb_user write;

        自己可以读,自己可以写

        其他线程进行读和写都会进入阻塞

metadata lock(MDL)元数据锁

        保证并发访问 数据库 对象场景下的一致性而设定的。

                在对一张表进行增,删,改的时候,会自动为表添加元数据锁

                以防止其他的connection对当前表的字段进行修改

行锁

        行锁只有一行

        在增删改查的时候要配合事务进行触发,在事务提交后锁就会释放

        行锁必须要有条件,.指定锁住的行

                如果执行的条件不是索引,那么行锁会自动升级成表锁

行锁的分类

        共享锁

        排他锁:增删改都是排他锁

死锁

        出现情况

                当线程A修改1数据的时候,给1添加了一个锁

                当线程B修改2数据的时候,给2添加了一个锁

                接下来线程A去修改2数据,进入阻塞状态

                接下来线程B去修改1数据,进入阻塞状态

理论上出现死锁会进入阻塞状态,默认死锁时间是50秒,,由于时间太长,mysql加入了一个自动检查死锁的功能

在出现高并发的情况下,很容易出现死锁,所以自动检测死锁在事务开启后,会严重影响效率

可以将自动检测死锁功能关闭,并把死锁时间调为1秒

set GLOBAL innodb_deadlock_detect = off;

比较好的方法是借用其他缓存框架,如redis,将数据先在redis中进行更新,然后每个一段时间插入到数据库中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值