【发布时间】:2020-06-06 15:27:55
【问题描述】:
This question 比较 SELECT...LOCK IN SHARE MODE 和 SELECT...FOR UPDATE。但是,这两个与事务中的 SELECT 有何不同?数据库是 MariaDB,但如果没有差异,MySQL 的答案也应该没问题。最重要的是,我需要在避免数据库死锁的背景下获得信息。
【问题讨论】:
标签: mysql sql select transactions mariadb
This question 比较 SELECT...LOCK IN SHARE MODE 和 SELECT...FOR UPDATE。但是,这两个与事务中的 SELECT 有何不同?数据库是 MariaDB,但如果没有差异,MySQL 的答案也应该没问题。最重要的是,我需要在避免数据库死锁的背景下获得信息。
【问题讨论】:
标签: mysql sql select transactions mariadb
可以避免很多死锁;有些不能。没有一种技术可以防止所有死锁。
FOR UPDATE 似乎比LOCK IN SHARE MODE 更有用。 (我很想听到有人反对。)
通常的模式似乎是:
BEGIN;
SELECT ... FOR UPDATE; -- use the columns fetched; lock the row(s)
-- Note: the locked rows may or may not actually be UPDATEd later
-- Note: FOR UDPATE prevents other connections from grabbing the same row(s)
UPDATE/DELETE/... -- those rows.
COMMIT;
但是......以上没有任何东西可以防止经典的死锁场景:
BEGIN; -- connection 1
SELECT row 123 FOR UPDATE;
SELECT row 234 FOR UPDATE;
...
对比
BEGIN; -- connection 1
SELECT row 234 FOR UPDATE;
SELECT row 123 FOR UPDATE; -- Note: locking order was swapped
...
未能执行某种形式的SELECT ...LOCK/UPDATE 很容易导致“竞争条件”,其中两个连接以不一致的方式作用于同一行。
另一个注意事项:如果您以相同的顺序“锁定”相同的行,那么一个连接可能会停止,直到另一个连接释放。 (cf innodb_lock_wait_timeout,默认为 50 秒 [我认为时间过长])
(我所有的讨论都应该适用于 MySQL 或 MariaDB 中所有版本的 InnoDB/XtraDB。)
【讨论】: