再谈事务

上一篇咱们简单了解了事务,这一篇我们再深入一下吧

Ⅰ、事务隔离级别

事务一共有四种隔离级别

简称 全称 -
ru read-uncommited 未提交读
rc read-commited 提交读
rr repeatable-read 可重复读
srz serializable 可串行

从真正意义上来看只有srz达到真正隔离性的要求

oracel、sqlserver默认rc,mysql默认rr(99.99%达到隔离性要求)

事务隔离级别越低,事务请求的锁越少或者保持锁的时间就越短

1.1 四种隔离级别解读

事务隔离级别解决了三个问题,脏读,不可重复读,幻读

①read-uncommitted

可以读到其他线程未提交的数据,没人用,这就是脏读

②read-committed

解决了脏读,不会读到其他线程未提交的数据

但是a线程事务开始没提交,b线程读不到对应的数据,a线程事务提交后,b读到了

这就是不可重复读,两次读到不一样,破坏了隔离性,一个线程的事务所做的修改被另一个线程可见了

③repeatable-read

解决不可重复读,一边提交了,另一边还是看不到,两次读结果一样

重复读还可以解决一个问题,幻读(读到之前不存在的记录,讲锁的时候再演示)

例外情况:

  • for update锁定读就可以读到第一个线程中事务提交的数据,可以说是幻读,也可以说是一个不可重复读,这就是99.999%,哈哈
  • 这里也是一种不符合隔离性的,读到了之前不存在的记录,只要是支持mvcc就很难做到完全隔离性

④serializable

两阶段加锁可串行化保证隔离性:加锁阶段,只加锁不放锁,解锁阶段,只放锁,不解锁

对于所有的写,每行上面都有锁,会有大量的锁竞争和超时

这样就失去了MVCC特性(非锁定一致性读)

所有操作都要加共享锁,lock in share mode ,执行selct * from xxx;

其实重写为select * from xxx lock in share mode; 对这条记录加共享锁,

强制事务排序,使得不会互相冲突,这样就不存在并发问题,都是串行了,读写相互阻塞

1.2 好奇心,我们对比下rr和sr

RR隔离级别
sesion1:
mysql> set tx_isolation="REPEATABLE-READ";
Query OK, 0 rows affected (0.00 sec)

mysql> create table t_lock(a int, b int, primary key(a));
Query OK, 0 rows affected (0.11 sec)

mysql> insert into t_lock values(1,1);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_lock;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |
+---+------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.02 sec)

mysql> select b from t_lock where a=1;
+------+
| b    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

session2:
mysql> set tx_isolation="REPEATABLE-READ";
Query OK, 0 rows affected (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update  t_lock set b=2 where a = 1;
Query OK, 1 row affected (0.00 sec) Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.03 sec)

session1:
mysql> select b from t_lock where a=1;  -- 再执行一次,得到的结果是1
+------+
| b    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> select b from t_lock where a=1 for update;  -- for update的去读,得到的结果是2
+------+
| b    |
+------+
|    2 |
+------+ 1 row in set (0.00 sec)
session1中, RR隔离级别下,前两次读都是读取的快照,最后一次读取的当前更新的值

SR隔离级别
session1:
mysql> select * from t_lock;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |
+---+------+
1 row in set (0.00 sec)

mysql> set tx_isolation=‘SERIALIZABLE‘;
Query OK, 0 rows affected (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select b from t_lock where a=1;
+------+
| b    |
+------+
|    1 |
+------+ 1
row in set (0.00 sec)

session2:
mysql> show engine innodb status\G
-- ------------省略部分输出------------
2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 3, OS thread handle 0x7f946bc94700, query id 30 localhost root cleaning up
TABLE LOCK table `burn_test`.`t_lock` trx id 5390 lock mode IS
RECORD LOCKS space id 15 page no 3 n bits 72 index `PRIMARY` of table `burn_test`.`t_lock` trx id 5390 lock mode S locks rec but not gap  -- 有S锁
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
0: len 4; hex 80000001; asc     ;;
1: len 6; hex 00000000150c; asc       ;;
2: len 7; hex 8c000000340110; asc     4  ;;
3: len 4; hex 80000001; asc     ;;

mysql> set tx_isolation=‘SERIALIZABLE‘;
Query OK, 0 rows affected (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update t_lock set b=2 where a=1;  -- 在SR的隔离级别下,直接阻塞,因为a=1上有一个S锁
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

SERIALIZABLE的隔离级别一般来说是不会去用

1.3 事务隔离级别的选择

show variables like ‘tx_isolation‘;
set global 后只对之后创建的session生效,之前的session没用

如何查看当前各个线程的事务隔离级别,sys库里面的session表看不了啊?

应该看performance_schema中user_variables_by_thread表

select * from user_variables_by_thread where variable_name = ‘tx_isolation‘;
找到thread_id
select processlist_id from threads where thread_id in(xxx);
再对应到processlist id

重点:

  • 我们生产中一定要用rc,不要用默认的rr,一般场景rc性能会好很多,rc的锁好理解
  • 为了同步数据一致性binlog_format用row,mixed会遇到各种bug导致主从不一致,5.7官方默认用row了,没有协商的余地,组复制也必须用row(目前MySQL若启用rc,不管binlog_format怎么设置都会强行转为row)
    transaction_isolation = read-committed
    binlog_format = row
    上面两个一定要配到my.cnf中,没有任何理由
  • 有一种情况rr比rc好,条件是,应用偏读,一个事务里面有10个select,后面会提到,read_view的原因

原文地址:https://www.cnblogs.com/---wunian/p/9064205.html

时间: 2024-08-30 14:57:25

再谈事务的相关文章

再谈ITFriend网站的定位

ITFriend-IT从业者互动交流平台 http://www.itfriend.cn/ 在网站开发阶段.内部测试阶段.公开测试阶段,让诸多好友和网友,参与了我们的网站ITFriend的体验和测试.其中,大家非常关心,我们的网站是干什么的.在我们不做任何解释的情况下,有的网站认为ITFriend很像QQ空间.有的想知道与知乎和ask.fm等问答网站有何不同,还有更多与人人网.新浪微博.CSDN等进行比较的. 个人以为,用户这么认为是非常正常的.当一个新事物出来的时候,大家首先想到的是,这个新事物

再谈消息队列技术

上周,我们举办了第二届技术沙龙,我这边主要演讲了消息队列技术的议题,现分享给大家: 在我们团队内部,随着消息应用中心(任务中心)的广泛应用,有时候我们感觉不到消息队列的存在,但这不影响消息队列在高可用.分布式.高并发架构下的核心地位. 消息队列都应用到了哪些实际的应用场景中? 一.再谈消息队列的应用场景 异步处理:例如短信通知.终端状态推送.App推送.用户注册等 数据同步:业务数据推送同步 重试补偿:记账失败重试 系统解耦:通讯上下行.终端异常监控.分布式事件中心 流量消峰:秒杀场景下的下单处

C++ Primer 学习笔记_73_面向对象编程 --再谈文本查询示例

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he

C++ Primer 学习笔记_74_面向对象编程 --再谈文本查询示例[续/习题]

面向对象编程 --再谈文本查询示例[续/习题] //P522 习题15.41 //1 in TextQuery.h #ifndef TEXTQUERY_H_INCLUDED #define TEXTQUERY_H_INCLUDED #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <set> #include <map&g

再谈MySQL全库备份

再谈MySQL全库备份 简介 Part1:写在最前 在很早之前,我写过一个MySQL生产库全库备份脚本,今天有同事问我是不是要再加一个-R参数来备份存储过程,理由的话是由于mysqldump --help中 关于存储过程的默认备份是false. routines                          FALSE MySQL生产库全库备份脚本 http://suifu.blog.51cto.com/9167728/1758022 实战 Part1:写在最前 我备份一般就三个参数 --s

Android 再谈handler

今天在做http网络事件的响应网络接收处理一般不能放在主线程中使用,目前也只会使用AsyncTask进行处理!之前虽然写过handler处理的一些文章但是发现全不会了!无奈~ 关于handler某位兄弟已经整理的很透彻了!现在引用下原话如下: Handler监听者框架:子线程是事件源,主线程是监听者.Handler作为子线程的监听器出现:主线程中生成Handler的子类,并重写handleMessage(Message msg) 方法,用来对子线程响应.子线程调用Hanlder的sendMess

再谈ORACLE CPROCD进程

罗列一下有关oprocd的知识点 oprocd是oracle在rac中引入用来fencing io的 在unix系统下,如果我们没有采用oracle之外的第三方集群软件,才会存在oprocd进程 在linux系统下,只有在10.2.0.4版本后,才会具有oprocd进程 在window下,不会存在oprocd 进程,但是会存在一个oraFenceService服务,用来实现相同的功能,该服务采用的技术是基于windows的,与oprocd不同 oprocd进程可以运行在两者模式下:fatal和n

Java基础——再谈面向对象

去年的这个时候,心血来潮写了篇<简述面向对象技术>,先在看来不由的会想:这都是写的什么跟什么啊?(ps:虽然现在写的博客依然不咋地)但是,Java的学习中又一次不得不再一次面向对象,所以,奉上一篇<再谈面向对象>,做为新年的一盘开胃菜. 面向对象是相对于面向过程而言,是一种思想. 区别于面向过程: 面向过程是以函数为基础,完成各种操作,强调的是过程,而面向对象是以对象为基础,强调的是对象. 比如说把大象装进冰箱分为几步,宋丹丹是这样说的:三步呗, 第一步:打开冰箱门, 第二步:把大

再谈multistage text input(中文输入法)下UITextView的内容长度限制

之前写过一篇<如何更好地限制一个UITextField的输入长度>,在文章最后得到的结论是可以直接使用 UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification; 进行监听,截断超出maxLength的部分. 所以后来我在处理UITextView的内容长度时,也直接参考这个方法: [[NSNotificationCenter defaultCenter] addObserver:self selector:@select