MySQL 中的锁定是什么?什么时候会使用它?

发布于 2024-09-11 10:12:17 字数 53 浏览 2 评论 0原文

MySQL(或任何 RDBMS)中的锁定是什么?什么时候会使用它?带有示例的外行解释会很棒!

What is Locking in MySQL (or any RDBMS) and when would you use it? A Layman explanation with a Example would be great!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

執念 2024-09-18 10:12:17

我们有一个联名银行帐户,余额为 200 美元

我去 ATM 机,将卡放入机器,机器检查我的余额为 200 美元

同时,你走进银行并要求 50 美元,柜员提出您的帐户并确认您有钱。

我请求提款 200 美元,机器计数我的钱给我 200 美元,并将我的余额设置为 0 美元

出纳员数算您的钱并给您 50 美元,然后系统将帐户余额更新为 150 美元(200 美元 - 50 美元提款)。

现在我们的账户里有 250 美元现金和 150 美元。利润200美元。

数据库应该使用锁来防止两个事务同时发生。

问题是,如果您以这种方式处理每个事务,那么我们将失去并发性,性能也会受到影响,因此根据场景使用不同的事务隔离级别,例如您可能不关心有人可以修改事务中已读取的数据。

http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

您应该学习这些并了解它们的适用场景。

We have a joint bank account with a balance of $200

I go to the ATM and put my card into the machine, the machine checks that I have a balance of $200

Meanwhile, you go into the bank and ask for $50, the teller brings up your account and confirms that you have the money.

I request a withdrawal of $200, the machine counts my money gives me $200 and sets my balance at $0

The teller counts your money and gives you the $50, the system then updates the balance on the account as $150 ($200 - $50 withdrawl).

So now we have $250 cash and $150 left in the account. $200 profit.

The database should have used locks to prevent both transactions occuring at the same time.

The problem is if you handle every transaction in that way then we would lose concurrency and performance would suffer, so there are different transaction isolation levels that are used depending on the scenario, for instance you might not care that someone can modify data that has been read in a transaction.

http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

You should learn these and understand the scenarios where they are applicable.

各自安好 2024-09-18 10:12:17

锁定对于避免两个用户同时修改数据至关重要。您可能认为这不太可能,但根据应用程序的不同,如果不同的用户频繁更改相同的数据,则存在重大风险。

想象一下以下情况,使用锁:John 打开他的屏幕(他不知道他正在使用数据库,他只是一个正在查看漂亮屏幕的最终用户),修改一些数据,然后然后点击“保存”。假设 John 在 9:30 打开屏幕,然后在 9:32 保存数据。

然而,玛丽在 9 点 29 分打开了完全相同的屏幕和相同的记录。她当时看到的数据与约翰在 9:30 看到的数据相同。然后,她更新了记录,并在 9 点 31 分点击“保存”。

保存了哪些数据?约翰的还是玛丽的?

玛丽高兴地继续处理其他记录,当她稍后回来再次打开记录时,她发现她的更改丢失了,而她看到了约翰的更改!

请注意,必须明智地使用锁定,以防止意外的副作用。例如,假设您的程序在每次有人打开记录进行更改时都会锁定该记录。如果约翰锁定记录并打开会话屏幕去吃午饭或者失去连接,会发生什么情况?锁可以长时间保留在那里,锁定且不可更改,同时禁止其他人更改(甚至查看)该记录。其他考虑因素可能是性能,因为对于大量事务,数据库锁定和解锁记录的时间可能会变得很明显。

了解锁定对于维护用户满意度和数据完整性至关重要。请查看文档。

Locking can be crucial to avoid two users modifying data at the same time. You may think that's unlikely, but depending on the application, there is a significant risk if the same data is frequently changed by different users.

Imagine the following situation without using locks: John opens his screen (he doesn't know he's using a database, he is only an end user who is looking at a pretty screen), modifies some data, and then hits "Save". Let's say John open the screen at 9:30 and then saves the data at 9:32.

However, Mary opened exactly the same screen and the same record at 9:29. She saw at that time the same data that John did at 9:30. Then, she updates the record, and hits "Save" at 9:31.

What data was saved? John's or Mary's?

Mary happily keeps working on other records, and when she comes back later to open the record again, she sees that her changes were lost, and she sees John's changes instead!!

Be aware that locking has to be used wisely to prevent unexpected side-effects. For example, let's say that your program locks a record every time somebody opens it make a change. What happens if John locks the record, and leaves his session screen open to have lunch or he looses his connection? The lock can remain there, locked and unchangeable, for a long time, while prohibiting everybody else from changing (or even looking at) that record. Other consideration may be performance, because the time for the database to lock and unlock records may become noticeable for a large number of transactions.

Understanding locking is crucial to maintain happy users and data integrity. Please look at the documentation.

飘过的浮云 2024-09-18 10:12:17

几天前,我回答了 关于SO的问题并给出了一个示例,演示了锁定 允许多个用户同时在具有递增 id 的表中插入行,而无需使用 AUTO_INCRMENT

以以下模式为例:

CREATE TABLE demo_table (id int) ENGINE=INNODB;

-- // Add few rows
INSERT INTO demo_table VALUES (1), (2), (3);

然后我们可以执行以下操作:

START TRANSACTION;

-- // Get the MAX(id) so that we increment it by one
SELECT @x := MAX(id) FROM your_table FOR UPDATE;

+---------------+
| @x := MAX(id) |
+---------------+
|             3 |
+---------------+
1 row in set (0.00 sec)

FOR UPDATE 语法实际上是对该查询读取的行加锁。

在不提交事务的情况下,我们启动另一个单独的会话(模拟并发用户),并执行相同的操作:

START TRANSACTION;

-- // Get the MAX(id) as well
SELECT MAX(id) FROM demo_table FOR UPDATE;

数据库将等到前一个会话中设置的锁被释放后再运行此查询。

因此切换到上一个会话,我们可以插入新行并提交事务:

-- // Insert a new row with id = MAX(id) + 1
INSERT INTO demo_table VALUES (@x + 1);

COMMIT;

第一个会话提交事务后,锁将被解除,并返回第二个会话中的查询:

+---------+
| MAX(id) |
+---------+
|       4 |
+---------+
1 row in set (8.19 sec)

注意,没有锁定,第二个会话会立即返回,但将 3 作为 MAX(id) 而不是 4。如果两个会话都要插入 idMAX(id) + 1 的行,则两者都会插入 id = 4。您可以在没有 FOR UPDATE 位的情况下模拟相同的测试,以了解如何在没有锁的情况下处理此问题。

A few days ago I answered a question on SO and gave an example which demonstrates a situation where locking allows multiple users to concurrently insert rows in a table with an incrementing id, without using AUTO_INCREMENT.

Consider the following schema as an example:

CREATE TABLE demo_table (id int) ENGINE=INNODB;

-- // Add few rows
INSERT INTO demo_table VALUES (1), (2), (3);

Then we can do the following:

START TRANSACTION;

-- // Get the MAX(id) so that we increment it by one
SELECT @x := MAX(id) FROM your_table FOR UPDATE;

+---------------+
| @x := MAX(id) |
+---------------+
|             3 |
+---------------+
1 row in set (0.00 sec)

The FOR UPDATE syntax is what actually puts a lock on the rows read by this query.

Without committing the transaction, we start another separate session (simulating a concurrent user), and do the same:

START TRANSACTION;

-- // Get the MAX(id) as well
SELECT MAX(id) FROM demo_table FOR UPDATE;

The database will wait until the lock set in the previous session is released before running this query.

Therefore switching to the previous session, we can insert the new row and commit the transaction:

-- // Insert a new row with id = MAX(id) + 1
INSERT INTO demo_table VALUES (@x + 1);

COMMIT;

After the first session commits the transaction, the lock will be lifted, and the query in the second session is returned:

+---------+
| MAX(id) |
+---------+
|       4 |
+---------+
1 row in set (8.19 sec)

Note that without locking, the second session would have returned immediately, but with 3 as MAX(id) instead of 4. If both sessions were to insert a row with an id of MAX(id) + 1, both would insert id = 4. You can simulate the same test without the FOR UPDATE bit to see how this is handled without locks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文