mysql InnoDB的事务

打印 上一主题 下一主题

主题 1780|帖子 1780|积分 5340

一、事务的概念

一组数据库操作要么全部成功,要么全部失败,目的是为了保证数据的最终一致性
二、事务的四大特性(ACID)


  • 原子性(Actomicity):当前事务的操作要么成功,要么失败,原子性是由undo log日志来保证
  • 一致性(Consistency):使用事务的最终目的,由业务代码正确逻辑保证
  • 隔离行(Isolation):在事务并发实验时,他们内部的操作不能互干系扰
  • 持久性(Durability):一旦提交了事务,它对数据库的改变就应该是永久性的。持久性是由redo log日志来保证
三、事务的隔离级别

InnoDB引擎中提供了四种隔离级别,级别越高事务的隔离行越好,但性能就越低,而隔离性是由mysql的各种锁以及MVCC机制来实现

  • READ UNCOMMITTED(读未提交):一个事务可以读到另一个事务未提交的数据。有脏读的可能
  • READ COMMITTED(读已提交):事务只能读取到已经提交的数据。有不可重复读的可能性
  • REPEATABLE READ(可重复读,MySQL 默认级别):在一个事务中多次读取同一条数据时,结果始终雷同。有幻读读可能
  • SERIALIZABLE(可串行化):最严的隔离级别,事务完全串行实验。无上述问题
三、脏读、不可重复读、幻读都是什么?



  • ‌脏读:是指一个事务读取了另一个事务未提交的事务。
    例:开启事务修改id是1的数据,但不提交事务。再开一个事务查询id是1的数据,但是不提交事务。
  1. set tx_isolation = 'read-uncommitted';
  2. begin;
  3. update test_tab set blance = blance + 500 where id =1;
  4. commit ;
复制代码
  1. set tx_isolation = 'read-uncommitted';
  2. begin ;
  3. select * from test_tab where id = 1;
  4. commit ;
复制代码

在事务修改sql事务未提交的环境下,查询结果是更新后的数据。在修改未提交事务时,被另一个事务读去到结果,可见是错误。脏读也就是写的事务未提交时,被另一个事务读区到结果。

  • 不可重复读:不可重复读是指只能读去到已经提交了的事务。
    例:
    还原表中的数据,
  1. set tx_isolation = 'read-committed';
  2. begin;
  3. update test_tab set blance = blance + 500 where id =1;
  4. commit ;
复制代码
  1. set tx_isolation = 'read-committed';
  2. begin ;
  3. select * from test_tab where id = 1;
  4. commit ;
复制代码
实验步骤:
1、开启一个事务,在事务中更新数据,不提交事务。再开启一个事务,查询正在更新的那条数据,不提交事务。

2、步骤1更新数据的事务提交,再次查询那条数据,不提交事务。

3、步骤1更新语句再次实验,不提交事务。再次查询那条数据,不提交事务。

4、步骤3的更新事务提交。再次查询那条数据,不提交事务。

5、查询的事务提交。

查询的事务无论是否提交,读到的数据都是已经提交事务的数据。

  • 幻读:
    还是将数据还原,重新实验下边的sql
  1. set tx_isolation = 'repeatable-read';
  2. begin;
  3. update test_tab set blance = blance + 500 where id =1;
  4. commit ;
复制代码
  1. set tx_isolation = 'repeatable-read';
  2. begin ;
  3. select * from test_tab where id = 1;
  4. select * from test_tab where id = 1;
  5. commit ;
  6. select * from test_tab where id = 1;
复制代码
步骤:
1、1、开启一个事务,在事务中更新数据,不提交事务。再开启一个事务,查询正在更新的那条数据,不提交事务。

2、2、步骤1更新数据的事务提交,再次查询那条数据,不提交事务。

3、步骤1更新语句再次实验,不提交事务。再次查询那条数据,不提交事务。

4、步骤3的更新事务提交。再次查询那条数据,不提交事务。

5、查询的事务提交,再次查询。

在一个事务里,只要读过了这条数据,后边再读这条数据都以第一次读到的这条数据为主。
那么如何办理这个问题呢?
第一个办法就是用更更高的隔离级别。
第二个办法用乐观锁机制,加上一个version字段,查询的时候将version字段查出来select 业务字段,version from table,更新的时候每次version字段+1 update table set 业务字段, version = version + 1 where version = 前边查出来的version值,知道影响行数大于0。
第三个办法可以使用数据库的悲观锁,假如字段计划到计算的时候,用业务字段 = 业务字段 + 数量,由于mysql的insert、update会有写锁,每次都会用数据库中的最新的数据进行操作

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小秦哥

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表