2014-12-04 2 views
0

Если у меня есть 2 следующие функции:Является ли возвращение last_insert_id всегда правильным?

int AccessDb::InsertColValue(string tableName, string col, string val) 
{ 
    try 
    { 
     sql::Statement *stmt; 
     bool ret; 

     if ((nomTable != "") && (col != "") && (val != "")) 
     { 
      string query = "INSERT INTO " + tableName + "(" + col + ") values ("; 
        query += val + ");"; 

      stmt = con->createStatement(); 
      ret = stmt->execute(query); 
     } 

     delete stmt; 

     return 0; 
    } 
    catch (sql::SQLException &e) 
    { 
     return -1; 
    } 
} 

и

long AccessDb::LastInsertId() 
{ 
    try 
    { 
     sql::Statement *stmt; 
     sql::ResultSet *res; 

     string query = "SELECT LAST_INSERT_ID() AS LAST_ID"; 

     stmt = con->createStatement(); 
     res = stmt->executeQuery(query); 

     delete stmt; 

     long lastId; 
     while (res->next()) 
     { 
      lastId = res->getInt("LAST_ID"); 
     } 

     return lastId; 
    } 
    catch (sql::SQLException &e) 
    { 
     return -1; 
    } 
} 

Могу ли я быть уверен, что возвращение LastInsertId() всегда будет давать мне правильный идентификатор, если я пишу следующие строки и если идентификатор автоматически генерируется базой данных?

AccessDb adb; // initialize the connexion with the db 
int ret = adb.InsertColValue("people", "name", "John"); 
if (ret == 0) 
    long lastId = adb.LastInsertId(); 

Если предыдущий код называется где-то еще в то же самое время, я могу иметь неверное значение в моей lastId переменной? Если да, нужно ли мне использовать блокировки и разблокировки на моем столе, чтобы избежать этого или другого решения?

+1

Функция зависит от сеанса, поэтому до тех пор, пока только один процесс может быть связан с данным сеансом, он вернет последний идентификатор вставки для этого сеанса. – Strawberry

ответ

2

Вот что говорит Docs:

Идентификатор, который был сгенерирован сохраняется на сервере на каждого подключения отдельно. Это означает, что значение, возвращаемое функцией данному клиенту, является первым значением AUTO_INCREMENT, сгенерированным , для самого последнего заявления, влияющего на столбец AUTO_INCREMENT, с помощью этого клиента . Это значение не может повлиять на других клиентов, даже если они генерируют собственные значения AUTO_INCREMENT. Такое поведение обеспечивает , что каждый клиент может получить свой собственный ID без учета активности других клиентов и без необходимости блокировок или транзакций.

Так что, если ваш собственный код на клиенте не делится связь между несколькими потоками (который он выглядит, как вы нет, так как нет мьютексы или замки в вашем коде) вы можете быть уверены, что ВЫБРАТЬ LAST_INSERT_ID () не смешивается с каким-либо другим соединением или клиентом.

Я не могу найти документы для библиотеки mysql C++, но проверьте, что возвращаемое значение ret = stmt->execute(query); в вашей функции InsertColValue() означает, что вы уверены, что единственный возможный способ, который вы не вставляете, - это когда исключение бросается.

+0

ах да, руководство. Нам сказали держать это в секрете! – Strawberry

+0

Спасибо за ваш ответ. Я использую несколько потоков, но я попытался свести свой пример к самому простому и забыл это сказать. Должен ли я использовать мьютексы, чтобы убедиться, что последний идентификатор верен? – Aleph0

+0

@ Aleph0 Я не знаю, нужно ли вам это делать или нет, это зависит от того, как вы создали код кода. Необходимо убедиться, что ни один другой SQL не запускается в одном соединении между оператором INSERT и точкой, в которой вы извлекаете LAST_INSERT_ID() – nos

Смежные вопросы