НЕТ - Блокировка не распространяется на сервер (ы).Таким образом, явная блокировка на подчиненном сервере не блокирует соответствующие таблицы на главном сервере, и наоборот .
Простой обходной путь, который мы использовали в нашемВ этом случае необходимо было направить все эти конкретные запросы блокировки на только главный сервер .Таким образом, независимо от того, какой сеанс клиента выполняется, эти запросы всегда выполняются только на главном сервере.Таким образом обрабатываются параллельные проблемы с подключением.
Я сделал подобный тип фильтрации в PHP-коде.Для направления запросов на соответствующие серверы (чтение запросов на ведомый и запись запросов на ведущий) пишется пользовательская функция для идентификации типа запроса.
Один примечательный момент заключается в том, что запросыв рамках транзакции / блокировки / разблокировки всегда рассматриваются запись запросов.
Кроме того, для Set
только SET AUTOCOMMIT
и SET TRANSACTION
являются командами записи.
Ниже приведена в значительной степени уменьшенная версия фактического кода, который мы используем:
/*
* All the WRITE operation commands
*/
$write_commands = array(
'create',
'alter',
'drop',
'truncate',
'comment',
'rename',
'insert',
'update',
'delete',
'merge',
'call',
'lock',
'unlock',
'start',
'commit',
'rollback',
'savepoint',
'set',
'replace'
);
/*
* method to determine whether Read or Write
* @param $sql String (SQL query string)
* @return: void
*/
function determineReadOrWrite(string $sql): void {
$dml_query = false;
$words = str_word_count(strtolower(trim($sql)), 1);
$first_word = isset($words[0]) ? $words[0] : '';
$second_word = isset($words[1]) ? $words[1] : '';
if (in_array($first_word, $this->write_commands)) {
/* if it is not "set" then we set to master link */
if ($first_word !== 'set'
|| ($first_word === 'set' && $second_word === 'autocommit')
|| ($first_word === 'set' && $second_word === 'transaction')
) {
$dml_query = true;
/* If we Lock tables or Begin a Transaction, we should run on Write servers only */
/* till we Commit/Rollback or Unlock Tables */
if(($first_word === 'start' && $second_word === 'transaction')
|| $first_word === 'lock'){
/* Set whether the current query is starting a Transaction / Lock etc */
$this->wait_for_commit_rollback = true;
}
/* We are doing Commit/Rollback or Unlock Tables */
if ($first_word === 'commit'
|| $first_word === 'rollback'
|| $first_word === 'unlock') {
$this->wait_for_commit_rollback = false;
}
}
}
/* It's a insert/update/delete/etc query - to be run on Write Db only */
if ($dml_query || $this->wait_for_commit_rollback) {
$this->setActiveConnectionToWrite(true);
} else {
$this->setActiveConnectionToRead();
}
}