mysqli транзакции / функции сохранения точек против ручного использования query ()

Следующие два фрагмента кода работают одинаково, или делают нативный mysqli Транзакционные функции делают некоторые дополнительные вещи?

Меня особенно интересует, как ошибки обрабатываются и сообщаются (если они вообще имеются) при запуске и совершении транзакций / создании и освобождении точек сохранения.

Используя конкретные mysqli функции для обработки транзакций:

$db = new mysqli('localhost', 'root', 'batman', 'batcave');
if (!$db->begin_transaction()) { throw new Exception($db->error); }
exc_query('INSERT INTO utility_belt SET item="apple"');
exc_query('INSERT INTO utility_belt SET item="banana"');
if (!$db->savepoint('vegetables')) { throw new Exception($db->error); }
exc_query('INSERT INTO utility_belt SET item="potato"');
exc_query('DELETE FROM utility_belt WHERE item="turnip"');
if (!$db->release_savepoint('vegetables')) { throw new Exception($db->error); }
exc_query('INSERT INTO utility_belt SET item="orange"');
if (!$db->commit()) { throw new Exception($db->error); }

Используя старый добрый query Функция сделать то же самое:

$db = new mysqli('localhost', 'root', 'batman', 'batcave');
exc_query('START TRANSACTION');
exc_query('INSERT INTO utility_belt SET item="apple"');
exc_query('INSERT INTO utility_belt SET item="banana"');
exc_query('SAVEPOINT vegetables');
exc_query('INSERT INTO utility_belt SET item="potato"');
exc_query('DELETE FROM utility_belt WHERE item="turnip"');
exc_query('RELEASE SAVEPOINT vegetables');
exc_query('INSERT INTO utility_belt SET item="orange"');
exc_query('COMMIT');

Реализация exc_query функция используется выше:

function exc_query($q) {
global $db;
if (!$db->query($q)) {
throw new Exception($db->error);
}
}

Почему я спрашиваю?

Я иногда получаю проблемы при попытке сделать RELEASE SAVEPOINT <name>и видя SAVEPOINT <name> does not exist, хотя я уверен, что ранее отправил SAVEPOINT <name> на сервер.

На основании того, что я прочитал в Документация MariaDB, эта ошибка может быть выдана, если START TRANSACTION не удалось в моих примерах. В этом случае транзакция не будет запущена, поэтому SAVEPOINT <name> будет игнорироваться, но RELEASE SAVEPOINT <name> впоследствии выкинет ошибку.

Что меня удивляет, так это то, что следующая строка не перехватывает сбои при создании первоначальной транзакции в этих случаях:

if (!$db->query($q)) {
throw new Exception($db->error);
}

… так что я не уверен, прав я или нет. К сожалению, официальная документация PHP о том, как работают эти функции mysqli не очень полезный.

2

Решение

На основе https://github.com/php/php-src/blob/master/ext/mysqli/mysqli_nonapi.c#L1115:

static int mysqli_savepoint_libmysql(MYSQL * conn, const char * const name, zend_bool release)
{
int ret;
char * query;
unsigned int query_len = spprintf(&query, 0, release? "RELEASE SAVEPOINT `%s`":"SAVEPOINT `%s`", name);
ret = mysql_real_query(conn, query, query_len);
efree(query);
return ret;
}

PHP просто отправляет точно такой же запрос в базу данных, и больше ничего не делает.

Почему MySQLi::savepoint() будет работать иначе, чем MySQLi::query("SAVEPOINT"), Я понятия не имею. Обработка ошибок внутри исходного кода PHP выглядит одинаково, поэтому я ожидаю, что результат вашего $db->query($q) быть false если что-то пойдет не так.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]