如何保证数据库读写事务
2013-07-04 23:02
253 查看
场景
先讲下我当时遇到的一个应用场景:一份含有5万条数据的表,希望每次都能从中获取到一条未被使用过的数据,然后再标记该条数据已被使用。
数据库时mysql,为方便起见,转化成sql的语义就是:
一张表:
value | status |
v1 | 1 |
v2 | 1 |
... | 1 |
特别说明:表结构并不是必须这样,你可以自己设计。
解决思路
如果你觉得很简单:直接select这条数据,然后update它即可。那就真的悲剧了。比如说这样的读写SQL
SELECT value FROM table WHERE status = 1 LIMIT 1 UPDATE table SET status = 0 WHERE value = 'v1'如果每次请求都如下图一样,是依次顺序执行,的确是没有任何问题
但是如果应用的并发量很高时,这样就会出现问题,比如下图中,用户2在用户1执行完毕select但没执行完毕update时,执行了select。那么用户1和用户2将获得同一条数据,这明显不是我们想要的结果。
那又什么好的解决方案呢?相信很多人立马想到的方案肯定是事务。不错,用事务的确是种不错的解决方案
解决方案一:事务
START TRANSACTION;但毕竟事务是种很影响性能的方法, 那有没有可以不用事务的方法呢?
SELECT value FROM table WHERE status = 1 LIMIT 1 UPDATE table SET status = 0 WHERE value = 'v1'
COMMIT;或rollback;
解决方案二:根据UPDATE结果判定是否有效
依据的原理是,在Mysql中执行UPDATE语句时,它会返回执行结果,具体如下:mysql> UPDATE table SET status = 0 WHERE value = 'v1' AND status = 1; Query OK, 0 rows affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0这里 Rows matched 表示匹配的数量,Changed表示改动的行数
回到刚到的问题,我们可以用这些信息来判断是否成功
SELECT value FROM table WHERE status = 1 LIMIT 1 UPDATE table SET status = 0 WHERE value = 'v1' AND status = 1当返回结果是:
Rows matched: 1 Changed: 1 Warnings: 0表示这次数据更新是有效的。
当返回结果是:
Rows matched: 0 Changed: 0 Warnings: 0表示这次数据更新失败,因为该行数据已经别人占用,需要重试
但这种方法的问题,就是并发量特别高时,很多请求会出现冲突,需要重试。
解决方案三:利用表的自增id属性
id | value | status |
1 | v1 | 1 |
2 | v2 | 1 |
需要另外一张表table2
id | ... |
1 | ... |
2 | ... |
... | ... |
INSERT INTO table2 ( ....) VALUES( .... ); 获取到table2 中最近的id UPDATE table SET status = 0 WHERE id = id SELECT value FROM table WHERE id = id由于自增id是唯一性的,所以可以保证最终得到的数据也是唯一性的,但缺点也非常明显:多需要一张表,而且两张表的id需要一定的映射关系。
解决方案四:引入requestID字段
表设置为:value | status | request_id |
v1 | 1 | |
v2 | 1 |
UPDATE table SET status = 0, request_id = 'xxxxx' WHERE status = 1 LIMIT 1 SELECT value FROM table WHERE request_id = 'xxxxx'只要保证request_id是唯一性(最简单的作法就是hash(服务器+时间 +随机数)),我们得到的结构也肯定是有效的
希望对大家有所帮助。^v^
相关文章推荐
- 如何保证数据库读写事务
- 如何保证数据库读写事务
- 什么是ACID特性,数据库如何保证ACID特性的? 事务的传播特性与隔离级别?
- 同时10万个事务在线,读写频繁,数据库该如何设计
- 数据库同步程序如何保证事务装载高效又完整
- 如何保证数据库结构的合理性(二、调整表结构)
- 在业务逻辑中如何进行数据库的事务管理。
- 如何使用注解配置bean保证注解事务不失效
- 如何保证数据库结构的合理性(三、建立可靠的关系)
- Dynamo分布式系统——「RWN」协议解决多备份数据如何读写来保证数据一致性,而「向量时钟」来保证当读取到多个备份数据的时候,如何判断哪些数据是最新的这种情况
- 操作分布式文件之八:如何批量并行读写远程文件和事务补偿处理
- 如何在 SQL Server 2005 中使用 DBCC SHRINKFILE 语句收缩事务日志文件-数据库知识
- 如何安排磁盘使数据库读写更快
- 数据库中,什么是事务,可以简述,事务机制如何实现的吗
- 基于 EntityFramework 的数据库主从读写分离架构(2)- 改进配置和添加事务支持
- msql笔记七——ThreadLocal保证客户端同时拿到的是同一个连接,数据库多事务的处理
- 如何读写property文件,保证一定顺序
- 如何理解数据库中事务的原子性?
- SpringBoot笔记5---如何读写数据库之通过Query对象读写数据库
- Spring事务之如何保证同一个Connection对象