数据库并发设计

lxq19851204 2014-09-08 12:02:49
有4个表trans(transid,transno...) transid是主键
transdetail(transid,itemid,...) transid和itemid是联合主键
transcondiment(transid,itemid,condimentid,...)transid和itemid,condimentid是联合主键
transpayment(transid,paymentid,....)transid和paymentid是联合主键.

现在插入数据是先查询数据库的最后一个transid,然后加1,这样会造成同时很多台机器插入数据时transid会重复.

该怎么解决这个问题?
...全文
207 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
hjyang2012 2014-09-09
  • 打赏
  • 举报
回复
楼主你的情况我猜测是这样的。 A事务开启 获取transid = 1;计算出新的transid 为 2,注意此事A事务没提交 B事务开启 获取transid = 1(因为A还没提交),计算新的transid = 2 解决方案是这样的: 查询transid的时候使用for update, select transid from tab_name where ..... for update 这样就可以解决重复的问题了。不过如果你并发非常高的话效率可能会有影响,因为使用了for update,下个事务执行这里的时候会等到这个事务commit之后才会执行。实际上不是并发处理了。
hjyang2012 2014-09-09
  • 打赏
  • 举报
回复
引用 12 楼 lxq19851204 的回复:
你insert的时候,如果看到已经有了,会报主键重复的错误啊,不可能让你插入重复值的。 当然事务提交的时候会看到主键重复错误,所以现在是不要出现这种插入错误,可以同时插入不报错的.
额。你想当然了。我估计情况是这样的。 A事务开启 获取transid = 1;计算出新的transid 为 2,注意此事A事务没提交 B事务开启 获取transid = 1(因为A还没提交),计算新的transid = 2 这样就重复了。
hjyang2012 2014-09-09
  • 打赏
  • 举报
回复
楼主我告诉你使用for update 可以解决你的问题。
iihero 2014-09-08
  • 打赏
  • 举报
回复
加上事务, Begin Trans, insert 第一张表,得到last_insert_id 然后依次插入后边几张表 commit trans 有异常,则rollback 这是事务处理的最典型应用啊,怎么会有重复? 难道你用错了引擎类型?
lxq19851204 2014-09-08
  • 打赏
  • 举报
回复
你insert的时候,如果看到已经有了,会报主键重复的错误啊,不可能让你插入重复值的。 当然事务提交的时候会看到主键重复错误,所以现在是不要出现这种插入错误,可以同时插入不报错的.
九月茅 2014-09-08
  • 打赏
  • 举报
回复
引用 8 楼 lxq19851204 的回复:
[quote=引用 6 楼 ACMAIN_CHM 的回复:] [quote=引用 3 楼 lxq19851204 的回复:] [quote=引用 1 楼 ACMAIN_CHM 的回复:] trans(transid,transno...) 考虑直接使用transid auto_increment
自增的话其他表如何如何实现自增? 因为插入的话是4个表同时插入数据? [/quote]这样的所有进程不需要考虑锁trans表,直接插入,然后last_insert_id 得到transid,再向其它表插入数据即可。[/quote] Trans表可以自增,但是其他几个表都要获取到TransID才可以插入数据。 比如2台机器同时插入,这样的话last_insert_id会不会一样? [/quote]不会一样的。
九月茅 2014-09-08
  • 打赏
  • 举报
回复
引用 7 楼 lxq19851204 的回复:
[quote=引用 5 楼 mchdba 的回复:] [quote=引用 4 楼 lxq19851204 的回复:] [quote=引用 2 楼 mchdba 的回复:] “这样会造成同时很多台机器插入数据时transid会重复” 这个场景是不是可以理解成:应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 另外transid会重复,把transid字段设置成自增长的,就可以了,另外你数据库的隔离级别是什么类型的? 疑惑:为什么你的trans扩展表非要做联合主键啊,我觉得没有必要,去掉联合主键,只把表的自增业务id作为主键就OK了。
应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 是这样的。 你的意思是trans表的TransID自增,然后 TransDetail和其他2个表加一个ID来实现自增,取消联合主键吗?[/quote] 是的啊,我看你表设计里面,每个表都有自增主键了。 比如: transdetail(transid,itemid,...) 里面的itemid不是自增的吗? transcondiment(transid,itemid,condimentid,...)的condimentid呢,不是自增的吗? transpayment(transid,paymentid,....)的paymentid呢,不是自增的吗?[/quote] 里面的ID都不是自增的,都是自己添加的。 例如:Trans(200,000001),TransDetail 是(200,1,...)(200,2,...)(200,3,...) TransCondiment(200,2,1),(200,2,2), transpayment(100,200),transpayment(10q,200) paymentID是一直加下去的,不过数据库设定paymentID也不是自增的,而是手动+1的。 所以就造成并发问题. [/quote] 我觉得你这不是叫做并发的问题啊,一个db里面有事务,有锁啊,你select到的都是最新的记录条数。 你insert的时候,如果看到已经有了,会报主键重复的错误啊,不可能让你插入重复值的。 多台机器插入数据时transid会重复,你这个重复到底是哪个表的哪些字段数据会重复呢?如果可以你把这些字段设置成唯一键试试看。
lxq19851204 2014-09-08
  • 打赏
  • 举报
回复
当前的插入数据是这样的: 1张单据存储在Trans中,单据中所有的产品存在TransDetail中,产品的不同属性存在TransCondiment中,单据的付款信息存在TransPayment中. 所以Trans中的TransID是连接所有表信息的主键。
lxq19851204 2014-09-08
  • 打赏
  • 举报
回复
引用 6 楼 ACMAIN_CHM 的回复:
[quote=引用 3 楼 lxq19851204 的回复:] [quote=引用 1 楼 ACMAIN_CHM 的回复:] trans(transid,transno...) 考虑直接使用transid auto_increment
自增的话其他表如何如何实现自增? 因为插入的话是4个表同时插入数据? [/quote]这样的所有进程不需要考虑锁trans表,直接插入,然后last_insert_id 得到transid,再向其它表插入数据即可。[/quote] Trans表可以自增,但是其他几个表都要获取到TransID才可以插入数据。 比如2台机器同时插入,这样的话last_insert_id会不会一样?
lxq19851204 2014-09-08
  • 打赏
  • 举报
回复
引用 5 楼 mchdba 的回复:
[quote=引用 4 楼 lxq19851204 的回复:] [quote=引用 2 楼 mchdba 的回复:] “这样会造成同时很多台机器插入数据时transid会重复” 这个场景是不是可以理解成:应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 另外transid会重复,把transid字段设置成自增长的,就可以了,另外你数据库的隔离级别是什么类型的? 疑惑:为什么你的trans扩展表非要做联合主键啊,我觉得没有必要,去掉联合主键,只把表的自增业务id作为主键就OK了。
应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 是这样的。 你的意思是trans表的TransID自增,然后 TransDetail和其他2个表加一个ID来实现自增,取消联合主键吗?[/quote] 是的啊,我看你表设计里面,每个表都有自增主键了。 比如: transdetail(transid,itemid,...) 里面的itemid不是自增的吗? transcondiment(transid,itemid,condimentid,...)的condimentid呢,不是自增的吗? transpayment(transid,paymentid,....)的paymentid呢,不是自增的吗?[/quote] 里面的ID都不是自增的,都是自己添加的。 例如:Trans(200,000001),TransDetail 是(200,1,...)(200,2,...)(200,3,...) TransCondiment(200,2,1),(200,2,2), transpayment(100,200),transpayment(10q,200) paymentID是一直加下去的,不过数据库设定paymentID也不是自增的,而是手动+1的。 所以就造成并发问题.
ACMAIN_CHM 2014-09-08
  • 打赏
  • 举报
回复
引用 3 楼 lxq19851204 的回复:
[quote=引用 1 楼 ACMAIN_CHM 的回复:] trans(transid,transno...) 考虑直接使用transid auto_increment
自增的话其他表如何如何实现自增? 因为插入的话是4个表同时插入数据? [/quote]这样的所有进程不需要考虑锁trans表,直接插入,然后last_insert_id 得到transid,再向其它表插入数据即可。
九月茅 2014-09-08
  • 打赏
  • 举报
回复
引用 4 楼 lxq19851204 的回复:
[quote=引用 2 楼 mchdba 的回复:] “这样会造成同时很多台机器插入数据时transid会重复” 这个场景是不是可以理解成:应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 另外transid会重复,把transid字段设置成自增长的,就可以了,另外你数据库的隔离级别是什么类型的? 疑惑:为什么你的trans扩展表非要做联合主键啊,我觉得没有必要,去掉联合主键,只把表的自增业务id作为主键就OK了。
应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 是这样的。 你的意思是trans表的TransID自增,然后 TransDetail和其他2个表加一个ID来实现自增,取消联合主键吗?[/quote] 是的啊,我看你表设计里面,每个表都有自增主键了。 比如: transdetail(transid,itemid,...) 里面的itemid不是自增的吗? transcondiment(transid,itemid,condimentid,...)的condimentid呢,不是自增的吗? transpayment(transid,paymentid,....)的paymentid呢,不是自增的吗?
lxq19851204 2014-09-08
  • 打赏
  • 举报
回复
引用 2 楼 mchdba 的回复:
“这样会造成同时很多台机器插入数据时transid会重复” 这个场景是不是可以理解成:应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 另外transid会重复,把transid字段设置成自增长的,就可以了,另外你数据库的隔离级别是什么类型的? 疑惑:为什么你的trans扩展表非要做联合主键啊,我觉得没有必要,去掉联合主键,只把表的自增业务id作为主键就OK了。
应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 是这样的。 你的意思是trans表的TransID自增,然后 TransDetail和其他2个表加一个ID来实现自增,取消联合主键吗?
lxq19851204 2014-09-08
  • 打赏
  • 举报
回复
引用 1 楼 ACMAIN_CHM 的回复:
trans(transid,transno...) 考虑直接使用transid auto_increment
自增的话其他表如何如何实现自增? 因为插入的话是4个表同时插入数据?
九月茅 2014-09-08
  • 打赏
  • 举报
回复
“这样会造成同时很多台机器插入数据时transid会重复” 这个场景是不是可以理解成:应用端有N台机器,进行并发操作,往一台db服务器里面写数据? 另外transid会重复,把transid字段设置成自增长的,就可以了,另外你数据库的隔离级别是什么类型的? 疑惑:为什么你的trans扩展表非要做联合主键啊,我觉得没有必要,去掉联合主键,只把表的自增业务id作为主键就OK了。
ACMAIN_CHM 2014-09-08
  • 打赏
  • 举报
回复
trans(transid,transno...) 考虑直接使用transid auto_increment

57,064

社区成员

发帖
与我相关
我的任务
社区描述
MySQL相关内容讨论专区
社区管理员
  • MySQL
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧