简体   繁体   English

我是否需要(我将需要)锁定共享模式| 在交易中进行更新?

[英]Do I need (will I ever need) LOCK IN SHARED MODE | FOR UPDATE within a transaction?

I'm painfully struggling trying to understand how to write best my code and queries 我痛苦地试图理解如何编写最好的代码和查询

straight to the question: do I need or will I ever need to write explicitly LOCK IN SHARED MODE or FOR UPDATE in a transaction (apart from READ UNCOMMITTED ones)? 直截了当的问题:我是否需要或者我是否需要在交易中明确写入LOCK IN SHARED MODEFOR UPDATE (除了READ UNCOMMITTED之外)?

if I have external keys, do I need to select rows explicitly to apply the lock to these rows, or the foreign keys definition is enough? 如果我有外部密钥,是否需要明确选择行以将锁应用于这些行,或者外键定义是否足够?

The short answer: absolutely yes. 简短的回答:绝对是的。

The complete answer: it depends on the use case. 完整的答案:这取决于用例。 Perhaps in the most of scenarios the default locks used by InnoDb is sufficient. 也许在大多数情况下,InnoDb使用的默认锁定就足够了。 These locks make sure that your data is consistent within a transaction. 这些锁可确保您的数据在事务中保持一致。 But here's a scenario that needs a lock using SELECT ... FOR UPDATE : 但这是一个需要使用SELECT ... FOR UPDATE锁定的场景SELECT ... FOR UPDATE

Consider you are making a web application in which your session data is stored in database. 考虑您正在创建一个Web应用程序,其中会话数据存储在数据库中。 Race condition is a concern when it comes to session data. 在会话数据方面, 竞争条件是一个问题 While this concern is satisfied when files are used to store session data, but if you move them to database it's your duty to make sure requests won't overwrite each other's session changes. 虽然在使用文件存储会话数据时会满足这种担忧,但如果将它们移动到数据库,则有责任确保请求不会覆盖彼此的会话更改。 In this scenario you need to read session data from MySQL using FOR UPDATE to make sure other requests will wait for this one to write back the session and commit the transaction before they could read it. 在这种情况下,您需要使用FOR UPDATE从MySQL读取会话数据,以确保其他请求将等待此会话回写会话并提交事务,然后才能读取它。

[UPDATE] [UPDATE]

Here's a use case for shared mode: 以下是共享模式的用例:

Shared mode is useful when you want to make sure that some record remains unchanged to the end of your transaction. 如果要确保某些记录在事务结束时保持不变,则共享模式非常有用。 eg when you are trying to insert a child record with a foreign key to a parent when the parent record has been inserted in previous transactions. 例如,当您在先前的事务中插入父记录时,尝试将具有外键的子记录插入父项时。 In this case you will first select the parent record locked in shared mode and then try to insert the child to make sure that when you are inserting the child, parent still exists. 在这种情况下,您将首先选择在共享模式下锁定的父记录,然后尝试插入子项以确保在插入子项时,父项仍然存在。 This way other sessions can still read the parent record but no one can change it. 这样,其他会话仍然可以读取父记录,但没有人可以更改它。 That's just off the top of my mind, but in the all use cases of shared mode lock this fact remains the same that you want a record to remain unchanged while it's still accessible for others to read. 这只是我的想法,但在共享模式锁的所有使用情况下,这个事实仍然是相同的,你希望记录保持不变,而其他人仍然可以阅读。

[UPDATE] [UPDATE]

Regarding the transaction isolation level of SERIALIZABLE , the MySQL's documentation is pretty clear. 关于SERIALIZABLE的事务隔离级别, MySQL的文档非常清楚。 If you set the transaction level this way, and also SET autocommit = 0; 如果以这种方式设置事务级别,还要SET autocommit = 0; , then it's exactly like the REPEATABLE READ level plus writing all your select queries with LOCK IN SHARE MODE at the end (unless you mention FOR UPDATE explicitly). ,那么它与REPEATABLE READ级别完全相同,最后用LOCK IN SHARE MODE编写所有选择查询(除非你明确提到FOR UPDATE )。 It means everything you'll touch (explicitly or implicitly) will be locked. 这意味着您将触摸的所有内容(显式或隐式)都将被锁定。 Those that are selected without any mention of locks or those with LOCK IN SHARED MODE are locked in shared mode, and the rest in exclusive mode. 那些在没有提及锁定或选择LOCK IN SHARED MODE情况下被选中的那些被锁定在共享模式中,其余的处于独占模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM