文档章节

对数据库表数据一致性的控制方法

 我要五个字
发布于 2016/11/02 15:54
字数 1423
阅读 67
收藏 0

读数据分为快照读和当前读。

快照读:(不加锁)读到的未必最新的,普通色select语句

当前读:(加锁) 读到的都是最新的。有:

1、select * from table ? lock in share mode;

2、select * from table where ? for update; (关于for update用法具体下面说)

3、insert, update, delete

第3类update数据的操作步骤是:mysql server根据查询条件先读取满足条件的第一条记录,并加锁,返回mysql server,mysql server收到之后会执行update操作,一条完成,再下一条。delete同理,Insert操作会稍微有些不同,简单来说,就是Insert操作可能会触发Unique Key的冲突检查,也会进行一个当前读。

mysql写数据的时候都会进行当前读。

关于每条sql如何执行的时候如何加锁参照:http://hedengcheng.com/?p=771

 

数据库事物的控制,数据库事物分四个级别从低到高分别

1:read uncommitted

读未提交,脏读,这个在应用中基本不用。

2:read committed

读提交,会产生重复读

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…

分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。

3:repeatable read

重复读,就是在开始读取数据(事务开启)时,不再允许修改操作。

但是会存在幻读,因为幻读是insert产生的

事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。

4、serializable序列化

Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

 

我们写service的时候经常遇到先查询再修改的操作。比如 用手机号注册一个新用户,首先得用手机号查询用户表是否存在,如果不存在则插入一条,存在就给他登录。  问题来了,当手机号相同的两个请求并发访问的时候,结果是不是在用户出现了两个手机号相同的记录(因为同时查都发现没有这个手机号),但我们要保证手机号是唯一的。(先不说数据表给手机号建立唯一约束)

一开始我使用事物的第三个等级也就是repeatable read,发现不行,为什么呢,细想一下,repeatable read只是防止一个事物开启的时候别的事物不被修改,但是还是可以查呀,呵呵。

嗯,不能被修改,for update就出现了,for update会产生锁,具体产生什么锁得看查询条件,一个原则,对明确查询结果的结果加行锁,查询结果如果整个表数据都有可能,就表锁。

比如:根据主键id查询,肯定是一条,行锁。

          根据name查询(无索引),表锁,因为都有可能

          根据name查询(有索引),行锁

举个例子:
假设有个表单products ,里面有id跟name二个栏位,id是主键索引。
例1: (明确指定主键索引,并且有此笔资料,row lock)

SELECT * FROM products WHERE id='3' FOR UPDATE;
例2: (明确指定主键索引,若查无此笔资料,无lock)

SELECT * FROM products WHERE id='-1' FOR UPDATE;
例2: (无主键索引,table lock)

SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
例3: (主键索引不明确,table lock)

SELECT * FROM products WHERE id<>'3' FOR UPDATE;
例4: (主键索引不明确,table lock)

SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;

锁,就针对写数据库的操作加锁,如果select for update当然也锁了。

for update就有效的解决了上述的问题,注意,事物里面不要写时间不可控的逻辑,比如调一个第三方的接口等待返回,这样事物的时间会变成,而表一直被锁了。具体会出现什么问题没遇到。。。

 

还有一个方法就是通过程序来控制,java里有个关键字synchronized,同步锁,能解决问题,就是效率很低,

for (int k = 0; k < 10; k++) {
    long start = System.currentTimeMillis();
    for (int j = 0; j < 100000000; j++) {
        synchronized (lock) {
            int i = 1;
        }
    }
    System.out.println(System.currentTimeMillis() - start);
    start = System.currentTimeMillis();
    for (int j = 0; j < 100000000; j++) {
        int i = 1;
    }
    System.out.println(System.currentTimeMillis() - start);
}

 

2366
30
2407
33
2410
30
2371
31
2380
31
2371
30
2388
32
2402
33
2396
30
2385
33

 

© 著作权归作者所有

粉丝 4
博文 24
码字总数 15717
作品 0
宁波
私信 提问
数据库锁总结

一直想写一篇关于数据库锁的相关总结文章,因为平时看数据库相关的博文的时候,会时不时看到某个数据库锁,一直没弄清楚各种锁的关系,下面就大概总结一下,希望园友提出问题。   数据库锁...

17099933344
2017/08/03
0
0
分布式一致性的想法

背景 最近一直在思考,工作这么多年下遇到的分布式系统的一下问题,以及针对这些问题提供的解决方案。 借这个机会,顺便梳理清楚这块知识,希望同大家一起探讨下 常见一致性问题 下订单减库存...

6776jkjk
2017/11/27
0
0
Oracle和mysql的区别

一、数据库的主要类型 数据库类型主要可分为:网状数据库、关系数据库、树状数据库、面向对象数据库。在商业中最主要的是关系型数据库,例如:Oracle、DB2、Sybase、My SQL Server、Informa...

lampit凌宇
2017/06/20
0
0
python之MySQLdb的基本操作

什么是MySQLdb? MySQLdb 是用于Python链接Mysql数据库的接口,它实现了 Python 数据库 API 规范 V2.0,基于 MySQL C API 上建立的。 如何安装MySQLdb? 为了用DB-API编写MySQL脚本,必须确保已...

LinQiH
2017/10/26
0
0
GTS解密--GTS的原理、架构与特点

作者 赵成 日期 2018-01-01 标签 分布式事务 , GTS , Global Transaction Service, 柔性事务, TCC , XA两阶段提交协议 全局事务服务(Global Transaction Service,简称 GTS)是阿里新推出的...

chengxiaozc
2018/01/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

采坑指南——k8s域名解析coredns问题排查过程

正文 前几天,在ucloud上搭建的k8s集群(搭建教程后续会发出)。今天发现域名解析不了。 组件版本:k8s 1.15.0,coredns:1.3.1 过程是这样的: 首先用以下yaml文件创建了一个nginx服务 apiV...

码农实战
9分钟前
1
0
【2019年8月版本】OCP 071认证考试最新版本的考试原题-第6题

choose three Which three statements are true about indexes and their administration in an Orade database? A) An INVISIBLE index is not maintained when Data Manipulation Language......

oschina_5359
11分钟前
1
0
阿里巴巴开源 Dragonwell JDK 最新版本 8.1.1-GA 发布

导读:新版本主要有三大变化:同步了 OpenJDK 上游社区 jdk8u222-ga 的最新更新;带来了正式的 feature:G1ElasticHeap;发布了用户期待的 Windows 实验版本 Experimental Windows version。...

阿里巴巴云原生
16分钟前
1
0
教你玩转Linux—磁盘管理

Linux磁盘管理好坏直接关系到整个系统的性能问题,Linux磁盘管理常用三个命令为df、du和fdisk。 df df命令参数功能:检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少...

xiangyunyan
19分钟前
3
0
js 让textarea的高度自适应父元素的高度

textarea按照普通元素设置height是没有作用的,可以这么来设置, 下面给上一段项目代码 JS代码: $.fn.extend({ txtaAutoHeight: function () { return this.each(function () {...

文文1
20分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部