Всем хорошего дня!
Есть БД (таблицы с данными и несколько запросов) на файл-сервере. Формат Access 2007-2013 .accdb.
Пользователи присоединяются к базе через интерфес Excel с и использованием ADODB. Часть запросов храниться в виде хард-кода на VBA, часть внутри БД.
Выполнение одних и тех же действий, когда к базе подключен 1 пользователь и когда более различается как 20 сек и 3 мин. Может быть дело в типах блокировки или свойствах курсора соединения, но способа лечения не нашел.
Ниже приложу картинки с сетевым трафиком (там видно, что для 2-х пользователей кол-во передаваемых по сети данных превышает объем БД, хранящейся на файл-сервере - сейчас это 9 МБ).
Вот перечень операций (макс обновление на 400 записей), которые выполняются и в том и другом случае:
transaction_level = SMART_CNN.Cnn.BeginTrans
'*************************************** _
'РАСЧЕТ Абонентской базы
SQL_query = "SELECT bld_params.* " _
& "FROM bld_params INNER JOIN Buildings ON bld_params.ID_SU = Buildings.ID_SU WHERE Buildings.Processed=0 " _
& "ORDER BY bld_params.ID_SU, bld_params.Life_Time;"
Aab_Tkd_RS.CursorType = adOpenKeyset
Aab_Tkd_RS.Open SQL_query, SMART_CNN.Cnn, adOpenKeyset, adLockOptimistic
With Aab_Tkd_RS
'редактируем рекордсет ~ 400 записей
предыдущее_значение=![Поле1]
if(предыдущее_значение<>"") then
![Поле1]=![Поле1]*предыдущее_значение*коэффициент_какой-то
endif
.Update
.MoveNext
Loop
End With
'если что-то пойдет не так то выполнится
If (rez <> "OK") Then
BasicFunctions.UserDataDisplayError (rez & vbNewLine & "Изменения в модели будут отменены!")
SMART_CNN.Cnn.RollbackTrans
GoTo ExecExit
End If
'***************************************
Aab_Tkd_RS.Close
'*************************************** _
РАСЧЕТ OPEX
SQL_query = "DELETE * FROM opex " _
& "WHERE data_id in (SELECT data_id FROM bld_params WHERE Processed=0);"
SMART_CNN.Cnn.Execute SQL_query, adExecuteNoRecords, dbFailOnError 'УБИРАЕМ ПРЕДЫДУЩИЕ ДАННЫЕ
SQL_query="UPDATE еще 400 записей"
SMART_CNN.Cnn.Execute SQL_query, adExecuteNoRecords, dbFailOnError
If (rez <> "OK") Then
BasicFunctions.UserDataDisplayError (rez & vbNewLine & "Изменения в модели будут отменены!")
SMART_CNN.Cnn.RollbackTrans
GoTo ExecExit
End If
BasicFunctions.WriteIntoLog 22, "Кол-во домов: " & bld_counter
'***************************************
PrDisplayer.Recharge
'*************************************** _
РАСЧЕТ CAPEX
SQL_query="UPDATE еще 400 записей"
SMART_CNN.Cnn.Execute SQL_query, adExecuteNoRecords, dbFailOnError
If (rez <> "OK") Then
BasicFunctions.UserDataDisplayError (rez & vbNewLine & "Изменения в модели будут отменены!")
SMART_CNN.Cnn.RollbackTrans
GoTo ExecExit
End If
BasicFunctions.WriteIntoLog 23, "Кол-во домов: " & bld_counter
'***************************************
'*************************************** _
РАСЧЕТ ВЫРУЧКИ
SQL_query = "DELETE * FROM Revenue_Profits WHERE data_id in (SELECT data_id FROM bld_params WHERE Processed=0);"
SMART_CNN.Cnn.Execute SQL_query, adExecuteNoRecords, dbFailOnError 'УБИРАЕМ ПРЕДЫДУЩИЕ ДАННЫЕ
rez = ProcessRevenueAndProfits(PrDisplayer)'функция открывает рекордсет и редактирует 400 записей, _
'так же, как это выполняется в части кода РАСЧЕТ Абонентской базы
If (rez <> "OK") Then
BasicFunctions.UserDataDisplayError (rez & vbNewLine & "Изменения в модели будут отменены!")
SMART_CNN.Cnn.RollbackTrans
GoTo ExecExit
End If
BasicFunctions.WriteIntoLog 24, "Кол-во домов: " & bld_counter
'***************************************
'*************************************** _
РАСЧЕТ Cash Flow
SQL_query = "DELETE * FROM CashFlow WHERE data_id in (SELECT data_id FROM bld_params WHERE Processed=0);"
SMART_CNN.Cnn.Execute SQL_query, adExecuteNoRecords, dbFailOnError 'УБИРАЕМ ПРЕДЫДУЩИЕ ДАННЫЕ
SMART_CNN.Cnn.Execute "CF_data", adExecuteNoRecords, dbFailOnError 'СЧИТАЕМ CF
BasicFunctions.WriteIntoLog 25, "Кол-во домов: " & bld_counter
'***************************************
'ФИНАЛИЗАЦИЯ РАСЧЕТА
SMART_CNN.Cnn.Execute "UPDATE bld_params SET Processed=1 WHERE Processed=0;", adExecuteNoRecords, dbFailOnError
SMART_CNN.Cnn.Execute "UPDATE buildings SET Processed=1 WHERE Processed=0;", adExecuteNoRecords, dbFailOnError
SMART_CNN.Cnn.CommitTrans
BasicFunctions.WriteIntoLog 27, "Домов: " & bld_counter
'***************************************
При запуске Excel на стороне пользователя происходит соединение с БД:
Public DataWorkBook As Excel.Workbook
Public Log_CNN As SmartCnn 'соединение с лог-файлом
Public SMART_CNN As SmartCnn 'соединение с лог-файлом
Public MyUser As SMART_User
Public SMART_Exec As SMART_Extractor
Public SMART_Ribbon As IRibbonUI
Public button_enable_state As Boolean
#If VBA7 And Win64 Then
' 64 битный Excel
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongLong)
Public Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long
#Else
' 32 битный Excel
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Declare Function timeGetTime Lib "winmm.dll" () As Long
#End If
Function Init() As Boolean 'запускаем все нужные соединения и классы объектов перед работой
Dim cnn_string As String
Dim MySmartCnn As SmartCnn
Set MyUser = New SMART_User 'СОЗДАЕМ ПОЛЬЗОВАТЕЛЯ, ПОЛУЧАЕМ СЕТЕВОЙ ЛОГИН
button_enable_state = True 'по умолчанию все элементы ленты активны
If (ActiveWorkbook Is Nothing) Then
Exit Function
End If
Set DataWorkBook = ActiveWorkbook
If Not (BasicFunctions.CheckFilePath(SMART_DB_PATH & "\" & SMART_DB_NAME)) Then
MsgBox "Не найден файл базы данных SAMRT", vbCritical, "SMART processor"
Init = False
Exit Function
End If
If Not (BasicFunctions.CheckFilePath(SMART_DB_PATH & "\" & LOG_DB_NAME)) Then
MsgBox "Не найден файл базы данных ведения лога", vbCritical, "SMART processor"
Init = False
Exit Function
End If
'ОПРЕДЕЛЯЕМ РАЗМЕЩЕНИЕ ВРЕМЕННОЙ БД
user_tmp_db_path = Application.DefaultFilePath
'*************************************** _
ПОДКЛЮЧЕНИЕ ЛОГ - ФАЙЛА
Set Log_CNN = New SmartCnn
cnn_string = "Provider=Microsoft.ACE.OLEDB.12.0;" _
& "Data Source=" & SMART_DB_PATH & "\" & LOG_DB_NAME & ";" _
& "Jet OLEDB:Database Password=********;"
If Not (Log_CNN.CreateADOConnectionToDB(cnn_string)) Then
MsgBox "Не удалось подключиться к базе данных LOGa.", vbCritical, "SMART processor"
Init = False
End If
'***************************************
'*************************************** _
ПОДКЛЮЧЕНИЕ ФАЙЛА БАЗЫ ДАННЫХ
Set SMART_CNN = New SmartCnn
cnn_string = "Provider=Microsoft.ACE.OLEDB.12.0;" _
& "Data Source=" & SMART_DB_PATH & "\" & SMART_DB_NAME & ";" _
& "Jet OLEDB:Database Password=*********;"
If Not (SMART_CNN.CreateADOConnectionToDB(cnn_string)) Then
MsgBox "Не удалось подключиться к базе данных SMART.", vbCritical, "SMART processor"
Init = False
Exit Function
End If
'***************************************
MyUser.CheckUp (MyUser.WinName)
'MyUser.CheckUp ("Lis")
If Not (MyUser.ValidUser) Then
BasicFunctions.UserDataDisplayError ("У пользователя " & MyUser.WinName & " нет доступа к SMART-модели.")
Init = False
Exit Function
End If
If (MyUser.Status = "Deleted") Then
BasicFunctions.UserDataDisplayError ("Ууу разбойник! Пользователю " & MyUser.WinName & vbCrLf _
& " доступ к SMART-модели заблокирован.")
Init = False
Exit Function
Else
MyUser.SetCurrentCompName
End If
BasicFunctions.WriteIntoLog 1
Init = True
Exit Function
End Function
Код класса SmartCnn:
Public WithEvents Cnn As ADODB.Connection
Private start_exec_time As Long 'в миллисекундах
Private exec_time As Long 'в миллисекундах
Private exec_timeout As Long 'в секундах
Private Sub Class_Initialize()
Set Me.Cnn = New ADODB.Connection
Me.Cnn.CursorLocation = adUseClient
exec_timeout = SMART_EXEC_TIMEOUT
End Sub
Public Function CreateADOConnectionToDB(cnn_string As String) As Boolean
On Error GoTo ErrHandler
Me.Cnn.Open cnn_string, "Admin", , adConnectUnspecified
CreateADOConnectionToDB = True
Exit Function
ErrHandler:
'BasicFunctions.RaiseError 514
If (Err.Number = 3705) Then
MsgBox Err.Description
CreateADOConnectionToDB = False
Exit Function
End If
BasicFunctions.DisplayError
End Function
Private Sub Cnn_ExecuteComplete(ByVal RecordsAffected As Long, ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, ByVal pCommand As ADODB.Command, ByVal pRecordset As ADODB.Recordset, ByVal pConnection As ADODB.Connection)
exec_time = BasicFunctions.timeGetTime - start_exec_time
End Sub
Private Sub Cnn_WillExecute(Source As String, CursorType As ADODB.CursorTypeEnum, LockType As ADODB.LockTypeEnum, Options As Long, adStatus As ADODB.EventStatusEnum, ByVal pCommand As ADODB.Command, ByVal pRecordset As ADODB.Recordset, ByVal pConnection As ADODB.Connection)
start_exec_time = BasicFunctions.timeGetTime
exec_time = 0
End Sub
Public Property Get ExecTime() As Long
ExecTime = exec_time
End Property
Public Sub CheckExecTimeout()
If (exec_time <> 0) Then Exit Sub
If (((BasicFunctions.timeGetTime - start_exec_time) / 1000) > exec_timeout) Then
BasicFunctions.UserDataDisplayError "Превышен лимит времени в " & exec_timeout & " секунд при привыполнении запроса к модели."
Me.Cnn.Cancel
End If
End Sub
Не смотря на то, что устанавливаю свойство соединения
Me.Cnn.CursorLocation = adUseClient
, когда в RunTime смотрю на объект SMART_CNN.Cnn у него это свойство поставлено в adUseClientBatch
Гуру, help plase.
http://www.sql.ru/forum/1206894/bd-accees-2013-accdb-nepomernyy-rost-setevogo-trafika-pri-kol-ve-polzovateley-1