PHP PDO SQLSRVR high cpu usage on Database - php

I'm facing a strange problem after reinstall Ubuntu Server 18.04.
My "Server 1" had these packages and drivers to connect PHP-FPM + Apache with a remote Sql Server Database 2016, the connections are using IPv4.
$ odbcinst --version
unixODBC 2.3.7
$ apt list msodbcsql17
msodbcsql17/bionic,now 17.7.2.1-1 amd64 [installed]
$ php --re pdo_sqlsrv | head -1
Extension [ <persistent> extension #33 pdo_sqlsrv version 5.9.0 ]
$ php --re sqlsrv | head -1
Extension [ <persistent> extension #41 sqlsrv version 5.9.0 ]
Below are my /etc/odbcinst.ini content:
$ cat /etc/odbcinst.ini
[ODBC Driver 17 for SQL Server]
Description=Microsoft ODBC Driver 17 for SQL Server
Driver=/opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.7.so.2.1
UsageCount=1
$ openssl version
OpenSSL 1.1.1 11 Sep 2018
My two servers are Ubuntu 18.04, all packages are upgraded.
To clarify, we are no issues on Ubuntu side, the issues are on SQL Server.
Using my "Server 1", Linux and SQL Server are ok and fast.
But using my "Server 2", with a new Ubuntu 18.04 install, my SQL Server use more than 90% CPU, and Linux still fast.
These two Linux uses the same packages and drivers listed above, with exactly same versions.
The PHP code executed are exactly same on two servers.
I forget to look another package or config on my "Server 2"?
I don't know if have relation, but on my SQL Server, the ODBC Driver version is 13. Maybe not, because the "Server 1" does not cause issues.
Thanks!

Finally, I found the problem!
Fast answer
Reading trace log on SQL Server, on "Application Name" field, we can observe that some origins calls DataBase (Apache, PHP-FPM and PHP Freetds)
The issue occurs using PHP SQLSRV (pdo), with only with FreeTDS (php ext DBLIB) does not have problem.
Then is a good idea use only PHP DBLIB with FreeTDS on unix systems.
Complete answer
TL;DR;
Of course, the problem is not with only with PHP SQLSRV extension. On our investigation, we look at diver version, and client Linux uses newest version of driver MSODBCSQL17.
But on our server, running SQL SERVER 2016, the driver version is 13.
But the Microsoft have a upgrade to version 17 (same used on Linux client)
Reading the change log, an issue about high cpu usage is fixed.
"Can you prove?"
Yes!
We didi a simple test, on our linux "server 1", we remove support from freetds (disable DBLIB), and immediately we can observe a decrease performance on our dashboard, and after some minutes, when freetds is enabled again (DBLIB) the performance returns to normal, see above.
Our new linux does not have freetds installed, we only taken drivers from Microsoft to PHP 7+ and PECL extension.
The problem is because our SQL SERVER uses ODBC Driver 13 and our cliente have ODBC Driver 17.
We can not upgrade the driver on SQL SERVER, because we need this version, and ODBC 17 is supported only on SQL SERVER 2019.
Then, for now our solution is to use freetds and not PHP SQLSRV extension.
Another point to observe is, all query from PHP SQLSRV is parametrized like this:
Declare #Out int;
EXEC sp_prepexec #Out output,
N'#P1 nvarchar(128), #P2 nvarchar(100)',
N'SELECT database_id, name
FROM sys.databases
WHERE name=#P1 AND state_desc = #P2',
#P1 = 'tempdb', #P2 = 'ONLINE';
EXEC sp_unprepare #Out;
The same query with freetds appears on tracer log like this:
SELECT database_id, name
FROM sys.databases
WHERE name='tempdb' AND state_desc='ONLINE';
I think that this difference makes SQL SERVER force use more CPU than FreeTDS with more simple query.
But you have installed both, how to decide wich to use?
Yes, on my "server 1" we have both drivers and extensions installed, but my application decide to use first DBLIB is is available, we use Laravel, and this code is inside connector:
/**
* Create a DSN string from a configuration.
*
* #param array $config
* #return string
*/
protected function getDsn(array $config)
{
// First we will create the basic DSN setup as well as the port if it is in
// in the configuration options. This will give us the basic DSN we will
// need to establish the PDO connections and return them back for use.
if (in_array('dblib', $this->getAvailableDrivers())) {
return $this->getDblibDsn($config);
} elseif ($this->prefersOdbc($config)) {
return $this->getOdbcDsn($config);
} else {
return $this->getSqlSrvDsn($config);
}
}
Conclusion
I didn't knows that my applications still using FreeDTS after install PHP SQLSRV, this problem did not appears before, cause laravel have a preference to dblib.
This problem is too hard to find, and I hope that all analysis helps you, who is reading until this line.
Thx!
;)

Related

Should one use FreeTDS driver instead of MS SQL Driver for compatibility between older PHP and newer SQL Servers?

I was struggling to connect my Drupal (7.43) application (hosted on a PHP 5.4 server) to a Microsoft Azure SQL database.
I got really depressed and even found myself arguing with my company's DBA for why did you install this database on the newest version of SQL Server?.
Edited:
The reason why I asked that was because of Microsoft official documentation which says one should not connect to newer versions of SQL Servers if PHP server version is under 7.*.
System Requirements for the Microsoft Drivers for PHP for SQL Server
https://learn.microsoft.com/en-us/sql/connect/php/system-requirements-for-the-php-sql-driver?view=sql-server-ver15#driver-versions
According to this article, if PHP server version is 5.4, the official MS driver for such php server is 3.2 version. Therefore, if the SQL Server driver is 3.2, it should not connect to SQL Server version higher than 2014.
TL; DR;
I used FreeTDS to connect 5.4 PHP application to Azure SQL Server! Yaay
FreeTDS is re-implementation of C libraries originally marketed by Sybase and Microsoft SQL Server. It allows many open source applications such as Perl and PHP (or your own C or C++ program) to connect to Sybase or Microsoft SQL Server.
My operational system is CentOS 7.
I installed basic yum packages for http server and php database connection.
yum install httpd httpd-tools php php-common php-cli php-odbc php-pdo unixODBC unixODBC-devel
So far I understand:
PDO stands for PHP Data Objects.
ODBC stands for Open Database Connectivity -- which is a standard application programming interface for accessing database management systems.
Alright, I then installed FreeTDS:
yum install epel-release
yum check-update
yum install freetds freetds-devel
Then I had /etc/freetds.conf:
[MYCLIENT]
host = myclient.database.edtech.com
port = 6669
tds version = 8.0 # Btw, how important is this version for old PHP servers versus new SQL servers?
I also had /etc/odbcinst.ini
[FreeTDS]
Driver = /lib64/libtdsodbc.so.0
FileUsage = 1
Furthermore, I had /etc/odbc.ini:
[MSSQLServer]
Driver = FreeTDS # Yes, ODBC will use FreeTDS, I get it.
Description = MSSQL Server
Trace = Yes
Server = myclient.database.edtech.com
Port = 6669
TDS_Version = 7.1 # Shouldn't this be same as the version in /etc/freetds.conf?
Database = ApplicationDB
Conclusions
I hope this question helps others.
FreeTDS is a different driver
than Microsoft's.
PHP does not know about FreeTDS not FreeTDS knows
about PHP version.
As far as I understood from the answers, there is
a ODBC bridge/layer in between them.
Better use the newest FreeTDS
version to make sure the connection works.
You said
The reason why I asked that was because of Microsoft official documentation which says I cannot connect to newer versions of SQL Server if my PHP version is below 7.*.
and
Is this php 5.4 connection really supposed to work with newest SQL
Server despite the official Microsoft docs say it should not?
...but actually, the Microsoft documentation you're talking about doesn't say you can't connect to SQL Server from PHP 5.4.
They said you can't (or at least you are not supported to) do that by using the Microsoft Drivers for PHP for SQL Server - which is the specific product that documentation is talking about.
FreeTDS is a different driver. By replacing the driver, you've replaced the thing which Microsoft is saying you shouldn't use. AFAIK Microsoft have no involvement with FreeTDS, so what they support, and what their driver works with, is entirely up to them.

configure pdo_dblib - freetds already installed

I am running a Linux server that already has freetds installed, but is not configured to support dblib. Only sqlite and mysql are currently supported for PDO. MSSQL support is also enabled.
If I want to add support for dblib and enable the PDO Driver for FreeTDS/Sybase DB-lib, do I just need to run this command on the existing install:
./configure --with-pdo-dblib
If so, from which directory would I run the command?
Environment:
PHP Version 5.5.38
CENTOS 6.9
Thank you
If you have configured FreeTDS correctly, you should be able to connect like so:
$pdo = new PDO("dblib:host=mssql;dbname=$dbname", "$dbuser","$dbpwd");
If you can't, this answer gives more explicit instructions: Connect PHP to MSSQL via PDO ODBC
pdo_dblib is typically installed in most Linux distros when you install php-mssql (on CentOS and Ubuntu, for example). If the connect command isn't working, please rewrite your question to include the specific steps you have taken and the error output. Good luck!
Since writing this question, the support team at the company that is hosting this server installed the driver. I don't know exactly what steps they took to do it so I can not post a step by step answer as I would like. Closing this question.

PHP PDO could'nt not find driver

I'm getting error of PDO cannot find driver using PDO in environment. I'm using xamp on a Mac.
I had got to know the problem and I've installed freetds using homebrew install, and had successfully connected to the azure mssql server using below command
tsql -H 234fddfg.database.windows.net -p 1433 -U dbuser -P db123!
but I don't know what to do next.
I've tried below php code but I'm still getting the same error.
$dbh = new PDO("sqlsrv:Server=localhost;Database=mydb", "dbuser", "db123");
Driver for Microsoft SQL Server for PHP is needed to be installed for this.
Follow this link:
https://www.microsoft.com/en-in/download/details.aspx?id=20098
Perform the following steps to download and install the Microsoft Drivers for PHP for SQL Server (example below for 3.2 version):
1. Download SQLSRV32.EXE to a temporary directory
2. Run SQLSRV32.EXE
3. When prompted, enter the path to the PHP extensions directory
4. After extracting the files, read the Installation section of the SQLSRV32_Readme.htm file for next steps
Now just add the following line to your PHP.ini (this is for the non-thread safe version of PHP, which you are most likely using when you have installed PHP to use IIS FastCGI, which we recommend):
extension=php_sqlsrv.dll
And Restart server
Have you installed PDO_DBLIB, it seems that in OSX, we need to leverage PDO_DBLIB as the pdo driver connecting to MS SQL, e.g.
$pdo = new PDO("dblib:host=$dbhost;dbname=$dbname", "$dbuser","$dbpwd");
you can refer to Configure PHP environment on Mac to connect to SQL Server using PDO interface for more information.

sqlsrv drivers doesn't appear on a WAMP server phphinfo() after adding the extension entries in the php.ini file

I wanted to setup a database connection from PHP to SQL server 2012.I have a wamp server(64 bit) set up on a windows machine(64 bit) with PHP 5.5.12 and on the same machine I have SQL server 2012 installed.
Extracted sqlsrv drivers from official_link
Copied the extracted drivers php_sqlsrv_55_ts.dll, extension = php_pdo_sqlsrv_55_ts.dll to php\ext folder, and then changed the php.ini file to include the extensions
extension = php_sqlsrv_55_ts.dll; extension = php_pdo_sqlsrv_55_ts.dll;
Now I tried
<?php
phpinfo();
?>
I see the following information without any SQL server information in it.
Don't seem to have configured SQL server connection successfully. Could some one please guide me on what I am missing here.
64 bit WAMP server was not able to connect using the drivers extension = php_sqlsrv_55_ts.dll; extension = php_pdo_sqlsrv_55_ts.dll;
So, I installed a 32 bit version of the WAMP server and it works fine now.
Check the php error log (c:\wamp\logs\php_error.log).
I had the same setup (64bit WAMP/PHP 5.5.12) and same missing sqlsrv reference in phpinfo and I got this error in my log:
PHP Warning: PHP Startup: Unable to load dynamic library
'c:/wamp/bin/php/php5.5.12/ext/php_pdo_sqlsrv_55_ts.dll' - %1 is not a
valid Win32 application. in Unknown on line 0
The solution was to install the 64bit version of the sqlsrv drivers. I found the unofficial 64bit drivers through http://robsphp.blogspot.nl/2012/06/unofficial-microsoft-sql-server-driver.html
Warning: In my testing I found these 64bit PHP_PDO_SQLSRV extension 10 times slower than when using PHP_PDO_ODBC.
I am visiting this thread and i think this might help full for you and other with the same issue:
How can I install pdo_sqlsrv on my windows 2008 Server 2008 R2?
The PDO Extension is not the same as the native driver Microsoft is offering. For PDO you must enable
extension=php_pdo_mssql.dll
in your php.ini.
{Normally this file (php_pdo_mssql.dll) should be in your PHP extension-directory (C:...\php\ext). If it's not there you can download PHP from http://windows.php.net/download/ and just take the extension from a package there (take one that correspond with your PHP version of course)}.
Above is taken from PDO MSSQL Server - Driver not found
read for more details. i have the same issue foe linux and i have saved all the pages thats why i am quoting for you help.
if all above didn't work for you then:
On the php.net it is listed that
On Windows, PDO_ODBC is built into the PHP core by default. It is linked against the Windows ODBC Driver Manager so that PHP can connect to any database cataloged as a System DSN, and is the recommended driver for connecting to Microsoft SQL Server databases.
http://php.net/manual/en/ref.pdo-odbc.php
You can connect to mssql server using odbc drivers as i have never connect by my self from windows i use to do it through linux using freeTds, following pages might help you
http://craigballinger.com/blog/2011/08/usin-php-5-3-with-mssql-pdo-on-windows/
Connect PHP to MSSQL via PDO ODBC
PHP to SQL Server without ODBC or MSSQL support

Cannot connect to MSSQL 2008 db from php using odbc and freetds

I have been searching everywhere for solutions, but am getting more and more confused.
I am trying to connect to a SQL Server 2008 db from php using FreeTDS. The server is a MediaTemple DV 4.0 and it is running CentOS 5.7. I have a version of FreeTDS (v0.91) installed that I think I might have compiled several months back. When I run tsql -C it says my freetds.conf is in /usr/local/etc and a TDS version 5.0. I need it to be TDS version 7.0, but when I change that conf file, it does not change. And I can't find the conf file it is using. (problem 1)
I can connect to my db using tsql -H -p -U and run a query. However in my php file, I get IM002 error which I believe is a connection error to the db. I use odbc_connect for that. (problem 2, the biggest problem)
I don't even know where to start, as I have been installing, uninstalling for about the last 2 months...
I would welcome any suggestion on how to resolve the issue. As a side note, it used to work before I upgraded my DV at MediaTemple.
Thanks!
Shawn
Here is my tsql -C
Compile-time settings (established with the "configure" script)
Version: freetds v0.91
freetds.conf directory: /usr/local/etc
MS db-lib source compatibility: no
Sybase binary compatibility: no
Thread safety: yes
iconv library: yes
TDS version: 5.0
iODBC: no
unixodbc: yes
SSPI "trusted" logins: no
Kerberos: no
SQL Server 2008 actually wants TDS Version 7.3 -- not 7.0, which corresponds to SQL Server 7.
I can't provide assistance with FreeTDS debugging, but you might try a commercial driver where there's some incentive to fix problems, like my employer's offering. It's free to test for 2 weeks.
We also provide some docs on using PHP with ODBC, on the iODBC.org site.
Verify that debugging is turned on in your odbcinst.ini and that errors are sent to the defined logfile.
Try to connect and run a query using the iSQL tool and check your debug log for errors. The tool comes with the unixODBC package and uses your DSN to connect to your database.
You might also want to take a look at this page: Sometimes isql doesn't connect and tsql does

Categories