ACMAIN_CHM 我是多个线程同时跑,要保证每条数据只被读取一次?一次要读取10条,并标记这10条记录已经被读取过了。不能用程序啊。如果用程序的话。还没来得及更新,其它线程可能已经读取这些数据了。就是要问怎么处理中间结果呢? 1、 select * from t1 where t1.flag=0 order by rand() limit 10 for update; update t1 set t1.flag=1 ...后边怎么写呢? 谢谢!
多线程并发,比较麻烦。 只能用LOCK了。你用的什么存储引擎?
innodb 这样就好!你可以用事务。在事务中, 你可以先 select * from t1 order by rand() limit 10 for update; 然后再把这 10 条记录的ID得到后再 update t1 set flag=1 where id in (66104 ,33227 ,85053 ,...)
start transaction; 1,select * from t1 order by rand() limit 10 for update; 2,这怎么写呢 如何得到 (66104 ,33227 ,85053 ,...), 3,update t1 set flag=1 where id in (66104 ,33227 ,85053 ,...); commit; 谢谢,
start transaction; 1,create TEMPORARY TABLE tmp_tbl select * from t1 order by rand() limit 10 for update; 3,update t1 set flag=1 where id in (select id from tmp_tbl); 4,select * from tmp_tbl; commit;这是个意思,但mysql临时其它线程也可见,所以执行是会有问题。第二线程执行时表 tmp_tbl 已经存在了并在使用过程中。如何解决呢? 谢谢!
不能。其它进程 如果 select * from t1 order by rand() limit 10 for update; 恰巧与这已经锁住的10条有相同的,则必须等待你的事务提交后,再能继续。你可以自己做个试验。 在一个连接中 select * from t1 order by rand() limit 10 for update; 然后再开一个连接, select * from t1 where id= xxx for update; 随便写个被锁的ID。
能帮我写个完整的例子吗?谢谢, 现在这两种都不行。临时表,其它线程也可见! start transaction; 1,create TEMPORARY TABLE tmp_tbl select * from t1 order by rand() limit 10 for update; 3,update t1 set flag=1 where id in (select id from tmp_tbl); 4,select * from tmp_tbl; commit; start transaction; 1,create TEMPORARY TABLE tmp_tbl select * from t1 order by rand() limit 10 for update; 3,update t1 inner join tmp_tbl on t1.id=tmp_tbl.id set flag=1 ; 4,select * from tmp_tbl; commit;
你用什么语言开发?直接在你的 C 或者 java 中实现。
我用 .net C#。如何做呢。谢谢
这个建议你到C#的版块去问一下。1. C#中打开事务。 2。C#中利用ADO。NET得到这个 select * from t1 order by rand() limit 10 for update; 3. C# 根据得到的记录集,生成这个 (66104 ,33227 ,85053 ,...); 字符串。 4。 C#执行 update t1 set flag=1 where id in (66104 ,33227 ,85053 ,...); 5. C# 中commit; 事务 如果上述哪一个你不会,建议你到C#去问一下。
我只想通过一个存储过程来实现。不想在程序中做。ado中开启事务,我觉得效率低!谢谢你的回复。
如果你的问题的标题是: 用存储过程来实现。则可以如下。declare v_xxx varchar(1000); START TRANSACTION; select group_concat(id) into v_xxx from (select id from t2 where falg=0 order by rand() limit 10 for update) t; update t2 set flag=1 where find_in_set(id,@xxx); commit; select * from t2 where find_in_set(id,@xxx);
我用的UuiD做主键,这样查询的结果怎么不对呢。start transaction;select group_concat( id ) into @v from tb1 limit 10 for update; select * from tb1 where find_in_setid,@v); commit; 得到了27条记录·奇怪呢??
不要用 SESSIO变量@v 用 局部变量v_xxx
我最终这样做。看看有没有什么问题! start trnasaction; set @selectid=uuid(); update t1 a inner join(select id from t1 where t1.flag=0 limit 10 for update) b on a.id=b.id set a.flag=1,a.selectid=@selectid; select * from t1 where flag=1 and selectid==@selectid; commit; 直接更新符合条件的记录。利用 uuid()的唯一性来获取记录。这样在多线程并发时应该不会有问题了。不过不知道效率如何? 明白人给指点一下。谢谢!
效率要测试一下,要在flag、selectid 上建立复合索引
declare v_xxx varchar(1000); START TRANSACTION; select group_concat(id) into v_xxx from (select id from t2 where falg=0 order by rand() limit 10 for update) t; update t2 set flag=1 where find_in_set(id,v_xxx ); commit; select * from t2 where find_in_set(id,v_xxx ); 可以试一下这个。 你的多个线程共享的一个连接。
+-------+-------+
| id | col |
+-------+-------+
| 66104 | 66104 |
| 33227 | 33227 |
| 85053 | 85053 |
| 62135 | 62135 |
| 80887 | 80887 |
| 87671 | 87671 |
| 24325 | 24325 |
| 57971 | 57971 |
| 50360 | 50360 |
| 19033 | 19033 |
+-------+-------+
10 rows in set (0.30 sec)mysql>并标记这10条记录已经被提取过
需要按照提取的结果,再更新回原表。没有什么特别的办法,只能通过程序来实现。
1、 select * from t1 where t1.flag=0 order by rand() limit 10 for update;
update t1 set t1.flag=1 ...后边怎么写呢?
谢谢!
只能用LOCK了。你用的什么存储引擎?
这样就好!你可以用事务。在事务中, 你可以先 select * from t1 order by rand() limit 10 for update;
然后再把这 10 条记录的ID得到后再 update t1 set flag=1 where id in (66104 ,33227 ,85053 ,...)
1,select * from t1 order by rand() limit 10 for update;
2,这怎么写呢 如何得到 (66104 ,33227 ,85053 ,...),
3,update t1 set flag=1 where id in (66104 ,33227 ,85053 ,...);
commit;
谢谢,
1,create TEMPORARY TABLE tmp_tbl select * from t1 order by rand() limit 10 for update;
3,update t1 set flag=1 where id in (select id from tmp_tbl);
4,select * from tmp_tbl;
commit;这是个意思,但mysql临时其它线程也可见,所以执行是会有问题。第二线程执行时表 tmp_tbl 已经存在了并在使用过程中。如何解决呢?
谢谢!
不能。其它进程 如果 select * from t1 order by rand() limit 10 for update; 恰巧与这已经锁住的10条有相同的,则必须等待你的事务提交后,再能继续。你可以自己做个试验。
在一个连接中 select * from t1 order by rand() limit 10 for update; 然后再开一个连接, select * from t1 where id= xxx for update; 随便写个被锁的ID。
现在这两种都不行。临时表,其它线程也可见!
start transaction;
1,create TEMPORARY TABLE tmp_tbl select * from t1 order by rand() limit 10 for update;
3,update t1 set flag=1 where id in (select id from tmp_tbl);
4,select * from tmp_tbl;
commit; start transaction;
1,create TEMPORARY TABLE tmp_tbl select * from t1 order by rand() limit 10 for update;
3,update t1 inner join tmp_tbl on t1.id=tmp_tbl.id set flag=1 ;
4,select * from tmp_tbl;
commit;
2。C#中利用ADO。NET得到这个 select * from t1 order by rand() limit 10 for update;
3. C# 根据得到的记录集,生成这个 (66104 ,33227 ,85053 ,...); 字符串。
4。 C#执行 update t1 set flag=1 where id in (66104 ,33227 ,85053 ,...);
5. C# 中commit; 事务
如果上述哪一个你不会,建议你到C#去问一下。
START TRANSACTION;
select group_concat(id) into v_xxx from (select id from t2 where falg=0 order by rand() limit 10 for update) t;
update t2 set flag=1 where find_in_set(id,@xxx);
commit;
select * from t2 where find_in_set(id,@xxx);
select * from tb1 where find_in_setid,@v);
commit;
得到了27条记录·奇怪呢??
用 局部变量v_xxx
start trnasaction;
set @selectid=uuid();
update t1 a inner join(select id from t1 where t1.flag=0 limit 10 for update) b on a.id=b.id set a.flag=1,a.selectid=@selectid;
select * from t1 where flag=1 and selectid==@selectid;
commit;
直接更新符合条件的记录。利用 uuid()的唯一性来获取记录。这样在多线程并发时应该不会有问题了。不过不知道效率如何?
明白人给指点一下。谢谢!
START TRANSACTION;
select group_concat(id) into v_xxx from (select id from t2 where falg=0 order by rand() limit 10 for update) t;
update t2 set flag=1 where find_in_set(id,v_xxx );
commit;
select * from t2 where find_in_set(id,v_xxx );
可以试一下这个。
你的多个线程共享的一个连接。