通过 MySQL InnoDB 行锁的应用程序互斥
我的应用程序由几个与通用 MySQL 机器通信的 Apache 服务器组成。该应用程序的一部分允许用户创建未来一小时的约会。我需要一种机制来防止不同的用户同时来自不同的 Apache 实例,预订相同的一小时预约时段。我已经看到在 Oracle 数据库上实现了类似的“系统间互斥”解决方案(基本上是“选择...进行更新”),但还没有处理在 MySQL 上执行相同操作的详细信息。希望有任何建议、代码或文档参考、最佳实践等。我尝试用谷歌搜索,但主要是关于 MySQL 内部互斥体的讨论。
这些是我认为相关的 MySQL 设置(我的代码将具有 try-catch 和所有内容,并且在不解锁其锁定的内容的情况下决不应该放弃,但也必须考虑在这些情况下发生的情况):
mysql> show variables like 'innodb_rollback_on_timeout';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| innodb_rollback_on_timeout | OFF |
+----------------------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 100 |
+--------------------------+-------+
1 row in set (0.00 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
任何替代解决方案(MySQL 之外)可以推荐吗?我确实也有一个 memcached 实例在运行,但经常被刷新(并且不确定我是否想要 memcachedb 等来实现容错)。
感谢您的帮助...
My application consists of a couple of Apache servers talking to a common MySQL box. Part of the application lets users create one hour appointments in the future. I need a mechanism which prevents different users coming from the different Apache instances at the same time, book the same one hour appointment slot. I've seen a similar "inter-system mutex" solution implemented on Oracle databases (basically 'select ... for update') but haven't dealt with the details on doing the same with MySQL. Would appreciate any advise, code or documentation references, best practices, etc. Did try to google around but mostly discussions about the MySQL internal mutexes come up.
These are my MySQL settings I thought relevant (my code will have try-catch and all and should never bail without unlocking what it locked but have to account for what happens in those cases as well):
mysql> show variables like 'innodb_rollback_on_timeout';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| innodb_rollback_on_timeout | OFF |
+----------------------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 100 |
+--------------------------+-------+
1 row in set (0.00 sec)
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
Any alternate solutions (outside of MySQL) you could recommend? I do have a memcached instance running as well but gets flushed rather often (and not sure I want to have memcachedb, etc. to make that fault tolerant).
Appreciate your help...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
还可以使用 MySQL 和 MariaDB 的
GET_LOCK
(和RELEASE_LOCK
)函数:https://dev.mysql.com/doc/refman/5.5/en/miscellaneous -functions.html#function_get-lock(过时的链接)这些函数可用于实现问题中描述的行为。
获取锁
my_app_lock_1
。释放锁:
请注意(引自MariaDB的文档):
名称在服务器范围内被锁定。 如果某个名称已被一个客户端锁定,
GET_LOCK()
会阻止另一个客户端对同名锁的任何请求。这允许客户端就给定的锁达成一致name 使用该名称来执行协作咨询锁定。但请注意,它还允许不在合作客户端集合中的客户端无意或有意地锁定名称,从而防止任何合作客户端锁定该名称。减少这种可能性的一种方法是使用特定于数据库或特定于应用程序的锁名称。例如,使用db_name.str
或app_name.str
形式的锁名称。使用
GET_LOCK()
获取的锁不会与事务交互。One can also use MySQL's and MariaDB's
GET_LOCK
(andRELEASE_LOCK
) functions:https://dev.mysql.com/doc/refman/5.5/en/miscellaneous-functions.html#function_get-lock(outdated link)The functions can be used to realize the behavior described in the question.
Acquiring a lock
my_app_lock_1
.Releasing the lock:
Please note (the quotes from MariaDB's documentation):
在这里回答我自己的问题。我们最终(在 PHP 中)所做的事情是这样的:
为了验证它是否可以从两个不同的控制台运行。时间性能比基于标准文件锁的互斥锁要差一些,但仍然可以接受。
Answering my own question here. A variation of this is what we eventually end up doing (in PHP):
To verify it works run from two different consoles. Time performance is a bit worse than standard file lock based mutexes but still very acceptable.