V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
kayseen
V2EX  ›  Python

mysql 的两条数据同时保存成功问题

  •  
  •   kayseen · 2019-11-29 09:43:23 +08:00 · 5099 次点击
    这是一个创建于 1819 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如现在有两张表,分别是class表和studend表,

    现在两张表都是空的,并且在student表里面有一个字段是class_id,

    两张表需要同时新建一条数据: class1student1,

    并且student1class_id字段需要指向class1的 id,

    请问这种场景应该怎么实现才能让他们保持一致性,并且student1class_id可以指向class1的 id?

    因为class1没有保存的时候,是没有 id 字段的,

    还是说这种场景下不能保持一致性啊

    31 条回复    2019-11-29 18:20:54 +08:00
    kayseen
        1
    kayseen  
    OP
       2019-11-29 09:44:36 +08:00
    简单描述的话, 就是两条数据需要同时保存成功,但是在一条数据里需要记录另外一条数据的 id......
    ysoserious
        2
    ysoserious  
       2019-11-29 09:45:58 +08:00
    事务
    joyme
        3
    joyme  
       2019-11-29 09:46:44 +08:00
    事务不能解决这个问题吗
    Reficul
        4
    Reficul  
       2019-11-29 09:50:06 +08:00 via Android
    事物,非要强一致可以加外键。不一致不会死人就程序逻辑保证
    littleylv
        5
    littleylv  
       2019-11-29 09:58:35 +08:00
    你说的同时是有多同时啊
    0.000000000000001 秒的同时吗
    先插入 class1,得到 class1 的 id,再插入 student1,放到事务执行,也可以说是同时啊
    hmxxmh
        6
    hmxxmh  
       2019-11-29 09:59:39 +08:00
    事务加外键吧,django 可以用 with transaction.atomic()进入事务
    markgor
        7
    markgor  
       2019-11-29 10:07:06 +08:00   ❤️ 2
    別來騙代碼,如果連這也偷懶,你技術的道路也走到盡頭了。
    如果你是剛學,那給思路你沒問題。
    開啟事物。
    插入 class 表,獲取 insertid。
    插入 studend 表
    任何一部出錯,都 rollback,
    成功都 commit。
    kayseen
        8
    kayseen  
    OP
       2019-11-29 10:10:08 +08:00
    @markgor
    谢谢你帮忙解答,是新手,但是从头到尾我说要代码了吗?还有技术的道路走到尽头???
    rockyou12
        9
    rockyou12  
       2019-11-29 10:11:29 +08:00
    @kayseen 应为你这个问题太过低级……任何看过一点数据库文档的人都不会问你这个问题……
    kayseen
        10
    kayseen  
    OP
       2019-11-29 10:11:45 +08:00
    @ysoserious
    @joyme
    @Reficul
    @littleylv
    @hmxxmh
    谢谢大家解答,现在知道了,本来知道可以事务操作,不知道事务之后会有数据的 id,感谢
    kayseen
        11
    kayseen  
    OP
       2019-11-29 10:12:20 +08:00
    @rockyou12
    好的,大神
    justRua
        12
    justRua  
       2019-11-29 10:12:48 +08:00
    class1 没有保存的时候,是没有 id 字段的。你可以用某些规则生成 id,这样两条插入语句就可以并行执行。例如:用 crc32 计算 className 的值,再在插入的时候指定 classId 就好了
    kayseen
        13
    kayseen  
    OP
       2019-11-29 10:14:22 +08:00
    @justRua
    嗯呢,谢谢啦, 我本来也是纠结不保存没有 id 的问题,上面各位介绍了事务之后就有 id 了,可以看下
    dongisking
        14
    dongisking  
       2019-11-29 10:37:22 +08:00
    不建议增加外键,7#的方法可取
    tulongtou
        15
    tulongtou  
       2019-11-29 10:39:05 +08:00 via iPhone
    事务都有 flush 和 commit 两种动作,flush 的时候就有 id 了,这个时候还可以 rollback,commit 之后就不能 rollback 了
    blodside
        16
    blodside  
       2019-11-29 10:40:37 +08:00
    先整个数据库的课看看吧。不用直接看文档,比到处问来的效率高。
    事务的基础知识包括:CAID、4 种隔离级别之类的。
    justRua
        17
    justRua  
       2019-11-29 10:40:41 +08:00
    mysql 通过 SELECT LAST_INSERT_ID()可以拿取到,你这不就是获取自增 id 的问题么。还以为你要多线程并发插入
    MatthewHan
        18
    MatthewHan  
       2019-11-29 10:42:16 +08:00
    ACID 数据库本身就是可以保证原子性的,假设在代码中是 2 个步骤对持久层的处理,把这个两步当做一个整体,要么全部执行,要么全部不执行。
    augustpluscn
        19
    augustpluscn  
       2019-11-29 10:59:36 +08:00
    事务,class 保存后不用等 commit 就能获取到 id 了
    markgor
        20
    markgor  
       2019-11-29 11:01:48 +08:00
    @kayseen

    比如现在有两张表,分别是 class 表和 studend 表,
    :有兩張表

    现在两张表都是空的,并且在 student 表里面有一个字段是 class_id
    :裡面一個字段叫 class_id

    两张表需要同时新建一条数据: class1 和 student1,
    :無法理解同時插入 class1 和 studen1 數據,畢竟上面沒提過字段,唯一字段是 class_id,這行自行腦補為各插入數據

    并且 student1 的 class_id 字段需要指向 class1 的 id,
    :student1.class_id 對應 class1.id;(上面表名是 class 和 studend 這裡就變了,也自行腦補算了。)

    请问这种场景应该怎么实现才能让他们保持一致性,并且 student1 的 class_id 可以指向 class1 的 id?
    :如何保持 student1.class_id 對應 class1.id 的關係。

    因为 class1 没有保存的时候,是没有 id 字段的,
    :那如果先保存 class1 會導致什麼後果?

    还是说这种场景下不能保持一致性啊
    :請問你試過了嗎?自己試出來的才是真諦。


    另外,
    不是事务之后会有数据的 id,
    你只要 ID 是使用 AI 的,插入後都能獲取自增 ID。
    事物的開啟是為了保證第二句插入的時候有意外能把第一步的操作取消了(回滾)。


    最後,我語言可能有些偏激。
    我意思是如果你非新手問這樣的問題,你技術道路基本是走到盡頭了。
    geying
        21
    geying  
       2019-11-29 11:05:05 +08:00
    @markgor 老哥真走心 顶你
    VictorJing94
        22
    VictorJing94  
       2019-11-29 11:49:59 +08:00   ❤️ 2
    ....这个应用不对吧...什么情况下会需要同时创建 class 和 student 呢...楼主不妨再好好思索一下
    Joyboo
        23
    Joyboo  
       2019-11-29 12:02:24 +08:00
    还是用事务吧,外键一堆坑
    julyclyde
        24
    julyclyde  
       2019-11-29 14:21:56 +08:00
    @VictorJing94 显然你是对的,且仅你是对的
    reus
        25
    reus  
       2019-11-29 15:11:02 +08:00
    事务都不知道,建议返厂重修。
    ukipoi
        26
    ukipoi  
       2019-11-29 15:12:39 +08:00
    @VictorJing94
    学生必须在一个班里才被记录成本校学生。
    学校不限制招生。
    一个班级满了,会新开一个班来安排学生。
    这种情况算么?
    luofan004
        27
    luofan004  
       2019-11-29 15:28:32 +08:00
    你们再这样子,吓得楼主都不敢问问题了。
    waterlaw
        28
    waterlaw  
       2019-11-29 15:51:18 +08:00 via Android
    mysql 的事务是通过锁保证的,acid 严格来说不一定对,可以看下数据库的共享锁,写锁,排他锁,以及快照读(一个事务获得写锁修改另一个事务可以读该记录最近的快照), 一致性就事务加回滚,spring 的话就 @Transactional(propagation=Propagation.REQUIRED, rockbsck=Exception.class), 用 mysql 默认可重复读隔离级别就可以了
    akira
        29
    akira  
       2019-11-29 16:58:13 +08:00
    就这个场景而言。。并不需要那么严谨。。
    VictorJing94
        30
    VictorJing94  
       2019-11-29 17:20:32 +08:00
    @ukipoi 不算吧,反正多操作就是事务,场景举例不对就是了,我也就吐槽一下不严谨的举例
    markgor
        31
    markgor  
       2019-11-29 18:20:54 +08:00
    @ukipoi 有點牛角尖了吧...
    第一步,必須是查班級有沒滿,滿了就丟去另一個班。返回班級 ID。
    第二步,把第一步返回的班級 ID 記錄進學校的表裡。

    你的條件是:
    學生必須綁定班級才算本校學生。
    班級滿了開新班,但不限數量。

    所以根據條件,流程自然是先檢查班級人數是否滿再做對應業務邏輯。
    第二步是把第一步的班級 ID 記錄進學校裡,
    最後得出的結果就是這個學生是 XXX 班 XXX 學校的學生。

    A.ID 對應 B.AID 就註定了是必須先有 A 才有 B。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   993 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 22:06 · PVG 06:06 · LAX 14:06 · JFK 17:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.