运行我想要按顺序访问数据库的两个并发脚本,以便每个自动增量主键是顺序的。即,当时运行它们(实例A和实例B)将导致
1-A, 2-A, 3-A, 1-B, 2-B, 3-B
然而,目前我得到了
1-A, 1-B, 2-A, 2-B ,3-A ,3-B
事务和锁定表没有像我预期的那样工作,我做了一些更深入的研究,看起来两个脚本(即使在不同的浏览器中运行)都获得相同的连接。因此,他们都在同一个会话中,不会阻止另一个会话。我有什么办法可以强迫他们获得不同的连接(改为mysqli或PDO不是一个选项,因为这是一个现有的系统)?
铬:
object(DB_mysql)#10 (26) {
["phptype"]=>
string(5) "mysql"
...
火狐
object(DB_mysql)#10 (26) {
["phptype"]=>
string(5) "mysql"
...
使用下面的DSN字符串完成数据库创建。 (那里有一些其他的逻辑)
mysql://root:@127.0.0.1/XXX?new_link=true
查询RUN:
LOCK TABLES xxxx write
SET autocommit=0
TRANSATION START
>>insert 1
>>insert 2
>>insert 3
COMMIT
UNLOCK TABLES
两个标签同时刷新: 标签1:
[0]=>
int(56335766)
[1]=>
int(56335768)
[2]=>
int(56335770)
标签2:
array(3) {
[0]=>
int(56335765)
[1]=>
int(56335767)
[2]=>
int(56335769)
}
正如数据显示的那样,尽管表格被锁定,数据仍然交织在一起。
答案 0 :(得分:3)
问:为什么锁定没有工作?
A:根据问题的更新,显示SQL语句的顺序:
LOCK TABLES xxx WRITE
START TRANSACTION
问题是START TRANSACTION
正在释放锁定。
MySQL Reference Manua中记录了这种行为
参考:http://dev.mysql.com/doc/refman/5.6/en/lock-tables.html
锁定释放规则
如果会话开始一个事务(例如,使用START TRANSACTION
),则隐式{执行{1}}会导致释放现有锁。 (有关表锁定和事务之间交互的其他信息,请参阅Section 13.3.5.1, “Interaction of Table Locking and Transactions”。
原始问题的原始答案
问:我有什么办法可以强迫他们获得不同的联系吗?
A:我想你可能会在那里咆哮错误的树。很可能每个人都使用不同的数据库连接。
您显示的值 UNLOCK TABLES
, 2-A
, 2-B
似乎是字符串值
如果对这些字符串值执行3-A
SELECT
,则会按照显示返回的顺序返回行。如果没有ORDER BY
,则MySQL是免费的以任何顺序返回行。如果MySQL使用索引返回行,而不执行排序操作,我们(几乎总是)观察到行返回的行与索引中出现的行的顺序相同。
如果您依赖列的ORDER BY
属性,则不会将相同的值分配给两个不同的行(除非您使用的是MyISAM且AUTO_INCREMENT
列不是索引中的前导栏...)
除此之外,两行不会获得相同的auto_increment值。
或者,您在数据库表中获得的内容实际上更像是
AUTO_INCREMENT
auto_id byclient
------- --------
14156 A
14157 B
14158 A
14159 B
14160 A
14161 B
属性位于表的列上,而不是"每个数据库连接"。插入行的两个(或更多)并发会话可以执行"交错"价值。他们不必使用相同的数据库连接。
为了防止其他数据库连接同时对表执行INSERT,您需要实现一种机制来实现这一点。在数据库级别,您可以使用一些并发查杀表锁。但这些只会在它们被释放之前或数据库连接期间一直持有。如果您从数据库断开连接,那些锁就会消失。
因此,如果两个独立的浏览器间歇性地调用相同的PHP页面,那将无法帮助您。即使你确实有办法为每个浏览器会话获得单独的数据库连接。
我强烈怀疑您正在搅拌数据库连接,为每次执行PHP脚本建立新的数据库连接。
(我认为你可能在使用相同的数据库连接时出错了。你会在多个数据库连接中获得相同的行为。)
<强>后续强>
我认为你问的是错误的问题。为什么你需要具有AUTO_INCREMENT id值&#34;按顺序&#34;?如果这是一个实际要求,则可能AUTO_INCREMENT
不适合解决问题。 (好像你可能试图让AUTO_INCREMENT执行一个不适合的任务。在某些配置中,你不能保证AUTO_INCREMENT值会按插入行的顺序升序。)
我不是要求AUTO_INCREMENT值是连续的(这确实是一个要求),而是要备份,而不是考虑真正的要求是什么。也许确定&#34;会话&#34;插入每一行(让每个会话在表中的列中存储一个值,以及客户端为该会话分配的升序整数值。然后你不必关心分配了什么AUTO_INCREMENT值:
AUTO_INCREMENT