免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3895 | 回复: 6
打印 上一主题 下一主题

Mysql如果不用自增长字段 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-08-02 22:51 |只看该作者 |倒序浏览
各位好,
我现在有个表,想用个ID int作为主键,但我不想把ID作为AUTO_INCREMENT类型,因为这样在数据迁移或者增删的时候,不好控制,但这个表可能同时被多个人修改,这样在处理插入操作的时候不太好控制,我用PHP来实现。

问题是比如前一个然拿到当前的最大值加一,然后在他插入记录以前,可能有人也拿到了这个ID并且已经插入数据了。有什么办法能避免这个冲突吗?或者是有比较强大的SQL语句能搞定?

create table test(
  id       int NOT NULL DEFAULT 0,
  name      varchar(32)  NOT NULL DEFAULT '',
  PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=UTF8;

多谢

论坛徽章:
0
2 [报告]
发表于 2010-08-02 23:29 |只看该作者
guid

论坛徽章:
0
3 [报告]
发表于 2010-08-03 10:39 |只看该作者
回复 1# HappyWin

guid是个方法,如果你不要求主键是连续的话。
如果需要连续自增id,可以考虑由单独一个表来存储,只需要一列自增id,每次insert后通过getLastId得到自增的id值,由数据库保证唯一性。

论坛徽章:
8
综合交流区版块每周发帖之星
日期:2015-12-02 15:03:53数据库技术版块每日发帖之星
日期:2015-10-02 06:20:00IT运维版块每日发帖之星
日期:2015-10-02 06:20:00IT运维版块每日发帖之星
日期:2015-09-14 06:20:00金牛座
日期:2014-10-10 11:23:34CU十二周年纪念徽章
日期:2013-10-24 15:41:34酉鸡
日期:2013-10-19 10:17:1315-16赛季CBA联赛之北京
日期:2017-03-06 15:12:44
4 [报告]
发表于 2010-08-03 14:14 |只看该作者
自己用应用程序来维护一个自增字段?

论坛徽章:
0
5 [报告]
发表于 2010-08-03 17:06 |只看该作者
楼主的问题,可以用锁表的办法来解决。当一个SESSION进行的查询插入的时候,锁定表,加写锁。这样其他SESSION不能写入。
下面开始测试。
1:创建一个存储过程,实现自增字段。

  1. create procedure sp1()
  2. begin
  3.   declare A int;
  4.   select max(id) into A from test;
  5.   insert into test values(if(A<=>null,0,A)+1,concat('a',if(A<=>null,0,A)));
  6. end ;
复制代码
2:打开一个连接,先锁定test 表,再进行call sp1();

mysql> lock table test write;
Query OK, 0 rows affected (0.00 sec)

mysql> call sp1();
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+----+------+
| id | name |
+----+------+
|  1 | a0   |
+----+------+
1 row in set (0.00 sec)
这时候不解锁,看另外一个连接

3:另外一个连接进行插入操作
mysql> call sp1();
由于表被锁,等待表释放。。
(如果不锁表的话,此条记录的ID=2)

4:在第一个连接里再插入一条
mysql> call sp1();
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+----+------+
| id | name |
+----+------+
|  1 | a0   |
|  2 | a1   |
+----+------+
2 rows in set (0.00 sec)
插入成功,ID是2.

5:释放锁定。
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

6:释放锁的同时,3的操作成功。

mysql> call sp1();
Query OK, 1 row affected (16.17 sec)
等待了16.17秒。
再来查3操作后,写入的是否是2

mysql> select * from test;
+----+------+
| id | name |
+----+------+
|  1 | a0   |
|  2 | a1   |
|  3 | a2   |
+----+------+
3 rows in set (0.00 sec)

ID=3.

测试成功。
在程序调用的时候,CALL SP1前加lock table test write;执行后加UNLOCK TABLES;

论坛徽章:
0
6 [报告]
发表于 2010-08-03 20:21 |只看该作者
多谢楼上各位的解答,非常详细,特别是909413335兄弟的回答很具体,受益匪浅,

我现在还是想用sql搞定,调用存储过程会不会带来性能问题啊?
如果分两步做,先插入再用getLastId,可能拿到的是别人插入的ID,可能在我插入以后,在getLastId以前,后面又有人插入了数据,会不会我拿到别人的LastId?

多谢了

论坛徽章:
0
7 [报告]
发表于 2010-08-04 09:16 |只看该作者
我现在还是想用sql搞定,调用存储过程会不会带来性能问题啊?

不会有性能问题。
在ID上建一个聚簇索引。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP