Bu yüzden birkaç hafta önce bu evcil hayvan projesinde boş zamanımda çalışıyorum ve üzerinde sıkıştığım bir sorunla karşılaştım. SO'yu inceledim ve sorunu çözdüm, konuyla ilgili gerçekten hiçbir şey bulamadım.İmleç durumu, C++ eşzamanlılığı ve SQL sunucusu
Yerel bir SQL Server örneğine bağlanmak için bir ODBC sürücüsü kullanan çok iş parçacıklı (C++ uygulamasında çok iş parçacığı için çok yeniyim) çalışıyorum. Bağlantı düzgün çalışıyor ve numaralı telefondan numaralı ana parçayı kullanıyor. Ancak, birden fazla iş parçacığı kullanmaya başladığımda (yukarıda belirtildiği gibi, bok gibi görünüyor - deneme yanılma ile öğreniyorum) C++ concurrencty ve saklı yordamla ilgili olduğunu düşündüğüm hata iletileri alıyorum SQL sunucusunda çalışıyor.
show_error tarafından görüntülenen gibi hata iletisi:
: AşağıdaUSE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_addHistorical] Script Date: 30/03/2016 10:16:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_addHistorical]
@Symbol nchar(10),@Date datetime,
@Open decimal(12,2),@Close decimal(12,2),@MinPrice decimal(12,2),
@MaxPrice decimal(12,2),@Volume int
AS
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRANSACTION
MERGE HistoricalStock WITH (UPDLOCK) AS myTarget
USING (SELECT @Symbol AS Symbol,
@Date AS Date, @Open AS [Open], @Close AS [Close],
@MinPrice AS MinPrice, @MaxPrice AS MaxPrice,@Volume AS Volume) AS mySource
ON mySource.Symbol = myTarget.Symbol AND mySource.Date = myTarget.Date
WHEN MATCHED
THEN UPDATE
SET [Open] = mySource.[Open], [Close] = mySource.[Close],
MinPrice = mySource.MinPrice, MaxPrice = mySource.MaxPrice, Volume = mySource.Volume
WHEN NOT MATCHED
THEN
INSERT(Symbol,Date,[Open],[Close],MinPrice,MaxPrice,Volume)
VALUES(@Symbol,@Date,@Open,@Close,@MinPrice,@MaxPrice,@Volume);
COMMIT
veritabanı konnektör ve boktan parçacığı olduğunu
#include "stdafx.h" #include "database_con.h" //////////////////////////////////////////////////////////////////////// // Show errors from the SQLHANDLE void database_con::show_error(unsigned int handletype, const SQLHANDLE& handle) { SQLWCHAR sqlstate[1024]; SQLWCHAR message[1024]; if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL)) wcout << "Message: " << message << "\nSQLSTATE: " << sqlstate << endl; } std::wstring database_con::StringToWString(const std::string& s) { std::wstring temp(s.length(), L' '); std::copy(s.begin(), s.end(), temp.begin()); return temp; } //////////////////////////////////////////////////////////////////////// // Builds the stored procedure query. std::wstring database_con::buildQuery(vector<std::wstring> input, string symbol) { std::wstringstream builder; builder << L"EXEC sp_addHistorical " << "@Symbol='" << L"" << StringToWString(symbol) << "'," << "@Date='" << (wstring)L"" << input.at(0) << "'," << "@Open=" << (wstring)L"" << input.at(1) << "," << "@Close=" << (wstring)L"" << input.at(2) << "," << "@MaxPrice=" << (wstring)L"" << input.at(3) << "," << "@MinPrice=" << (wstring)L"" << input.at(4) << "," << "@Volume=" << (wstring)L"" << input.at(5) << ";"; return builder.str(); } void database_con::executeQuery(wstring query) { if (SQL_SUCCESS != SQLExecDirectW(stmt, const_cast<SQLWCHAR*>(query.c_str()), SQL_NTS)) { std::cout << "Execute error " << std::endl; show_error(SQL_HANDLE_STMT, stmt); std::wcout << L"Unsuccessful Query: " << query << std::endl; } // Close Cursor before next iteration starts: SQLRETURN closeCursRet = SQLFreeStmt(stmt, SQL_CLOSE); if (!SQL_SUCCEEDED(closeCursRet)) { show_error(SQL_HANDLE_STMT, stmt); // maybe add some handling for the case that closing failed. } } //////////////////////////////////////////////////////////////////////// // Constructs a database connector object with the historical data and its symbol database_con::database_con(std::vector<std::vector<std::wstring>> historical, string symbol){ /* Set up the handlers */ /* Allocate an environment handle */ SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); /* We want ODBC 3 support */ SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0); /* Allocate a connection handle */ SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); /* Connect to the DSN */ SQLDriverConnectW(dbc, NULL, L"DRIVER={SQL Server};SERVER=ERA-PC-STUART\\JBK_DB;DATABASE=master;UID=geo;PWD=kalle123;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE); /* Check for success */ if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt)) { show_error(SQL_HANDLE_DBC, dbc); std::cout << "Failed to connect"; } std::cout << "Building and executing the query" << std::endl; for (_mVecHistIter = historical.begin(); _mVecHistIter != historical.end(); _mVecHistIter+5) { std::thread t(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol)); std::thread t2(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol)); std::thread t3(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol)); std::thread t4(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol)); std::thread t5(&database_con::executeQuery, *this, buildQuery(*_mVecHistIter, symbol)); t.join(); t2.join(); t3.join(); t4.join(); t5.join(); //executeQuery(buildQuery(*_mVecHistIter, symbol)); } /*_mSymbol = symbol; std::wstringstream stream(StringToWString(historical)); std::wstring line; int row = 0; while (std::getline(stream, line)) { if (row > 0) { vector<wstring> vHistorical = parseData(L"" + line, ','); std::wstring SQL = buildQuery(vHistorical, _mSymbol); if (SQL_SUCCESS != SQLExecDirectW(stmt, const_cast<SQLWCHAR*>(SQL.c_str()), SQL_NTS)) { std::cout << "Execute error " << std::endl; show_error(SQL_HANDLE_STMT, stmt); std::wcout << L"Unsuccessful Query: " << SQL << std::endl; } // Close Cursor before next iteration starts: SQLRETURN closeCursRet = SQLFreeStmt(stmt, SQL_CLOSE); if (!SQL_SUCCEEDED(closeCursRet)) { show_error(SQL_HANDLE_STMT, stmt); // maybe add some handling for the case that closing failed. } } row++; }*/ std::cout << "Query " << _mSymbol << " ready" << std::endl; } database_con::~database_con() { std::cout << "The database object has been deleted" << std::endl; }